Pygame停止光事件

时间:2014-02-19 17:50:02

标签: python events python-3.x event-handling pygame

我正在尝试在实验#8中为Program Arcade Games Book创建最后一个示例。

我想要实现的最后一件事是一个根据三个事件和计时器改变颜色的红绿灯。

我知道我必须在某一时刻使用pygame.time.set_timer(),但我还没有接触到Pygame中的事件处理。我不知道如何制作三个独立的事件,将每个相应的交通灯变成鲜艳的颜色。

这是我到目前为止所做的,如果省略258行到266,动画就可以使用Pygame和Python 3(我尝试连接“事件”但它只是不工作很明显)。

这是一个修订版本,我尝试使用计时器来改变颜色,而不是制作单独的事件,但它在这种情况下也不起作用;(

import random
import math

# Requirements:

# Modify the prior Create-a-Picture lab, or start a new one.

# Animate the image. Try one or more of the following:

    # Move an item across the screen.
    # Move an item back and forth.
    # Move up/down/diagonally.
    # Move in circles.
    # Have a person wave his/her arms.
    # Create a stoplight that changes colors.

# import statement
import pygame

# Define colors:
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
DULLRED = (153, 50, 51)
GREEN = (0, 255, 0)
DULLGREEN = (55, 154, 54)
BLUE = (0, 0, 255)
LIGHTBLUE = (103, 255, 246)
YELLOW = (252, 255, 31)
DULLYELLOW = (156, 157, 50)

# initialize pygame:
pygame.init()

# screen:
size = (700, 500)
screen = pygame.display.set_mode(size)

# Set the caption:
pygame.display.set_caption("Chapter 8 Lab")

# Clock:
clock = pygame.time.Clock()

# FPS:
FPS = 60

# boolean variable for game:
done = False

# For loop for white circles:
whiteCircleList = []

for i in range(25):
    x = random.randrange(0, 700)
    y = random.randrange(0, 50)
    whiteCircleList.append([x,y])

# For Loop for Blue Circles:
blueCircleList = []

for i in range(100):
    circleX = random.randrange(0, 500)
    circleY = random.randrange(0, 700)
    blueCircleList.append([circleX, circleY])

# Light Blue Circle For Loop:
lightBlueCircleList = []

for i in range(100):
    circleX = random.randrange(0, 500)
    circleY = random.randrange(0, 700)
    lightBlueCircleList.append([circleX, circleY])

# Surfboard's Rectangle (x-pos, y-pos, x-length, y-length):
surfboardRect = pygame.Rect(325, 225, 50, 150)
boardY = 255.
rectYChange = -5
phase = 0

# Diagonal Rectangle in Top Left Corner:
topLeftDiagonalRect = pygame.Rect(0, 0, 10, 10)

# Diagonal Rectangle in Top Right Corner:
topRightDiagonalRect = pygame.Rect(500, 1, 10, 10)

# Diagonal Rectangle Vectors for Top Left Rectangle:
topLeftDiagonalRectXChange = 5
topLeftDiagonalRectYChange = 5

# Diagonal Rectangle Vectors for Top Right Rectangle:
topRightDiagonalRectXChange = -5
topRightDiagonalRectYChange = -5

# Angle for Hand Rotation
handAngle = 0

# Variable for Traffic Light Cover:
currentTopColor = DULLRED

currentMiddleColor = DULLYELLOW

currentBottomColor = GREEN

while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    # Game Logic:
    phase += 1

    if phase > 180:
        phase = phase * -1

    # Save exact position as a float to avoid floating point errors:
    boardY += math.cos(math.radians(phase))*2

    surfboardRect.y = int(boardY)

    # Clear the screen:
    screen.fill(RED)

    # Drawing Code:

    # Falling Down circles:
    for i in range(len(whiteCircleList)):
        pygame.draw.circle(screen, WHITE, [whiteCircleList[i][0], whiteCircleList[i][1]], 3)
        whiteCircleList[i][1] += 5
        # If the rectangles have hit the bottom of the screen, make them appear 10 pixels above the top:
        if whiteCircleList[i][1] > 450:
            x = random.randrange(0, 700)
            whiteCircleList[i][0] = x
            y = random.randrange(-50, -10)
            whiteCircleList[i][1] = y

    # Red Falling Up Circles:
    for i in range(len(blueCircleList)):
        pygame.draw.circle(screen, BLUE, [blueCircleList[i][0], blueCircleList[i][1]], 5, 5)
        blueCircleList[i][1] -= 5
        if blueCircleList[i][1] < 50:
            circleX = random.randrange(0,700)
            circleY = random.randrange(400, 500)
            blueCircleList[i][0] = circleX
            blueCircleList[i][1] = circleY

    # Light Blue Falling Up Circles:
    for i in range(len(lightBlueCircleList)):
        pygame.draw.circle(screen, LIGHTBLUE, [lightBlueCircleList[i][0], lightBlueCircleList[i][1]], 3, 3)
        lightBlueCircleList[i][1] -= 5
        if lightBlueCircleList[i][1] < 50:
            circleX = random.randrange(0, 700)
            circleY = random.randrange(400, 450)
            lightBlueCircleList[i][0] = circleX
            lightBlueCircleList[i][1] = circleY

    # Revised Surfboard Rectangle Code:
    pygame.draw.rect(screen, BLACK, surfboardRect, 0)

    # Top Left Diagonal Rectangle Code:
    pygame.draw.rect(screen, BLACK, topLeftDiagonalRect, 0)

    # Add The Top Left Diagonal Rectangle Change Vectors
    topLeftDiagonalRect.x += topLeftDiagonalRectXChange
    topLeftDiagonalRect.y += topLeftDiagonalRectYChange

    # Top and Bottom Screen Collision:
    if topLeftDiagonalRect.y >= 500 or topLeftDiagonalRect.y <= 0:
        topLeftDiagonalRectYChange = topLeftDiagonalRectYChange * -1

    # Left and Right Screen Collision:
    if topLeftDiagonalRect.x <= 0 or topLeftDiagonalRect.x >= 700:
        topLeftDiagonalRectXChange = topLeftDiagonalRectXChange * -1

    # Draw the top right rectangle:
    pygame.draw.rect(screen, BLACK, topRightDiagonalRect, 0)

    # Add the change vectors for the Top Right Rectangle:
    topRightDiagonalRect.x += topRightDiagonalRectXChange
    topRightDiagonalRect.y += topRightDiagonalRectYChange

    # Top and Bottom Screen Collision:
    if topRightDiagonalRect.y <= 0 or topRightDiagonalRect.y >= 500:
        topRightDiagonalRectYChange = topRightDiagonalRectYChange * -1

    # Left and Right Screen Collision:
    if topRightDiagonalRect.x <= 0 or topRightDiagonalRect.x >= 700:
        topRightDiagonalRectXChange = topRightDiagonalRectXChange * -1

    # Person Waving His Arms:
    # Head:
    pygame.draw.circle(screen, WHITE, [575, 300], 15)

    # Body:
    pygame.draw.rect(screen, BLUE, [560, 315, 30, 60], 0)

    # Left Rotating Hand:
    # Left Hand's Original Dimensions:
    # pygame.draw.line(screen, WHITE, [560, 315], [540, 295], 5)

    # Original Hand's x position based on the rotating circle idea:
    # handX = 40 * math.sin(handAngle) + 560

    # Original Hand's y position based on the rotating circle idea:
    # handY = 40 * math.cos(handAngle) + 315
    handPosition = (40 * math.sin(handAngle) + 560, 40 * math.cos(handAngle) + 315)

    pygame.draw.line(screen, WHITE, [560, 315], handPosition, 4)

    # Increase the hand angle by 0.05 Radians:
    handAngle = handAngle + 0.05

    # Reset the angle after a full sweep:
    pi = 3.141592653

    if handAngle > 2 * pi:
        handAngle = handAngle - 2*pi

    # Right Immobile Hand:
    pygame.draw.line(screen, WHITE, [590, 315], [590, 340], 4)

    # Left Leg:
    pygame.draw.rect(screen, WHITE, [560, 375, 10, 20], 0)

    # Right Leg:
    pygame.draw.rect(screen, WHITE, [580, 375, 10, 20], 0)

    # Left Shoe Ellipse
    # Ellipse Notes: ellipse(Surface, color, Rect, width=0) -> Rect
    pygame.draw.ellipse(screen, BLACK, [550, 390, 20, 15], 0)

    # Right Shoe Ellipse:
    pygame.draw.ellipse(screen, BLACK, [580, 390, 20, 15], 0)

    # Add in a changing traffic light
    # Rectangle for Traffic Light:
    pygame.draw.rect(screen, WHITE, [50, 350, 50, 100], 0)

    # Traffic Light Post:
    pygame.draw.rect(screen,BLACK, [65, 450, 20, 40], 0)

    # Top light:
    pygame.draw.circle(screen, currentTopColor, [75, 370], 12)

    # Second light:
    pygame.draw.circle(screen, currentMiddleColor, [75, 400], 12)

    # Third light:
    pygame.draw.circle(screen, currentBottomColor, [75, 430], 12)

    # Three events must be cycled to change each of the traffic light colors
    # from their dull versions to their fullest color forms

    # The question is, can this be achieved through a timer?

    # 60 frames per second is on the timer itself so every 180 frames would mean
    # 3 seconds, or every 300 frames would mean 5 seconds

    # DOCS on set timer: set_timer(eventid, milliseconds)

##    turnRedLightOn = pygame.draw.circle(screen, RED, [75, 370], 12)
##                   + pygame.draw.circle(screen, DULLYELLOW, [75, 400], 12)
##                   + pygame.draw.circle(screen, DULLGREEN, [75, 430], 12)

    # Turn the top light red and all other lights dull every three seconds
    pygame.time.set_timer(currentTopColor = RED, 3000)
    pygame.time.set_timer(currentMiddleColor = DULLYELLOW, 3000)
    pygame.time.set_timer(currentBottomColor = DULLGREEN, 3000)

    # Turn the middle light yellow and all other lights dull every six seconds
    pygame.time.set_timer(currentTopColor = DULLRED, 6000)
    pygame.time.set_timer(currentMiddleColor = YELLOW, 6000)
    pygame.time.set_timer(currentBottomColor = DULLGREEN, 6000)

    # Turn the bottom light green and all other lights dull every nine seconds
    pygame.time.set_timer(currentTopColor = DULLRED, 9000)
    pygame.time.set_timer(currentMiddleColor = DULLYELLOW, 9000)
    pygame.time.set_timer(currentBottomColor = GREEN, 9000)


    # Update the screen:
    pygame.display.flip()

    # Clock FPS:
    clock.tick(FPS)

# Quit after main game loop ends:
pygame.quit()

1 个答案:

答案 0 :(得分:1)

set_timer不应该在主循环的每个循环中执行,你可以在外面调用它,它会每3000ms重复一次。

# Current Light
light_on = 0  # 0-red 1-yellow 2-green

LIGHTS_EVENT = pygame.USERVENT + 0   # Event code for Lights change
pygame.time.set_timer(LIGHTS_EVENT, 3000)

while not done:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

        if event.type == LIGHTS_EVENT:
            light_on += 1
            if light_on == 3:
                light_on = 0


    currentTopColor = DULLRED
    currentMiddleColor = DULLYELLOW
    currentBottomColor = DULLGREEN
    if light_on == 0:
        currentTopColor = RED
    if light_on == 1:
        currentMiddleColor = YELLOW
    if light_on == 2:
        currentBottomColor = GREEN

    # Top light:
    ...