我正在pygame上编写自己的框架,并添加了一些运动和碰撞的功能。框架看起来像这样:
import pygame
def check_collisions(obj1, objects):
collisions = []
for obj in objects:
if obj.colliderect(obj1):
collisions.append(obj)
return collisions
def blit_center(surface, object, display):
display.blit(surface, [object.x/surface.get_width(), object.y/surface.get_height()])
class PhysicsObject(object):
def __init__(self, x, y, width, height, vel_x=0, vel_y=0):
self.width = width
self.height = height
self.x = x
self.y = y
self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
self.velocity = pygame.Vector2(vel_x, vel_y)
def move(self, environment):
collisions = {
'top': False,
'bottom': False,
'left': False,
'right': False,
}
self.x += self.velocity.x
self.rect.x = int(self.x)
collisions_checked = check_collisions(self.rect, environment)
for obj in collisions_checked:
if self.velocity.x > 0:
self.rect.right = obj.left
collisions['right'] = True
elif self.velocity.x < 0:
self.rect.left = obj.right
collisions['left'] = True
self.y += self.velocity.y
self.rect.y = int(self.y)
collisions_checked = check_collisions(self.rect, environment)
for obj in collisions_checked:
if self.velocity.y > 0:
self.rect.bottom = obj.top
collisions['bottom'] = True
elif self.velocity.y < 0:
self.rect.top = obj.bottom
collisions['top'] = True
return collisions
class Entity(PhysicsObject):
def __init__(self, x, y, width, height, vel_x=0, vel_y=0):
super().__init__(x, y, width, height, vel_x, vel_y)
self.surf = pygame.Surface((self.width, self.height))
self.surf.fill('red')
self.colorkey = (0, 0, 0)
self.surf.set_colorkey(self.colorkey)
def set_image(self, image):
if image is str:
self.surf = pygame.image.load(image)
else:
self.surf = image
def set_color(self, color):
self.surf.fill(color)
def set_size(self, width=None, height=None):
if width is not None:
self.width = int(width)
if height is not None:
self.height = int(height)
def display(self, display):
display.blit(self.surf, [self.x-self.width/2, self.y-self.height/2])
现在在我的测试文件中,我想测试这个功能,但当我移动我的播放器到障碍,它没有停止。它只是穿过它。为什么会这样?我怎样才能解决这个问题呢?
也是我的测试脚本看起来像这样:
import pygame
from pygame.locals import *
import sys
from gameFrame import *
pygame.init()
display_size = [500, 500]
display = pygame.display.set_mode(display_size)
clock = pygame.time.Clock()
player = Entity(32, 32, 32, 32)
obstacle = Entity(200, 200, 200, 32)
while True: # Main gameloop
for event in pygame.event.get():
if event.type == pygame.QUIT: # Prevent frozen program
pygame.quit()
sys.exit()
display.fill([70, 120, 255]) # Make Background
keys = pygame.key.get_pressed()
player.velocity.xy = 0, 0
if keys[K_w]:
player.velocity.y = -5
if keys[K_s]:
player.velocity.y = 5
if keys[K_a]:
player.velocity.x = -5
if keys[K_d]:
player.velocity.x = 5
player.display(display)
obstacle.display(display)
player.move([obstacle.rect])
pygame.display.update() # Update the display
clock.tick(60)
仅仅约束矩形(self.rect.bottom
,self.rect.left
)的位置是不够的。如果你改变了self.rect.bottom
或self.rect.left
,你必须同时设置self.x
,因为self.rect.x
在下一帧由self.x
再次设置:
class PhysicsObject(object):
# [...]
def move(self, environment):
collisions = {'top': False, 'bottom': False, 'left': False, 'right': False,}
self.x += self.velocity.x
self.rect.x = int(self.x)
collisions_checked = check_collisions(self.rect, environment)
for obj in collisions_checked:
if self.velocity.x > 0:
self.rect.right = obj.left
self.x = self.rect.x # <---
collisions['right'] = True
elif self.velocity.x < 0:
self.rect.left = obj.right
self.x = self.rect.x # <---
collisions['left'] = True
self.y += self.velocity.y
self.rect.y = int(self.y)
collisions_checked = check_collisions(self.rect, environment)
for obj in collisions_checked:
if self.velocity.y > 0:
self.rect.bottom = obj.top
self.y = self.rect.y # <---
collisions['bottom'] = True
elif self.velocity.y < 0:
self.rect.top = obj.bottom
self.y = self.rect.y # <---
collisions['top'] = True
return collisions