【问题标题】:Pygame Sprite movement, failing to updatePygame Sprite 移动,无法更新
【发布时间】:2012-06-30 13:35:52
【问题描述】:

我将尝试将我的问题重新定义为一个更简洁和具体的问题。下面是 Hero 类,还有几个打印命令到终端,我试图用这些命令来解决问题:

代码:

class Hero(pygame.sprite.Sprite):
    """Moves the hero around the screen, following the mouse"""
    #male = load_image("malehero-64.png", -1)
    #female = load_image("girlhero-64.png", -1)
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image, self.rect = load_image("girlhero-64.png", -1)
        self.rect = self.image.get_rect()
        self.rect.topleft = (384,0)
        self.target = self.movetarget()

    #def setgender(self, gender):
        #if gender == "male":
            #self.image, self.rect = self.male
        #if gender == "female":
            #self.image, self.rect = self.female
        #self.startingpos = (480, 640)
        #self.rect.topleft = (480,640)
        #self.target = self.rect.topleft

    def movetarget(self):
        self.pos = pygame.mouse.get_pos()
        self.rect = self.image.get_rect()
        self.target = self.rect.topleft
        self.targetx,self.targety = self.target
        self.oldx, self.oldy = self.rect.topleft
        if self.oldx + tilesize < self.pos[0]:
            self.targetx = self.oldx + tilesize
        if self.oldx > self.pos[0]:
            self.targetx = self.oldx - tilesize
        if self.oldx + tilesize >= self.pos[0] and self.oldx < self.pos[0]:
            self.targetx = self.oldx
        if self.oldy + tilesize < self.pos[1]:
            self.targety = self.oldy + tilesize
        if self.oldy > self.pos[1]:
            self.targety = self.oldy - tilesize
        if self.oldy + tilesize >= self.pos[1] and self.oldy < self.pos[1]:
            self.targety = self.oldy
        self.target = (self.targetx,self.targety)
        print("NOW THE TARGET IS SET!!!!!!!!")
        print(self.targetx,self.targety)
        return self.target

    def update(self):
        "Move the hero closer to the last mouse position clicked self.target"
        self.rect = self.image.get_rect()
        print("topleft before")
        print(self.rect.topleft)
        self.xmove = 0
        self.ymove = 0
        print("update target is")
        print(self.target)
        if self.rect.topleft[0] > 960:
            self.rect.topleft = (960, self.rect.topleft[1])
        if self.rect.topleft[0] < 0:
            self.rect.topleft = (0, self.rect.topleft[1])
        if self.rect.topleft[0] >= 0 and self.rect.topleft[0] <= 960:
            if self.rect.topleft[0] < self.target[0]:
                self.xmove = 4
            if self.rect.topleft[1] < self.target[1]:
                self.ymove = 4
            if self.rect.topleft[0] > self.target[0]:
                self.xmove = -4
            if self.rect.topleft[1] > self.target[1]:
                self.ymove = -4
        self.newx=self.rect.topleft[0]+self.xmove
        self.newy=self.rect.topleft[1]+self.ymove
        print("newx and newy")
        print (self.newx,self.newy)
        self.rect.topleft = (self.newx,self.newy)
        print("topleft after")
        print(self.rect.topleft)

运行时,终端的一个sn-p如下:

代码:

NOW THE TARGET IS SET!!!!!!!!
64 64
NOW THE TARGET IS SET!!!!!!!!
64 64
NOW THE TARGET IS SET!!!!!!!!
64 64
NOW THE TARGET IS SET!!!!!!!!
64 64
topleft before
(0, 0)
update target is
(0, 0)
newx and newy
0 0
topleft after
(0, 0)
topleft before
(0, 0)
update target is
(0, 0)
newx and newy
0 0
topleft after
(0, 0)
topleft before
(0, 0)
update target is
(0, 0)
newx and newy
0 0
topleft after
(0, 0)

我想要完成的事情: 当鼠标在游戏地图上点击时,Hero.movetarget 会被调用,并设置一个距离当前矩形一格的移动目标。然后,当字符精灵组对组中的所有精灵调用更新方法(这是正确的术语吗?)时,它们应该向目标图块移动几个像素。

当更新方法只是将所有精灵快速移动一格时,我让精灵毫无问题地执行此操作。我正在尝试更改它,以便精灵滑过几帧到新的目标图块,而不是简单地跳到那里。

当我阅读上面的终端打印输出时,在 Hero.movetarget 中设置的 self.target 变量与在 Hero.update 开始时打印到终端的 self.target 不同。

我不明白为什么更改 Hero.movetarget 中的 self.target 不会更改 Hero.update 中的 self.target。

请原谅我对问题措辞的任何无知,并提前感谢您提供的任何见解。

load_image 类取自 Pygame chimp 教程: 代码:

def load_image(name, colorkey=None):
    fullname = os.path.join('data', name)
    try:
        image = pygame.image.load(fullname)
    except pygame.error as message:
        print ('Cannot load image:', name)
        raise SystemExit(message)
    image = image.convert()
    if colorkey is not None:
        if colorkey is -1:
            colorkey = image.get_at((0,0))
        image.set_colorkey(colorkey, RLEACCEL)
    return image, image.get_rect()

调用 Hero 类的程序主体,编辑为我认为的相关部分: 代码:

hero = Hero()

charactersprites = pygame.sprite.Group((hero))

mathsterGroup = pygame.sprite.Group()
mathster = Mathster((0, 0))
mathsterGroup.add((mathster))
charactersprites.add((mathster))
mathster = Mathster((128, 256))
mathsterGroup.add((mathster))
charactersprites.add((mathster))
mathster = Mathster((512, 320))
mathsterGroup.add((mathster))
charactersprites.add((mathster))

inventory = TextObject("Hit a mathster!", Font, (0,0,0), (1024,50))
charactersprites.add((inventory))
nextproblem = Input(x=825, color=(255,25,25), 

heroGroup = pygame.sprite.Group()
heroGroup.add(hero)

clock = pygame.time.Clock() 

while 1:
    events1 = pygame.event.get()

    for event in events1:
        if event.type == pygame.QUIT: sys.exit()

    if not menu:
        for events in events1:
            if event.type == MOUSEBUTTONDOWN:
                mouseclick = 1

        if not collisiontest and mouseclick:
            for heros in charactersprites:
                hero.movetarget()
            for mathsters in mathsterGroup:
                mathster.movetarget()
            mouseclick = 0
        screen.fill((50,100,200))
        gamebackground = GameMap()
        if not mapdrawn:
            levelmap = gamebackground.drawmap()
            mapdrawn = 1
        screen.blit(levelmap, (0,0))
        wallGroup.draw(screen)
        nextproblem.update()
        nextproblem.draw(screen)
        charactersprites.update()
        charactersprites.draw(screen)
        screen.fill((50,100,200))
        screen.blit(menubackground, (0,0))
        menusprites.update()
        menusprites.draw(screen)


    pygame.display.flip()
    clock.tick(120)

提前感谢所有愿意帮忙的人。我一直在阅读很多教程来尝试自我教育,但我一直无法找到我出错的地方。

欢迎任何改进我的代码的提示,尽管修复我的一动不动的英雄是我的首要任务。

编辑以制定更具体的问题。

【问题讨论】:

  • 我解决了这个问题,尽管我仍然不确定它为什么不起作用。 charactersprites.update 和charactersprites.draw 没有更新和绘制所有组成员,所以我将精灵分成更小的组,它们正确更新和绘制。

标签: python-3.x pygame sprite


【解决方案1】:

磁贴 ID

我建议你为每个怪物/玩家的位置使用一个元组(x,y)。保存为 tile-offset 而不是像素。

绘制时,将 tile-id 转换为像素。离屏就好了。

def id_to_screen( tile_id width=32, height=32):
    """convert tile-coordinate to screen-coordinate (Pixels)"""
    x,y = tile_id
    x *= width
    y *= height
    return (x, y)         # unless you need: return pygame.Rect(x, y, width, height)    

您也需要反过来,将鼠标位置转换为 tile-id。

def screen_to_id( pos, width=32, height=32):
    # converts screen pixel coordinate to world map tile offsets.
    x = pos[0] / width
    y = pos[1] / height
    return (x, y)

矩形

rect.topleft 是精灵 blit 到的左上角。设置它来移动精灵。 (现在您正在设置 targetx,并从 self.rect 读取。

    self.rect.topleft = (384,0)

    # or
    self.rect.move_ip(384,0)

删除 self.targetx 。除非您将其用作地图上的 tile-id 位置,而不是像素。 (如果你画一个精灵,当它的 Rect 不在屏幕上时,那很好。)

一些提示:

    self.targetx = self.rect.topleft[0]
    self.targety = self.rect.topleft[1]

    # becomes
    self.target = self.rect.topleft
    # or
    x,y = self.rect.topleft
    # or
    self.tilex, self.tiley = self.rect.topleft

rect 虚属性很有用。请参阅:http://www.pygame.org/docs/ref/rect.html#pygame.Rect。它们简化了逻辑/删除了一些数学运算。

    r.bottomleft = (20,30)
    r.left = 500

numpy + 示例项目

Numpy 对于多维数组(roguelike 2d tile maps)很有用。 示例为地图使用 numpy 数组。 http://code.google.com/p/ninmonkey/source/browse/#hg%2Fexamples%2Fmaptiles_numpy%253Fstate%253Dclosed

运行 main.py ,按 s 切换滚动磁贴。

【讨论】:

  • 我非常感谢这些提示。他们会有所帮助,但我仍然不明白我的问题的根源。我更具体地说明了我的问题;如果您可以添加任何其他见解,我将不胜感激。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
  • 1970-01-01
相关资源
最近更新 更多