我正在做一个平台游戏,玩家有一把剑。我希望玩家只能在他下面有地面的时候攻击(所以他不能在空中攻击)。所以我实现了这段代码:
for b in instancelist:
for p in players:
if b.rect.collidepoint(p.rect.centerx,p.rect.bottom+4):
grounded=1
else:
grounded=0
print grounded
但是..
print grounded
每次返回零。虽然如果我将exit(1)
添加到测试玩家是否在地面的部分,它仍然存在!(虽然接地仍然等于零)
以下是完整的代码:
import pygame,random
from collections import namedtuple
from pygame.locals import *
pygame.init()
pygame.display.set_caption('Legend of Zelda | By Sam Tubb')
screen=pygame.display.set_mode((640,480))
instancelist=[]
players=[]
enemys=[]
clock=pygame.time.Clock()
Move = namedtuple('Move', ['up', 'left', 'right'])
#load sprites
block1=pygame.image.load('block1.png').convert()
#load/init player stuffs
playersprites=[pygame.image.load('link1.png').convert(),pygame.image.load('link2.png').convert(),
pygame.image.load('link3.png').convert(),pygame.image.load('linkatk.png').convert(),pygame.image.load('linkup.png').convert()]
for s in playersprites:
s.set_colorkey((255,0,0))
frame=0
frameplus=1
frametime=0
psprite=playersprites[frame]
max_gravity = 75
left=0
atk=0
atktime=0
grounded=0
class Enemy(object):
def __init__(self,x,y):
self.x=x
self.y=y
self.sprite=playersprites[0]
self.rect=self.sprite.get_rect(left=x,top=y)
class Player(object):
sprite=psprite
def __init__(self, x, y):
self.rect = self.sprite.get_rect(centery=y, centerx=x)
# indicates that we are standing on the ground
# and thus are "allowed" to jump
self.on_ground = True
self.xvel = 0
self.yvel = 0
self.jump_speed = 7
self.move_speed = 3
def update(self, move, blocks):
# check if we can jump
if move.up and self.on_ground:
self.yvel -= self.jump_speed
# simple left/right movement
if move.left:
self.xvel = -self.move_speed
if move.right:
self.xvel = self.move_speed
# if in the air, fall down
if not self.on_ground:
self.yvel += 0.3
# but not too fast
if self.yvel > max_gravity: self.yvel = max_gravity
# if no left/right movement, x speed is 0, of course
if not (move.left or move.right):
self.xvel = 0
# move horizontal, and check for horizontal collisions
self.rect.left += self.xvel
self.collide(self.xvel, 0, blocks)
# move vertically, and check for vertical collisions
self.rect.top += self.yvel
self.on_ground = False;
self.collide(0, self.yvel, blocks)
def collide(self, xvel, yvel, blocks):
# all blocks that we collide with
for block in [blocks[i] for i in self.rect.collidelistall(blocks)]:
# if xvel is > 0, we know our right side bumped
# into the left side of a block etc.
if xvel > 0:
self.rect.right = block.rect.left
if xvel < 0:
self.rect.left = block.rect.right
# if yvel > 0, we are falling, so if a collision happpens
# we know we hit the ground (remember, we seperated checking for
# horizontal and vertical collision, so if yvel != 0, xvel is 0)
if yvel > 0:
self.rect.bottom = block.rect.top+0.4
self.on_ground = True
self.yvel = 0
# if yvel < 0 and a collision occurs, we bumped our head
# on a block above us
if yvel < 0: self.rect.top = block.rect.bottom
class Block(object):
def __init__(self,x,y,sprite):
self.x=x
self.y=y
self.sprite=sprite
self.rect=self.sprite.get_rect(x=self.x,y=self.y)
x = y = 0
level = [
"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
"B B",
"B B",
"B L B",
"B B",
"B B",
"B B",
"B E B",
"B B",
"B BBBBBBBBBBBBBBB B",
"B B B",
"B E B B",
"B B B",
"B B B",
"B B B",
"B B B",
"B E B",
"B B",
"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
]
# build the level
for row in level:
for col in row:
if col == "B":
p = Block(x,y,block1)
instancelist.append(p)
if col=="L":
players.append(Player(x, y))
if col=="E":
enemys.append(Enemy(x,y))
x += 16
y += 16
x = 0
#mainloop
while True:
for b in instancelist:
for p in players:
if b.rect.collidepoint(p.rect.centerx,p.rect.bottom+4):
grounded=1
else:
grounded=0
print grounded
#total_level_width = len(level[0])*16
#total_level_height = len(level)*16
screen.fill((0,0,0))
mse=pygame.mouse.get_pos()
key=pygame.key.get_pressed()
if atk==0:
if not key[K_w]:
if key[K_a]:
left=1
if frameplus==1:
if frame<2:
frameplus=0
frametime=5
frame+=1
else:
frame=0
psprite=pygame.transform.flip(playersprites[frame],1,0)
if key[K_d]:
left=0
if frameplus==1:
if frame<2:
frameplus=0
frametime=5
frame+=1
else:
frame=0
psprite=playersprites[frame]
if not key[K_a]:
if not key[K_d]:
if left==0:
psprite=playersprites[0]
else:
psprite=pygame.transform.flip(playersprites[0],1,0)
else:
if left==0:
psprite=playersprites[4]
else:
psprite=pygame.transform.flip(playersprites[4],1,0)
if key[K_SPACE]:
if atk==0:
atk=1
atktime=15
if left==0:
psprite=playersprites[3]
p.rect.right+=4
else:
psprite=pygame.transform.flip(playersprites[3],1,0)
p.rect.right-=16
for e in pygame.event.get():
if e.type==QUIT:
exit(1)
for inst in instancelist:
screen.blit(inst.sprite,inst.rect)
for p in players:
if atk==0:
p.rect=psprite.get_rect(x=p.rect.left,y=p.rect.top)
move = Move(key[K_w], key[K_a], key[K_d])
p.update(move, instancelist)
#scrolling
if p.rect.right>=500:
for inst in instancelist:
inst.rect.left-=4
for e in enemys:
e.rect.left-=4
p.rect.left-=4
if p.rect.left<=140:
for inst in instancelist:
inst.rect.left+=4
for e in enemys:
e.rect.left+=4
p.rect.left+=4
if p.rect.top<=80:
for inst in instancelist:
inst.rect.top+=4
for e in enemys:
e.rect.top+=4
p.rect.top+=4
if p.rect.bottom>300:
for inst in instancelist:
inst.rect.bottom-=4
for e in enemys:
e.rect.bottom-=4
p.rect.bottom-=4
for b in instancelist:
if p.rect.colliderect(b.rect):
p.ground=1
screen.blit(psprite,p.rect)
for e in enemys:
if atk==1:
if left==0:
if p.rect.left<e.rect.left:
if p.rect.colliderect(e.rect):
enemys.remove(e)
else:
if p.rect.right>e.rect.right:
if p.rect.colliderect(e.rect):
enemys.remove(e)
screen.blit(e.sprite,e.rect)
#timers
if frametime>0:
frametime-=1
else:
frameplus=1
if atktime>0:
atktime-=1
else:
if atk==1:
if left==1:
p.rect.right+=16
else:
p.rect.right-=4
atktime=0
atk=0
p.rect=psprite.get_rect(x=p.rect.left,y=p.rect.top)
pygame.draw.rect(screen, ((255,0,0)), p.rect, 1)
clock.tick(60)
pygame.display.flip()
有人能帮忙吗?:)
最重要的是,正如martineau所说,接地环路将重置任何接地的发现。
instancelist似乎会受益于作为一个位置判断或数组,你可以根据玩家的位置更有效地测试它,而不是每次都将玩家的位置与每个块进行比较。
*编辑-忽略下面。@猴子善意地指出我是如何反转pygame坐标系的。
此外,我对文档的阅读表明,您的代码正在检查给定点是否位于b.rect中。给定的点是球员的水平中心和球员底部上方的4点。如果玩家躺在积木的底部,那么很好,因为它看起来像16号。但是你的秋季代码看起来会在玩家与积木碰撞之前将其发送到-4?无论如何,您可能希望将其反转为-4
,看看它的行为是否更像您想要的。
根据我对您代码的阅读,您在player
中有一个Player
,在instancelist
中有许多Block
。您的内部循环会为每个Block
-Player
对调用。除非您幸运(或不幸,因为这会隐藏错误),否则Player
与之冲突的Block
不会是您检查的最后一个。因此,在您的循环的稍后迭代中,您检查的Block
不会与Player
冲突,并且grgic
将在else
子句中设置回0
。
一种解决方案可能是摆脱你的other
语句。因此,如果任何方块
与玩家
发生碰撞,则接地将设置为1
,如果没有方块
与玩家
碰撞,则接地
将仅保持在0
。如果一个块
发生碰撞,以后不碰撞的块
不会改变接地
的值。
while True:
grounded = 0
for b in instancelist:
for p in players:
if b.rect.collidepoint(p.rect.centerx,p.rect.bottom+4):
grounded=1
print grounded
更好的解决方案可能是使用< code>break语句来避免不必要的工作。
while True:
grounded = 0
for p in players:
for b in instancelist:
if b.rect.collidepoint(p.rect.centerx,p.rect.bottom+4):
grounded=1
break
print grounded
我试图在pygame中创建一个下降效果,但我被困在一个特定的问题上。每当玩家摔倒并与平台发生碰撞时,我的玩家类就会开始上下摆动。我确信这与我的更新循环有关,但我不确定它到底是什么。我尝试了几种方法,例如重新排列层次结构,但无济于事。我最终在网上搜索,但没有得到答案。所以如果有人能帮忙,我将不胜感激。 谢谢!
我一直在学习一些pygame教程,并且基于这些教程开发了自己的代码。具体如下: 所以我想出了如何让我的家伙跳跃,但是我已经在天空中放置了一个块并试图这样做: 试图让角色停止跳跃。有没有一个内置的函数来测试这一点,或者有没有一个适合我的方法。顺便说一下,这是行不通的,我似乎也不知道该怎么做。非常感谢任何帮助:)
所以我试图用Python和Pyplay创建一个益智平台游戏,但是我遇到了一点麻烦。当我为主要角色使用单点图像,而不是矩形图像时,如何制作碰撞检测器?我知道直角图像有左、右、顶部和底部像素功能(这对冲突检测非常有用),但是对于单片图像有这样的功能吗?或者我只需要为x和y坐标创建一个变量图像的宽度/高度?我试过用那个 但是catImg一直在通过窗户的尽头。我做错了什么?提前谢谢。
刚开始使用pygame,当你按住箭头键时,试图让一个简单的点在屏幕上移动。目前,它只在你按键时移动,但你必须重复按键。 此外,我很感激你对我目前的代码有任何建议,可以改进或改变,使之更有效。
我已经有一段时间了。我正在尝试用PyGame制作一个游戏,我到达了碰撞段,已经被卡住了一段时间,并且检查了一些线程。 这是我的代码(删除了中间的其他方法和条件语句,但保留了相关部分)。我对这个错误有点困惑,因为我在两个类init中都self.imageRect=self.image.get_rect(),但是我有这个错误。当程序试图在dog类中执行冲突检测部分时,该错误具体为: "属性错误:'Pe
我知道有将近5到6个类似于我正在做的问题,但是没有一个答案对我有帮助(如果我不是一个完全的新手,他们可能会帮助我),所以我会试着展示我的具体案例。 我试图在PyGame(Python lib)中做一个精灵碰撞测试,但是我不能让它工作,碰撞时我得到的都是“假”,它根本不起作用,我也不知道为什么,我已经连续搜索了两天。 在我的游戏中,我有对象玩家(我称之为“老兄”)和对象敌人(我称之为...“敌人”)