【问题标题】:Can't move up and down while holding left or right按住左右不能上下移动
【发布时间】:2016-01-23 13:17:27
【问题描述】:

我正在开始一个角色扮演游戏,当角色向两边靠墙奔跑时,我无法让玩家平稳地上下移动。此外,角色在按住上下键并向北或南靠墙奔跑时,无法平稳地左右移动。

我尝试了“移动”功能的不同配置,但没有成功。我知道为什么算法不起作用,我只是不知道如何构造分支,以便在向右运行时,它将设置'self.rect.right = p.rect.left'而不设置'self .rect.bottom = p.rect.top' 下一次调用 'move()' 时,我在靠墙跑步时开始按下。

  def move(self, x, y, platforms):
        self.rect.left += x
        self.rect.top += y

        for p in platforms:
            if pygame.sprite.collide_rect(self, p):
                if isinstance(p, ExitBlock):
                    pygame.event.post(pygame.event.Event(QUIT))

                if self.x > 0: # Moving right
                    self.rect.right = p.rect.left
                if self.x < 0: # Moving left
                    self.rect.left = p.rect.right

                if self.y > 0: # Moving down
                    self.rect.bottom = p.rect.top
                if self.y < 0: # Moving up
                    self.rect.top = p.rect.bottom

这是您可以运行以查看不需要的行为的完整代码:

#! /usr/bin/python

import pygame, platform, sys
platform.architecture()

from pygame import *

import spritesheet
from sprite_strip_anim import SpriteStripAnim

WIN_W = 1400
WIN_H = 800
HALF_W = int(WIN_W / 2)
HALF_H = int(WIN_H / 2)

DEPTH = 32
FLAGS = 0
CAMERA_SLACK = 30

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.x = 0
        self.y = 0
        self.onGround = False
        self.image = Surface((32,32))
        self.image.fill(Color("#0000FF"))
        self.image.convert()
        self.rect = Rect(x, y, 32, 32)

    def update(self, up, down, left, right, running, platforms):
        if up:
            self.y = -5
        if down:
            self.y = 5
        if left:
            self.x = -5
        if right:
            self.x = 5
        if not(left or right):
            self.x = 0
        if not(up or down):
            self.y = 0

        self.move(self.x, 0, platforms)
        self.move(0, self.y, platforms)

    def move(self, x, y, platforms):
        self.rect.left += x
        self.rect.top += y

        for p in platforms:
            if pygame.sprite.collide_rect(self, p):
                if isinstance(p, ExitBlock):
                    pygame.event.post(pygame.event.Event(QUIT))

                if self.x > 0: # Moving right
                    self.rect.right = p.rect.left
                if self.x < 0: # Moving left
                    self.rect.left = p.rect.right

                if self.y > 0: # Moving down
                    self.rect.bottom = p.rect.top
                if self.y < 0: # Moving up
                    self.rect.top = p.rect.bottom


class Platform(Entity):
    def __init__(self, x, y):
        Entity.__init__(self)
        self.image = Surface((32, 32))
        self.image.convert()
        self.image.fill(Color("#DDDDDD"))
        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.fill(Color("#0033FF"))


def main():
    pygame.init

    screen = pygame.display.set_mode((WIN_W, WIN_H), FLAGS, DEPTH)
    pygame.display.set_caption("Use arrows to move!")
    timer = pygame.time.Clock()

    up = down = left = right = running = False
    bg = Surface((32,32))
    bg.convert()
    bg.fill(Color("#000000"))
    entities = pygame.sprite.Group()
    player = Player(32, 32)
    platforms = []

    x = y = 0
    level = [
        "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                    PPPPPPPPPPP           P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P    PPPPPPPP                              P",
        "P                                          P",
        "P                          PPPPPPP         P",
        "P                 PPPPPP                   P",
        "P                                          P",
        "P         PPPPPPP                          P",
        "P                                          P",
        "P                     PPPPPP               P",
        "P                                          P",
        "P   PPPPPPPPPPP                            P",
        "P                                          P",
        "P                 PPPPPPPPPPP              P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",]

    # 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

    total_level_width  = len(level[0])*32
    total_level_height = len(level)*32

    entities.add(player)

    while 1:
        timer.tick(60)

        # draw background
        for y in range(32):
            for x in range(32):
                screen.blit(bg, (x * 32, y * 32))

        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_w:
                up = True
                down = False
            if e.type == KEYDOWN and e.key == K_s:
                down = True
                up = False
            if e.type == KEYDOWN and e.key == K_a:
                left = True
                right = False
            if e.type == KEYDOWN and e.key == K_d:
                right = True
                left = False

            if e.type == KEYUP and e.key == K_w:
                up = False
            if e.type == KEYUP and e.key == K_s:
                down = False
            if e.type == KEYUP and e.key == K_d:
                right = False
            if e.type == KEYUP and e.key == K_a:
                left = False

        # update player, draw everything else
        player.update(up, down, left, right, running, platforms)

        for e in entities:
            screen.blit(e.image, e.rect)

        pygame.display.update()


if __name__ == "__main__":
    main()

【问题讨论】:

  • 这是大量需要阅读和推理的代码; you should probably trim some of the fat 让我们更容易为您提供帮助(例如,我很确定此代码中涉及图像和颜色的所有内容都与此问题无关)。
  • 我刚刚运行了这段代码,我能够在按住左或右的同时上下移动。它沿对角线移动。有时撞墙会让你跳起来。
  • 这就是我要解决的问题。我希望能够靠着左边的墙跑,然后同时向上按,让角色在靠墙的同时跑起来。看一下 move 方法,你会看到分支设置了 rect 的 y 值,因为我开始向下按,同时按向左,同时撞到墙上。

标签: python pygame game-physics


【解决方案1】:

找到了一个有效的算法@@http://pygame.org/project-Rect+Collision+Response-1061-.html:

def move(self, dx, dy):

    # Move each axis separately. Note that this checks for collisions both times.
    if dx != 0:
        self.move_single_axis(dx, 0)
    if dy != 0:
        self.move_single_axis(0, dy)

def move_single_axis(self, dx, dy):

    # Move the rect
    self.rect.x += dx
    self.rect.y += dy

    # If you collide with a wall, move out based on velocity
    for wall in walls:
        if self.rect.colliderect(wall.rect):
            if dx > 0: # Moving right; Hit the left side of the wall
                self.rect.right = wall.rect.left
            if dx < 0: # Moving left; Hit the right side of the wall
                self.rect.left = wall.rect.right
            if dy > 0: # Moving down; Hit the top side of the wall
                self.rect.bottom = wall.rect.top
            if dy < 0: # Moving up; Hit the bottom side of the wall
                self.rect.top = wall.rect.bottom

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 2017-09-27
    • 1970-01-01
    • 2016-05-16
    相关资源
    最近更新 更多