当玩家与墙碰撞时实施墙跳过程

时间:2017-04-04 14:27:46

标签: python pygame

我希望有人可以帮助我,或者就我的问题给我一些建议。 我一直在玩python的pygame模块,我遇到了一个我似乎无法解决的问题。 我想要发生的是:

  • 用户与墙碰撞。
  • 用户输入跳转命令。
  • 玩家对象跳跃然后跌倒。
  • 可以重复。

然而问题是,在我的代码中,玩家可以只持有“向上箭头”和“向左箭头”并且不断向上飞行,这是我不希望发生的,我不知道如何解决这个问题。我做了很多尝试,所有这些都是徒劳的。

这是完整的代码:

import pygame
from pygame import *

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

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

MAPLIST = ["LevelOne.txt"]
MAPCOUNT = 0

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 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 at the left edge
    l = max(-(camera.width-WIN_WIDTH), l)   # stop scrolling at the right edge
    t = max(-(camera.height-WIN_HEIGHT), t) # stop scrolling at the bottom
    t = min(0, t)                           # stop scrolling at the top
    return Rect(l, t, w, h)

class Entity(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = Surface((32, 32))
        self.image.convert()
        self.image.fill(Color("#f21000"))

class Player(Entity):
    def __init__(self, x, y):
        Entity.__init__(self)

        #self.image = pygame.image.load("player.png")
        #self.image.convert()
        self.rect = Rect(x, y, 32, 32)

        self.xvel = 0
        self.yvel = 0
        self.onGround = False
        self.canJump = False
        self.wallCollide = False

    def jump(self):

        if self.onGround:
            self.yvel = 0
            self.yvel -= 8
            self.rect.top += self.yvel
            self.onGround=False
            self.canJump=False

        if self.canJump and not self.onGround:
            self.yvel = 0
            self.yvel -= 4
            self.rect.top += self.yvel
            self.onGround = False
            self.canJump = False

    def update(self, up, down, left, right, running, platforms,entities):
        if self.wallCollide and not self.onGround:

        if down:
            print(self.wallCollide)
        if up:
            self.jump()
        if running:
            self.xvel = 1
        if left:
            self.xvel = -4
        if right:
            self.xvel = 4

        if not self.onGround:
                # print("x")
                # only accelerate with gravity if in the air
            self.yvel += 0.3
                # max falling speed
            if self.yvel > 100:
                self.yvel = 100

        if not (left or right):
            self.xvel = 0
        # increment in x direction
        self.rect.left += self.xvel
        # do x-axis collisions
        self.collide(self.xvel, 0, platforms, entities)
        # increment in y direction
        if not self.onGround:
            self.rect.top += self.yvel
        # assuming we're in the air
        # do y-axis collisions
        self.collide(0,self.yvel, platforms, entities)

    def collide(self, xvel, yvel, platforms, entities):
        # Player collisions with platforms. e.g. main blocks
        for p in platforms:
            if pygame.sprite.collide_rect(self, p):
                if yvel == 0:
                    self.wallCollide = True
                if xvel > 0:
                    self.rect.right = p.rect.left  # collide right
                if xvel < 0:
                    self.rect.left = p.rect.right  # collide left
                if yvel > 0:
                    self.rect.bottom = p.rect.top
                    self.onGround = True
                    self.canJump = True
                    self.yvel = 0
                if yvel < 0:
                    self.rect.top = p.rect.bottom
                    # if isinstance(p,Platform):
                    # self.onGround = True

class Platform(Entity):
    def __init__(self, x, y):
        Entity.__init__(self)
        self.image = pygame.image.load("brick.png")
        self.image.convert()
        self.rect = Rect(x, y, 32, 32)

def LoadMap(platforms,entities,x,y):
    currentLevel=[]
    mapFile = open(MAPLIST[MAPCOUNT])
    for line in mapFile:
        currentLevel.append(line)

    for row in currentLevel:
        for col in row:
            if col == "P":
                p = Platform(x, y)
                platforms.append(p)
                entities.add(p)
            elif col == "X":
                player=Player(x,y)
                entities.add(player)
            x += 32
        y += 32
        x = 0
    return currentLevel, player

def main():
    pygame.init()
    screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
    pygame.display.set_caption("Super Meat Boy")
    myfont = pygame.font.SysFont("monospace", 40)
    timer = pygame.time.Clock()

    entities = pygame.sprite.Group()
    platforms = []

    up = down = left = right = running = False
    x = y = 0

    bg = Surface((32, 32))
    bg.convert()
    bg.fill(Color("#66ccff"))
    currentLevel,player = LoadMap(platforms,entities,x,y)

    total_level_width = len(currentLevel[0]) * 32
    total_level_height = len(currentLevel) * 32
    camera = Camera(complex_camera, total_level_width, total_level_height)

    while True:
        clock=timer.tick(60)
        for e in pygame.event.get():

            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:
                running = True

            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_RIGHT:
                right = False

            if e.type == KEYUP and e.key == K_LEFT:
                left = False

            if e.type == KEYUP and e.key == K_SPACE:
                running = False

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

        camera.update(player)

        player.update(up, down, left, right, running, platforms, entities)

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


        pygame.display.update()

if __name__ == "__main__":
    main()

这是问题所在代码的一部分:

class Player(Entity):
    def __init__(self, x, y):
        Entity.__init__(self)

        #self.image = pygame.image.load("player.png")
        #self.image.convert()
        self.rect = Rect(x, y, 32, 32)

        self.xvel = 0
        self.yvel = 0
        self.onGround = False
        self.canJump = False
        self.wallCollide = False

    def jump(self):
        if self.onGround:
            self.yvel = 0
            self.yvel -= 8
            self.rect.top += self.yvel
            self.onGround=False
            self.canJump=False

        if self.canJump and not self.onGround:
            self.yvel = 0
            self.yvel -= 4
            self.rect.top += self.yvel
            self.onGround = False
            self.canJump = False

    def update(self, up, down, left, right, running, platforms, entities):
        if self.wallCollide and not self.onGround:

        if down:
            print(self.wallCollide)
        if up:
            self.jump()
        if running:
            self.xvel = 1
        if left:
            self.xvel = -4
        if right:
            self.xvel = 4

        if not self.onGround:
                # print("x")
                # only accelerate with gravity if in the air
            self.yvel += 0.3
                # max falling speed
            if self.yvel > 100:
                self.yvel = 100

        if not (left or right):
            self.xvel = 0
        # increment in x direction
        self.rect.left += self.xvel
        # do x-axis collisions
        self.collide(self.xvel, 0, platforms, entities)
        # increment in y direction
        if not self.onGround:
            self.rect.top += self.yvel
        # assuming we're in the air
        # do y-axis collisions
        self.collide(0,self.yvel, platforms, entities)

    def collide(self, xvel, yvel, platforms, entities):
        # Player collisions with platforms. e.g. main blocks
        for p in platforms:
            if pygame.sprite.collide_rect(self, p):
                if yvel == 0:
                    self.wallCollide = True
                if xvel > 0:
                    self.rect.right = p.rect.left  # collide right
                if xvel < 0:
                    self.rect.left = p.rect.right  # collide left
                if yvel > 0:
                    self.rect.bottom = p.rect.top
                    self.onGround = True
                    self.canJump = True
                    self.yvel = 0
                if yvel < 0:
                    self.rect.top = p.rect.bottom
                    # if isinstance(p,Platform):
                    # self.onGround = True

总而言之,我不希望玩家在举起“向上箭头”时能够飞上墙。任何帮助或建议将不胜感激。

(对不起,如果我以不正确的格式或地点发布,我是这个网站的新手。)

1 个答案:

答案 0 :(得分:0)

这不是一个真正的编码答案,而是更多的设计答案。

视频游戏中跳墙的一种常见设计包括在跳墙时自动给角色“推”。考虑一下Megaman X系列 - 如果你跳到右边的墙上跳下去,它就会把你推到左边。你仍然可以保持正确地从墙上弹跳,但是你无法放大墙壁。

所以我的建议是让walljumps成为一种特殊类型的跳跃,让你的xvel在墙壁对面的方向上大幅提升。

或者,限制角色跳墙的频率。也许一个walljump会翻转一个标志,以阻止一定数量的帧进一步跳转。