在动画弹跳球时PyGame中的奇怪时间问题

时间:2015-07-16 09:45:46

标签: python pygame

我正在使用PyGame编写一个游戏,并相信所有弹跳球的代码都是一致的。然而,过了一会儿,球以不同的速度反弹。

我的代码是否有误?如果是这样,请你试着找出哪里?如果没有,发生了什么?

由于

我的代码:

"""The IMPOSIBLE GAME"""

#Library
import time
import random
import pygame
import sys
from pygame.locals import *

Cube_x = 1
Cube_y = 1
Cube_x_vel = 0
Cube_y_vel = 0

#Colour Bank
Black = (0,0,0)
White = (255,255,255)
Red = (255,0,0)
Green = (0,255,0)
Blue = (0,0,255)
Dark_Purple = (102,0,102)
Orange = (255,128,0)

#Colour List
colour_list = [Black, White, Red, Blue, Green]

#Controls
UP = 'up'
DOWN = 'down'
LEFT = 'left'
RIGHT = 'right'

#Player Variables
DEATHS = 0
LEVEL = 1
SCORE = LEVEL - 1

#Sphere Coordinates
y_s1 = 0
y_s2 = 0
y_s3 = 0
y_s4 = 0
y_s5 = 0
sphere_vel = 5

#Shapes
def draw_CUBE(screen, colour, Cube_x, Cube_y):
    pygame.draw.rect(screen, colour, [Cube_x, Cube_y, 30, 30] ,0)

def draw_SPHERE1(Screen, y_s1):
    pygame.draw.ellipse(screen, Blue, [100, y_s1, 30, 30] ,0)

def draw_SPHERE2(Screen, y_s2):
    pygame.draw.ellipse(screen, Blue, [200, y_s2, 30, 30] ,0)

def draw_SPHERE3(Screen, y_s3):
    pygame.draw.ellipse(screen, Blue, [300, y_s3, 30, 30] ,0)

def draw_SPHERE4(Screen, y_s4):
    pygame.draw.ellipse(screen, Blue, [400, y_s4, 30, 30] ,0)

def draw_SPHERE5(Screen, y_s5):
    pygame.draw.ellipse(screen, Blue, [500, y_s5, 30, 30] ,0)


pygame.init()

#Window Variables
Cell_Size = 20
screen_width = 700
screen_height = 400
screen = pygame.display.set_mode((screen_width, screen_height))

clock = pygame.time.Clock()

done = False

while not done:

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

        if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    Cube_y_vel = -3
                    print("up")
                if event.key == pygame.K_DOWN:
                    Cube_y_vel = 3
                    print("down")

        if event.type == pygame.KEYUP:
                if event.key == pygame.K_UP:
                    Cube_y_vel = 0
                    print("Key Released")
                if event.key == pygame.K_DOWN:
                    Cube_y_vel = 0
                    print("Key Released")



        if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    Cube_x_vel = 3
                    print("up")
                if event.key == pygame.K_LEFT:
                    Cube_x_vel = -3
                    print("down")

        if event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT:
                    Cube_x_vel = 0
                    print("Key Released")
                if event.key == pygame.K_LEFT:
                    Cube_x_vel = 0
                    print("Key Released")


    Cube_y = Cube_y + Cube_y_vel
    Cube_x = Cube_x + Cube_x_vel

    y_s1 = y_s1 + sphere_vel
    if y_s1 > 370:
        sphere_vel = sphere_vel * -1
    if y_s1 < 0:
        sphere_vel = sphere_vel * -1

    y_s2 = y_s2 + sphere_vel
    if y_s2 > 370:
        sphere_vel = sphere_vel * -1
    if y_s2 < 0:
        sphere_vel = sphere_vel * -1

    y_s3 = y_s3 + sphere_vel
    if y_s3 > 370:
        sphere_vel = sphere_vel * -1
    if y_s3 < 0:
        sphere_vel = sphere_vel * -1

    y_s4 = y_s4 + sphere_vel
    if y_s4 > 370:
        sphere_vel = sphere_vel * -1
    if y_s4 < 0:
        sphere_vel = sphere_vel * -1

    y_s5 = y_s5 + sphere_vel
    if y_s5 > 370:
        sphere_vel = sphere_vel * -1
    if y_s5 < 0:
        sphere_vel = sphere_vel * -1
    screen.fill((255,255,255))

    colour = random.choice(colour_list)

    draw_CUBE(screen, colour, Cube_x, Cube_y)

    draw_SPHERE1(screen, y_s1)

    draw_SPHERE2(screen, y_s2)

    draw_SPHERE3(screen, y_s3)

    draw_SPHERE4(screen, y_s4)

    draw_SPHERE5(screen, y_s5)

    pygame.draw.rect(screen, Green, [90, 400, 100, 100] , 0)

    pygame.display.flip()

    clock.tick(60)

pygame.quit

2 个答案:

答案 0 :(得分:4)

看看y_s1成为&gt;时会发生什么? 370

y_s1 = y_s1 + sphere_vel          # 1
if y_s1 > 370:
    sphere_vel = sphere_vel * -1  # 2
if y_s1 < 0:
    sphere_vel = sphere_vel * -1

y_s2 = y_s2 + sphere_vel          # 3
if y_s2 > 370:
    sphere_vel = sphere_vel * -1
if y_s2 < 0:
    sphere_vel = sphere_vel * -1  # 4

y_s1变为375(#1)时,您将sphere_vel5更改为-5(#2),因此在第3行更改y_y2370365

所以现在y_s1总是与y_s2ys_3ys_4ys_5分开10。

圈子向下移动,y_s2在某个时间变为-5(因为10小于y_s1)。

因此第4行再次更改sphere_vel的符号,因此y_s3ys_4ys_50更改为5

现在只有y_s210关闭了,这就是你所看到的。

我建议您使用pygame的SpriteRect课程来简化您的生活。

这是一个简单的例子,请注意评论:

# The IMPOSIBLE GAME

import random
import pygame
from pygame.color import Color
from pygame.surface import Surface
from pygame.sprite import Sprite, Group

pygame.init()

# note how pygame defines a lot of colors already for you
colour_list = [Color('Black'), Color('White'), Color('Red'), Color('Blue'), Color('Green')]

# we use a dict to keep a simple 'What Key Moves In Which Direction'-map
keys = {pygame.K_UP:    ( 0, -3),
        pygame.K_DOWN:  ( 0,  3),
        pygame.K_LEFT:  (-3,  0),
        pygame.K_RIGHT: ( 3,  0)}

# using sprites will make your live easy
# e.g. you don't need to handle drawing yourself
class Player(Sprite):
    def __init__(self):
        Sprite.__init__(self)

        # we create a simple rectangular surface
        self.image = Surface((30, 30))
        self.rect = self.image.get_rect()
        self.image.fill(Color('Black'))

        # we set a colorkey so we can create a mask
        # this mask is used for pixel perfect collision
        # which will come in handy not only for circles
        # but if you extend your game to other shape
        self.image.set_colorkey(Color('Purple'))
        self.mask = pygame.mask.from_surface(self.image)
        self.deaths = 0

    def update(self):
        # use a random color from the list
        self.image.fill(random.choice(colour_list))

        # check which keys are pressed
        pressed = pygame.key.get_pressed()
        for key, movement in keys.iteritems():
            if pressed[key]:
                # and move our rect in that direction
                # note how we don't need extra variables
                # the rect is enough
                self.rect.move_ip(movement)

        # we use the clamp_ip function to ensure your rect 
        # does not get out of screeen.
        self.rect.clamp_ip(pygame.display.get_surface().get_rect())

        # check if we collide with any object in the objects group
        # we use pygame.sprite.collide_mask to have a pixel perfect
        # collision detection
        # objects is a global variable, which may bother, but we could
        # simply pass it through the update function instead
        if pygame.sprite.spritecollide(self, objects, False, pygame.sprite.collide_mask):
            self.deaths += 1
            self.rect.topleft = (0, 0)

class Circle(Sprite):
    def __init__(self, start_x, speed):
        Sprite.__init__(self)
        # same as the in the Player class
        # we create a simple Surface
        self.image = Surface((30, 30))
        self.rect = self.image.get_rect(x=start_x, y=100)
        self.image.fill(Color('Purple'))
        self.image.set_colorkey(Color('Purple'))
        pygame.draw.ellipse(self.image, Color('Blue'), (0, 0, 30, 30), 0)
        self.mask = pygame.mask.from_surface(self.image)
        self.y_vel = speed

    def update(self):
        # we create a rect which will tell us
        # were we would move
        target = self.rect.move(0, self.y_vel)

        # and if we would go out of screen
        if not pygame.display.get_surface().get_rect().contains(target):
            # we simply change direction
            self.y_vel *= -1

        # then acutally move
        self.rect.move_ip(0, self.y_vel)

screen = pygame.display.set_mode((700, 400))
clock = pygame.time.Clock()
done = False

# When creating the circles, we can specify the start position and speed
objects = Group((Circle(x+100, 5) for x in xrange(0, 500, 100)))

# use a Group to handle updating and drawing
all_group = Group(*objects)
all_group.add(Player())

# your main loop is as easy as this
while not done:

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

    all_group.update()

    screen.fill(Color('White'))
    all_group.draw(screen)
    pygame.display.flip()

    clock.tick(60)

pygame.quit()

enter image description here

答案 1 :(得分:0)

原因似乎是两件事。首先是因为你在检查它们是否仍然在屏幕上之前移动球,并且因为你的代码会产生一些时间问题。

我会通过在移动球之前检查并在for循环中一次性绘制球来解决这个问题。

示例:

#Sphere Coordinates
ylist = [0, 0, 0, 0, 0]
sphere_vel = 5

#Shapes
def draw_SPHERE(Screen, x, y):
    pygame.draw.ellipse(screen, Blue, [x, y, 30, 30] ,0)

pygame.init()

done = False

while not done:

    screen.fill((255,255,255))
    for y in range(len(ylist)):
        if ylist[y] + sphere_vel > 370 or ylist[y] + sphere_vel < 0:
            sphere_vel = sphere_vel * -1
        ylist[y] = ylist[y] + sphere_vel
        draw_SPHERE(screen, (y+1) * 100, ylist[y])

    pygame.display.flip()

    clock.tick(60)