好吧,我有一个实体在两个位置之间来回走动,现在是如下所示的像素位置:
if self.rect.left == 96:
self.right_dis = False
if self.rect.right == 480:
self.right_dis = True
if not self.right_dis:
self.xVel = 2
if self.right_dis:
self.xVel = -2
我的问题是,有没有办法指定它在平台上移动直到到达平台末端然后掉头?这样它就可以来回移动,而无需我指定哪些像素位置之间?以下是我的其余代码和视频:
import pygame
from pygame import *
WIN_WIDTH = 1120 - 320
WIN_HEIGHT = 960 - 320
HALF_WIDTH = int(WIN_WIDTH / 2)
HALF_HEIGHT = int(WIN_HEIGHT / 2)
DISPLAY = (WIN_WIDTH, WIN_HEIGHT)
DEPTH = 0
FLAGS = 0
CAMERA_SLACK = 30
def main():
global level
pygame.init()
screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
pygame.display.set_caption("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
timer = pygame.time.Clock()
level = 0
bg = Surface((32,32))
bg.convert()
bg.fill(Color("#0094FF"))
up = left = right = False
entities = pygame.sprite.Group()
player = Player(32, 32)
enemy = Enemy(32,32)
platforms = []
x = 0
y = 0
if level == 0:
level = [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" E ",
" PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPPP PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPP P",
" PPPP P",
" PPPP PPPPPPP",
" PPPPPPPPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPPPPP",
"PPPPP PPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPPP PPPP PPPPPPP",
"PPP PPPP",
"PPP PPPP",
"PPP PPPP",
"PPP PPPPPPPPPPPPPPPPPP",
"PPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",]
#background = pygame.image.load("Untitled.png")
total_level_width = len(level[0]) * 32
total_level_height = len(level) * 32
# build the level
for row in level:
for col in row:
if col == "P":
p = Platform(x, y)
platforms.append(p)
entities.add(p)
if col == "E":
e = ExitBlock(x, y)
platforms.append(e)
entities.add(e)
x += 32
y += 32
x = 0
camera = Camera(complex_camera, total_level_width, total_level_height)
entities.add(player)
entities.add(enemy)
while 1:
timer.tick(60)
for e in pygame.event.get():
if e.type == QUIT: raise SystemExit, "QUIT"
if e.type == KEYDOWN and e.key == K_ESCAPE:
raise SystemExit, "ESCAPE"
if e.type == KEYDOWN and e.key == K_UP:
up = True
if e.type == KEYDOWN and e.key == K_LEFT:
left = True
if e.type == KEYDOWN and e.key == K_RIGHT:
right = True
if e.type == KEYUP and e.key == K_UP:
up = False
if e.type == KEYUP and e.key == K_LEFT:
left = False
if e.type == KEYUP and e.key == K_RIGHT:
right = False
# draw background
for y in range(20):
for x in range(25):
screen.blit(bg, (x * 32, y * 32))
# draw background
#screen.blit(background, camera.apply((0,0)))
#draw entities
for e in entities:
screen.blit(e.image, camera.apply(e))
# update player, update camera, and refresh
player.update(up, left, right, platforms)
enemy.update(platforms)
camera.update(player)
pygame.display.flip()
class Camera(object):
def __init__(self, camera_func, width, height):
self.camera_func = camera_func
self.state = Rect(0, 0, width, height)
def apply(self, target):
try:
return target.rect.move(self.state.topleft)
except AttributeError:
return map(sum, zip(target, self.state.topleft))
def update(self, target):
self.state = self.camera_func(self.state, target.rect)
def complex_camera(camera, target_rect):
l, t, _, _ = target_rect
_, _, w, h = camera
l, t, _, _ = -l + HALF_WIDTH, -t +HALF_HEIGHT, w, h
l = min(0, l) # stop scrolling left
l = max(-(camera.width - WIN_WIDTH), l) # stop scrolling right
t = max(-(camera.height-WIN_HEIGHT), t) # stop scrolling bottom
return Rect(l, t, w, h)
class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
class Player(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.xvel = 0
self.yvel = 0
self.onGround = False
self.image = Surface((32,32))
self.image.fill(Color("#0000FF"))
self.image.convert()
self.rect = Rect(200, 1200, 32, 32)
def update(self, up, left, right, platforms):
if self.rect.top > 1440 or self.rect.top < 0:
main()
if self.rect.left > 1408 or self.rect.right < 0:
main()
if up:
if self.onGround:
self.yvel = 0
self.yvel -= 10 # only jump if on the ground
if left:
self.xvel = -10
if right:
self.xvel = 10
if not self.onGround:
self.yvel += 0.3 # only accelerate with gravity if in the air
if self.yvel > 80: self.yvel = 80 # max falling speed
if not(left or right):
self.xvel = 0
self.rect.left += self.xvel # increment in x direction
self.collide(self.xvel, 0, platforms) # do x-axis collisions
self.rect.top += self.yvel # increment in y direction
self.onGround = False; # assuming we're in the air
self.collide(0, self.yvel, platforms) # do y-axis collisions
def collide(self, xvel, yvel, platforms):
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if isinstance(p, ExitBlock):
pygame.event.post(pygame.event.Event(QUIT))
if xvel > 0: self.rect.right = p.rect.left
if xvel < 0: self.rect.left = p.rect.right
if yvel > 0:
self.rect.bottom = p.rect.top
self.onGround = True
if yvel < 0:
self.rect.top = p.rect.bottom
class Enemy(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.yVel = 0
self.xVel = 0
self.image = Surface((32,32))
self.image.fill(Color("#00FF00"))
self.image.convert()
self.rect = Rect(300, 1200, 32, 32)
self.onGround = False
self.right_dis = False
def update(self, platforms):
if not self.onGround:
self.yVel += 0.3
if self.rect.left == 96:
self.right_dis = False
if self.rect.right == 480:
self.right_dis = True
if not self.right_dis:
self.xVel = 2
if self.right_dis:
self.xVel = -2
self.rect.left += self.xVel # increment in x direction
self.collide(self.xVel, 0, platforms) # do x-axis collisions
self.rect.top += self.yVel # increment in y direction
self.onGround = False; # assuming we're in the air
self.collide(0, self.yVel, platforms) # do y-axis collisions
def collide(self, xVel, yVel, platforms):
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if xVel > 0: self.rect.right = p.rect.left
if xVel < 0: self.rect.left = p.rect.right
if yVel > 0:
self.rect.bottom = p.rect.top
self.onGround = True
if yVel < 0:
self.rect.top = p.rect.bottom
class Platform(Entity):
def __init__(self, x, y):
Entity.__init__(self)
#self.image = Surface([32, 32], pygame.SRCALPHA, 32) #makes blocks invisible for much better artwork
self.image = Surface((32,32)) #makes blocks visible for building levels
self.image.convert()
self.rect = Rect(x, y, 32, 32)
def update(self):
pass
class ExitBlock(Platform):
def __init__(self, x, y):
Platform.__init__(self, x, y)
self.image = pygame.image.load("end.png")
if __name__ == "__main__":
main()
最佳答案
获取实体
的矩形
。
如果向右移动,则取矩形
的右下
点,将其向右移动一个像素并向下移动一个像素,然后检查是否这样点与平台
碰撞。如果没有,您就知道它到达了平台的末端。
如果它向左移动,您只需获取左下
点并将其向左移动一个像素并向下移动一个像素。
“移动”一个点(如果它是一个Tuple
或List
)的一个简单方法是使用map-sum-zip技巧:
>>> point = (8,10)
>>> to_move = (1,1)
>>> map(sum, zip(point, to_move))
[9, 11]
>>> to_move = (-1,1)
>>> map(sum, zip(point, to_move))
[7, 11]
>>>
<小时/>
只是为了好玩,这是一个完整的示例(请注意注释):
class Enemy(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.yVel = 0
self.xVel = 2 # start moving immediately
self.image = Surface((32,32))
self.image.fill(Color("#00FF00"))
self.image.convert()
self.rect = Rect(300, 1200, 32, 32)
self.onGround = False
def update(self, platforms):
if not self.onGround:
self.yVel += 0.3
# no need for right_dis to be a member of the class,
# since we know we are moving right if self.xVel > 0
right_dis = self.xVel > 0
# create a point at our left (or right) feet
# to check if we reached the end of the platform
m = (1, 1) if right_dis else (-1, 1)
p = self.rect.bottomright if right_dis else self.rect.bottomleft
fp = map(sum, zip(m, p))
# if there's no platform in front of us, change the direction
collide = any(p for p in platforms if p.rect.collidepoint(fp))
if not collide:
self.xVel *= -1
self.rect.left += self.xVel # increment in x direction
self.collide(self.xVel, 0, platforms) # do x-axis collisions
self.rect.top += self.yVel # increment in y direction
self.onGround = False; # assuming we're in the air
self.collide(0, self.yVel, platforms) # do y-axis collisions
def collide(self, xVel, yVel, platforms):
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if xVel > 0:
self.rect.right = p.rect.left
self.xVel *= -1 # hit wall, so change direction
if xVel < 0:
self.rect.left = p.rect.right
self.xVel *= -1 # hit wall, so change direction
if yVel > 0:
self.rect.bottom = p.rect.top
self.onGround = True
if yVel < 0:
self.rect.top = p.rect.bottom
关于python - Pygame - 实体移动限制 - 碰撞检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14619700/