我试图在pygame中创建一个下降效果,但我被困在一个特定的问题上。每当玩家摔倒并与平台发生碰撞时,我的玩家类就会开始上下摆动。我确信这与我的更新循环有关,但我不确定它到底是什么。我尝试了几种方法,例如重新排列层次结构,但无济于事。我最终在网上搜索,但没有得到答案。所以如果有人能帮忙,我将不胜感激。
谢谢!
import pygame as pg
import os
#vector
VEC = pg.math.Vector2
def paint(parent, color=None):
""" fills the background for surfaces.
color: for none sprite surfaces optional parameter if given
"""
#set background color based on surface type
if color:
#class based surfaces or sprites
background = pg.Color(color)
else:
#none sprite surfaces usuallly not class
background = pg.Color(parent.background)
#check for image attribure
#if found fill the image's backround
if hasattr(parent, "image"):
parent.image.fill(background)
#if "image" not found fill the surface itself
else:
parent.fill(background)
class Asset(pg.sprite.Sprite):
""" asset class functions as base class for various assets in this case
either a player asset or a block asset group """
#if the given family name(see bellow in constructor) is block,
#all instances of block will be added to this group else its ignored
GROUP = pg.sprite.Group()
def __init__(self, parent=None, family=None, pos=None):
"""
parent:surface asset is being rendered to
family:type of asset(type is not used due to it being a buil-in)
pos: position of asset
"""
super().__init__()
self.parent = parent
self.family = family
self.pos = VEC(pos)
self.size = [20, 20]
#background will be based on family
self.background = {"block":"#000000","player":"#ff0000"}[self.family]
self.image, self.rect = self.set_image()
#see class documention for explanation
if self.family == "block":
Asset.GROUP.add(self)
#if family is player add essential fields for physics
else:
#velocity
self.vel = VEC(3, 3)
#acceleration(x:friction, y:gravity)
self.ac = VEC(.3, .3)
#jump height
self.height = 5
def update(self):
if self.family == "player":
#fall code
self.vel.y += self.ac.y
self.pos.y += self.vel.y
#prevents player from falling of the edge and adds teleportation
if self.pos.x + self.size[0] <= 0:
self.pos.x = 399
elif self.pos.x >= 400:
self.pos.x = 1 - self.size[0]
#updates asset rect postion
self.rect.topleft = self.pos
def render(self):
""" renders image to parent surface """
self.parent.blit(self.image, self.rect)
def set_image(self):
"""creates initial image and rect for sprite"""
self.image = pg.Surface(self.size)
paint(self)
self.rect = self.image.get_rect()
self.rect.topleft = self.pos
return self.image, self.rect
def move(self, key):
"""handles player movmet"""
for i in range(2):
#checks for right or left movment
if key[[pg.K_LEFT, pg.K_RIGHT][i]]:
self.pos.x += self.vel.x*[-1, 1][i]
def jump(self):
""" handles jumping """
self.vel.y = -self.height
def block_collision(player, blocks):
"""collision detection between blocks and player"""
hit = pg.sprite.spritecollide(player, blocks, False)
if hit:
if player.rect.bottom >= hit[0].rect.top:
player.pos.y = hit[0].rect.top - hit[0].rect.height
player.vel.y = 0
def main():
POS = [0, 0]
SIZE = [400, 400]
TITLE = "Test"
BACKGROUND = "#ffffff"
CLOCK = pg.time.Clock()
FPS = 60
RUN = True
os.environ["SDL_VIDEO_CENTERED"] = "1"
win = pg.display.set_mode(SIZE)
pg.display.set_caption(TITLE)
# create blocks group
#NOTE:blocks do not need a variable instance because they are
#automatically added to the class group on construction
for x in range(20):
Asset(family="block", pos=[x*20, 380])
#set player filed
player = Asset(win, family="player", pos=[20, 20])
while RUN:
for event in pg.event.get():
if event.type == pg.QUIT:
RUN = False
elif event.type == pg.KEYDOWN:
if event.key == pg.K_UP:
#player jump
player.jump()
#player movement
player.move(pg.key.get_pressed())
#fill window background
paint(win, BACKGROUND)
#check for collision
block_collision(player, Asset.GROUP)
#update player
player.update()
#update block group
Asset.GROUP.update()
#render player
player.render()
#render block group
Asset.GROUP.draw(win)
pg.display.update()
CLOCK.tick(FPS)
if __name__ == '__main__':
main()
有两个错误加在一起会产生问题
第一:
player.pos.y = hit[0].rect.top - hit[0].rect.height
这是没有道理的。顶部 - 高度
与底部
相同,因此您拥有
player.pos.y = hit[0].rect.bottom
但你需要命中[0].矩形顶部
与玩家.矩形.底部
player.rect.bottom = hit[0].rect.top
player.pos.y = player.rect.y
(这里我不知道为什么你使用player.pos
,如果它总是有相同的值作为player.rect
,并且rect
有许多有用的字段,如rect.bottom
,rect.center
等,它会自动重新计算rect. x
,rect. y
当你改变rect.bottom
,rect.center
等)
所以第一个修正是
if hit:
if player.rect.bottom >= hit[0].rect.top:
#player.pos.y = hit[0].rect.top - hit[0].rect.height
player.rect.bottom = hit[0].rect.top
player.pos.y = player.rect.y
player.vel.y = 0
第二:
你应该在检查碰撞前完成所有动作
# player movement
player.move(pg.key.get_pressed())
# update player
player.update()
#update block group
Asset.GROUP.update()
# check for collision - after all moves
block_collision(player, Asset.GROUP)
完整代码
import pygame as pg
import os
#vector
VEC = pg.math.Vector2
def paint(parent, color=None):
""" fills the background for surfaces.
color: for none sprite surfaces optional parameter if given
"""
#set background color based on surface type
if color:
#class based surfaces or sprites
background = pg.Color(color)
else:
#none sprite surfaces usuallly not class
background = pg.Color(parent.background)
#check for image attribure
#if found fill the image's backround
if hasattr(parent, "image"):
parent.image.fill(background)
#if "image" not found fill the surface itself
else:
parent.fill(background)
class Asset(pg.sprite.Sprite):
""" asset class functions as base class for various assets in this case
either a player asset or a block asset group """
#if the given family name(see bellow in constructor) is block,
#all instances of block will be added to this group else its ignored
GROUP = pg.sprite.Group()
def __init__(self, parent=None, family=None, pos=None):
"""
parent:surface asset is being rendered to
family:type of asset(type is not used due to it being a buil-in)
pos: position of asset
"""
super().__init__()
self.parent = parent
self.family = family
self.pos = VEC(pos)
self.size = [20, 20]
#background will be based on family
self.background = {"block":"#000000","player":"#ff0000"}[self.family]
self.image, self.rect = self.set_image()
#see class documention for explanation
if self.family == "block":
Asset.GROUP.add(self)
#if family is player add essential fields for physics
else:
#velocity
self.vel = VEC(3, 3)
#acceleration(x:friction, y:gravity)
self.ac = VEC(.3, .3)
#jump height
self.height = 5
def update(self):
if self.family == "player":
#fall code
self.vel.y += self.ac.y
self.pos.y += self.vel.y
#prevents player from falling of the edge and adds teleportation
if self.pos.x + self.size[0] <= 0:
self.pos.x = 399
elif self.pos.x >= 400:
self.pos.x = 1 - self.size[0]
#updates asset rect postion
self.rect.topleft = self.pos
def render(self):
""" renders image to parent surface """
self.parent.blit(self.image, self.rect)
def set_image(self):
"""creates initial image and rect for sprite"""
self.image = pg.Surface(self.size)
paint(self)
self.rect = self.image.get_rect()
self.rect.topleft = self.pos
return self.image, self.rect
def move(self, key):
"""handles player movmet"""
for i in range(2):
#checks for right or left movment
if key[[pg.K_LEFT, pg.K_RIGHT][i]]:
self.pos.x += self.vel.x*[-1, 1][i]
def jump(self):
""" handles jumping """
self.vel.y = -self.height
def block_collision(player, blocks):
"""collision detection between blocks and player"""
hit = pg.sprite.spritecollide(player, blocks, False)
if hit:
if player.rect.bottom >= hit[0].rect.top:
#player.pos.y = hit[0].rect.top - hit[0].rect.height
player.rect.bottom = hit[0].rect.top
player.pos.y = player.rect.y
player.vel.y = 0
def main():
POS = [0, 0]
SIZE = [400, 400]
TITLE = "Test"
BACKGROUND = "#ffffff"
CLOCK = pg.time.Clock()
FPS = 60
RUN = True
os.environ["SDL_VIDEO_CENTERED"] = "1"
win = pg.display.set_mode(SIZE)
pg.display.set_caption(TITLE)
# create blocks group
#NOTE:blocks do not need a variable instance because they are
#automatically added to the class group on construction
for x in range(20):
Asset(family="block", pos=[x*20, 380])
#set player filed
player = Asset(win, family="player", pos=[20, 20])
while RUN:
# --- events ---
for event in pg.event.get():
if event.type == pg.QUIT:
RUN = False
elif event.type == pg.KEYDOWN:
if event.key == pg.K_UP:
#player jump
player.jump()
#player movement
player.move(pg.key.get_pressed())
# --- updates --
#update player
player.update()
#update block group
Asset.GROUP.update()
#check for collision
block_collision(player, Asset.GROUP)
# --- draws ---
#fill window background
paint(win, BACKGROUND)
#render player
player.render()
#render block group
Asset.GROUP.draw(win)
pg.display.update()
CLOCK.tick(FPS)
# ---- end ---
pg.quit()
if __name__ == '__main__':
main()
我正在做一个平台游戏,玩家有一把剑。我希望玩家只能在他下面有地面的时候攻击(所以他不能在空中攻击)。所以我实现了这段代码: 但是.. 每次返回零。虽然如果我将添加到测试玩家是否在地面的部分,它仍然存在!(虽然接地仍然等于零) 以下是完整的代码: 有人能帮忙吗?:)
所以我试图用Python和Pyplay创建一个益智平台游戏,但是我遇到了一点麻烦。当我为主要角色使用单点图像,而不是矩形图像时,如何制作碰撞检测器?我知道直角图像有左、右、顶部和底部像素功能(这对冲突检测非常有用),但是对于单片图像有这样的功能吗?或者我只需要为x和y坐标创建一个变量图像的宽度/高度?我试过用那个 但是catImg一直在通过窗户的尽头。我做错了什么?提前谢谢。
我正在用Python创建一个乒乓游戏(很明显),我是Pyplay的新手,所以我想要一些帮助,当球碰到桨时,它会反转速度,朝相反的方向移动。到目前为止,一切都正常,但是当球到达桨时,它会穿过桨,不会改变方向。我已经解决了,所以桨不会离开屏幕,当球遇到墙时,球会改变方向,但当球遇到桨时,不会。任何帮助或提示将不胜感激。 我的划桨课: 我的球课 我的目标是当球触到球拍或反弹(重叠点)时,使球的速度反向(
我是蟒蛇/蟒蛇游戏的新手。我已经能够在小型测试程序中拼凑出一些东西,但试图掌握碰撞并没有发生。我尝试过学习多个教程,但我觉得我需要它完全分解,然后才能很好地理解它。 有人能解释一下像CollidRect(Rect)这样的东西是如何工作的吗?我需要一个碰撞函数的类,还是只需要两个矩形就可以得到结果? 我尝试使用的代码如下。我能够制作两个图像,每个图像都由一个矩形包围,我假设碰撞仅适用于精灵而不是图像
所以我在为我的平台游戏编写攻击方法时,我注意到我的游戏中的碰撞行为很奇怪,当我向敌人发起攻击(我的游戏中的火球)时没有损坏的记录,我添加了一个打印声明来检查他们是否失去任何生命值和没有记录,但是当我按住攻击方法(这是空格键)时,敌人上记录了多个攻击。 玩家角色是蓝色的,敌人是绿色的。 控制台显示敌人的生命值下降,但仅当空格键被按住时。 同样,当我走进敌人的精灵时,我点击一次空格键,我也能以这种方式
我已经有一段时间了。我正在尝试用PyGame制作一个游戏,我到达了碰撞段,已经被卡住了一段时间,并且检查了一些线程。 这是我的代码(删除了中间的其他方法和条件语句,但保留了相关部分)。我对这个错误有点困惑,因为我在两个类init中都self.imageRect=self.image.get_rect(),但是我有这个错误。当程序试图在dog类中执行冲突检测部分时,该错误具体为: "属性错误:'Pe