pygame - 跳墙

时间:2013-01-17 00:00:46

标签: python pygame

好的,所以我的代码启动并运行,当用户向右或向左移动时玩家与墙壁碰撞时,如果玩家释放方向(左或右),玩家将慢慢滑下墙壁玩家继续正常下降。

我想做的是这样当玩家撞到墙壁时他会“粘住”它,这意味着他仍然向下滑动并向下滑动直到他撞到地面(用户不必按住方向) )或者用户可以跳下墙。 (想想那些玩过它或看过游戏玩法或者超级玩家的超级肉男孩)。任何人都可以提出一个很好的方法来解决这个问题吗?

import pygame, time
from pygame import *


WIN_WIDTH = 800
WIN_HEIGHT = 640
HALF_WIDTH = int(WIN_WIDTH / 2)
HALF_HEIGHT = int(WIN_HEIGHT / 2)

DISPLAY = (WIN_WIDTH, WIN_HEIGHT)
DEPTH = 32
FLAGS = 0

def main():
    pygame.init()
    screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
    pygame.display.set_caption("Use arrows to move!")
    timer = pygame.time.Clock()

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

    space_num = 0

    x = y = 0
    level = [
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                              E           P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                           PPPPPP         P",
        "P                                          P",
        "P                                          P",
        "PPPPP                                      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
    camera = Camera(complex_camera, total_level_width, total_level_height)
    entities.add(player)

    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_DOWN:
                down = 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 == KEYDOWN and e.key == K_SPACE:
                if space_num < 6:
                    space = True
                    space_num += 1

            if e.type == KEYUP and e.key == K_UP:
                up = False
            if e.type == KEYUP and e.key == K_DOWN:
                down = False
            if e.type == KEYUP and e.key == K_LEFT:
                left = False
            if e.type == KEYUP and e.key == K_RIGHT:
                right = False
            if e.type == KEYUP and e.key == K_SPACE:
                space = False

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

        camera.update(player)

        # update player, draw everything else
        player.update(up, down, left, right, platforms, space)
        for e in entities:
            screen.blit(e.image, camera.apply(e))
        pygame.display.update()

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):
        return target.rect.move(self.state.topleft)

    def update(self, target):
        self.state = self.camera_func(self.state, target.rect)

#def simple_camera(camera, target_rect):
#    l, t, _, _ = target_rect
#    _, _, w, h = camera
#    return Rect(-l+HALF_WIDTH, -t+HALF_HEIGHT, w, h)

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

    def update(self, up, down, left, right, platforms, space):
        if up:
            if self.onGround: self.yvel -= 10 # only jump if on the ground
        if down:
            pass
        if left:
            self.xvel = -8
        if right:
            self.xvel = 8
        if not self.onGround:
            self.yvel += 0.3 # only accelerate with gravity if in the air
            if self.yvel > 40: self.yvel = 40 # 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
        self.rect.top += self.yvel # increment in y direction
        self.onGround = False; # assuming we're in the air
        self.onWall = False
        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
                    self.onWall = True

                if xvel < 0:
                    self.rect.left = p.rect.right
                    self.onWall = True

                if yvel > 0:
                    self.rect.bottom = p.rect.top
                    self.onGround = True
                    self.onWall = False
                    self.yvel = 0
                if yvel < 0: self.rect.top = p.rect.bottom

                if self.onWall:
                    self.yvel = 3


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

if __name__ == "__main__":
    main()

2 个答案:

答案 0 :(得分:1)

为玩家类提供一个布尔值,当他们触摸或停止触摸墙壁时设置它可能就像你需要的那样复杂。只要注意保持布尔与游戏世界中实际发生的事情同步的典型问题:你应该检查每个更新周期在同一个地方更改这个值,最有可能是在角色移动之后,没有其他地方。此外,如果墙壁或地形本身可以移动,则必须考虑到这一点。

答案 1 :(得分:0)

根据我编写的一些代码,这只是一个粗略的想法。

onCollision(wall, player):
  player.stuck = true
  player.wall_jump = true

onCollision(floor, player):
  player.stuck = false
  player.wall_jump = false # If you slide to the bottom of the floor, you can't walljump

onInput():

  player = getPlayer()
  if jump_key.state and player.wall_jump: # assuming you set jump_key.state to true, when jump key is pressed
    # set player direction to opposite
    # set player's horizontal and vertical velocity
    player.stuck = false;