精灵没有正确对齐边界

时间:2014-12-25 21:43:02

标签: python-2.7 pygame collision-detection sprite rect

我正在使用Pygame创建一个基本的乒乓式游戏,而且我已经移动了桨。我的代码可以防止拨片移动超出屏幕边缘,但如果玩家按住一个移动键,则拨片稍微移动到屏幕边缘。一旦玩家释放钥匙,桨就会快速回到它应该停止的位置。

我对Python和编码有点新手,所以我的代码可能不是最整洁或最有效的。虽然这个问题可能根本不会影响游戏玩法,但我想知道它为什么会这样,以及如何将其改变为我想要的方式。

我的代码是:

import random
import pygame
from pygame.locals import *
from sys import exit

screen_size = 600, 600
w,h = screen_size
screen = pygame.display.set_mode(screen_size)
clock = pygame.time.Clock()
pic = pygame.image.load

class paddle(pygame.sprite.Sprite):
    def __init__(self, pos):
        pygame.sprite.Sprite.__init__(self)

        self.pos = pos
        self.posx, self.posy = self.pos
        self.width = 10
        self.height = 100
        self.image = pygame.Surface((self.width, self.height))
        self.image.fill((255,255,255))
        self.rect = pygame.Rect((0,0), self.image.get_size())
        self.speed = 150

    def update(self, mov, tp):
        self.posy += mov * self.speed * tp
        self.rect.center = self.posx, self.posy

class box(pygame.sprite.Sprite):
    def __init__(self, pos):
        pygame.sprite.Sprite.__init__(self)

        self.pos = pos
        self.posx, self.posy = self.pos
        self.width = 10
        self.height = 10
        self.image = pygame.Surface((self.width, self.height))
        self.image.fill((255,255,255))
        self.rect = pygame.Rect((0,0), self.image.get_size())
        self.speed = 300        

        self.directionx = 0
        self.directiony = 0

    def update(self, mov, tp):
        self.posx += mov[0] * self.speed * tp
        self.posy += mov[1] * self.speed * tp
        self.rect.center = self.posx, self.posy

reset = True

done = False
while done == False:

    if reset == True:
        p1 = paddle((0,0))
        p1 = paddle((20,(h-p1.height)/2))
        p2 = paddle((0,0))
        p2 = paddle((w-20,(h-p2.height)/2))
        paddle_group = pygame.sprite.Group()
        paddle_group.add(p1)
        paddle_group.add(p2)

        ball = box(((w/2)-10,h/2))
        ball_group = pygame.sprite.Group(ball)

        reset = False
    else:
        pass

    time_passed = clock.tick(60)
    time_passed_seconds = time_passed/1000.0

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

    p1_movey = 0
    p2_movey = 0

    pressed_keys = pygame.key.get_pressed()
    pressed_mb = pygame.mouse.get_pressed()

    if pressed_keys[K_ESCAPE]:
        done = True

    if pressed_keys[K_w]:
        p1_movey = -2
    elif pressed_keys[K_s]:
        p1_movey = +2

    if pressed_keys[K_UP]:
        p2_movey = -2
    elif pressed_keys[K_DOWN]:
        p2_movey = +2

    p1.update(p1_movey, time_passed_seconds)
    p2.update(p2_movey, time_passed_seconds)


# This is where the border check is
    for PADDLE in paddle_group.sprites():

        if PADDLE.posy > h - (PADDLE.height/2):
            PADDLE.posy = h - (PADDLE.height/2)
        elif PADDLE.posy < (PADDLE.height/2):
            PADDLE.posy = (PADDLE.height/2)

    screen.fill((0,0,0))

    paddle_group.draw(screen)

    pygame.display.update()

pygame.quit()

边界部分标有注释。

1 个答案:

答案 0 :(得分:0)

问题是,您需要在不同时调整paddle的情况下更正每个posy rect posxposy存储精灵的位置 - 在这种情况下,它是中心 - 但您在屏幕上看到的位置由rect确定。因为您添加p#_movey,然后update(调整矩形),最后,对越界值进行posy更正,rect保留在其中#39;无效的位置。但是,因为已经调整了posy,所以未来的p#_movey更改会影响正确的位置,而不是无效的位置(这就是为什么您的精灵在发布移动键之前仍保持OB的原因)

简而言之,这就是:

  1. 为每位玩家确定p#_movey。
  2. 通过posy将p#_movey应用于播放器#{1}}和rect
  3. 调整update以保持每个PADDLE.posy的入口,但不要更新PADDLE in paddle_group以反映调整。 (PADDLE.rect确实需要更新。)
  4. 结束框架。

  5. 我能想到两种解决方案:

    1)修改您的rect循环,以便刷新for PADDLE in paddle_group.sprites(),它看起来像这样:

    PADDLE.rect.center

    2)或者,您可以在 # on the main loop... for PADDLE in paddle_group.sprites(): if PADDLE.posy > h - (PADDLE.height/2): PADDLE.posy = h - (PADDLE.height/2) elif PADDLE.posy < (PADDLE.height/2): PADDLE.posy = (PADDLE.height/2) PADDLE.rect.center = PADDLE.posx, PADDLE.posy ## ^ adding this line, which recenters the rect. 的{​​{1}}方法中运行边界检查,并从主循环中一起删除paddle循环。 update会看起来像这样:

    for PADDLE in paddle_group.sprites()

    ...只要您的边界由paddle.update(..)(屏幕高度;窗口底部)和 # in class paddle(..) ... def update(self, mov, tp): self.posy += mov * self.speed * tp self.posy = max(self.height / 2, min(self.posy, h - (self.height / 2))) ## ^ Adding this line, which checks boundaries for posy. ## because you're doing it here, there's no need to do it again on the main loop. self.rect.center = self.posx, self.posy (窗口顶部)和球拍高度定义。< / p>

    这两种解决方案都应该有效,尽管几乎肯定有第三种方法。 希望有所帮助!