【问题标题】:Python3, pygame 2D platformer, starting position (spawn), jump cutPython3, pygame 2D 平台游戏, 起始位置 (spawn), 跳切
【发布时间】:2018-08-20 10:28:18
【问题描述】:

玩家和生物的起始位置不能正常工作。当我在 SPRITES 中取出线时,Mob(即代码 atm 中的 #)该位置与“新”中的地图阅读器一起使用。 Atm 玩家和暴徒的起始位置为 0, 0 出于某种原因。我认为这与pos有关。

我尝试合并几个不同的教程,但我已经走到了这一步,但现在我卡在了起始位置,并在按键时进行了跳切。有任何想法吗?所有代码都在下面,在我的计算机上它们位于不同的文件中。

最好的祝福

MAIN.PY:

import pygame as pg #make alias for pygame as pg
import sys

#Import settings from file settings.py
from settings import *
from sprites import *
from tilemap import *
from os import path

class Game:
    def __init__(self):
        super().__init__()
        #init gamewindow
        pg.init()
        pg.mixer.init()
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        pg.display.set_caption(TITLE)
        self.clock = pg.time.Clock()
        self.font_name = pg.font.match_font(FONT_NAME)
        pg.key.set_repeat(500, 100)
        self.running = True
        self.load_data()

    def load_data(self): #load map from txt file
        game_folder = path.dirname(__file__)
        img_folder = path.join(game_folder, 'img')
        self.map = Map(path.join(game_folder, 'map.txt'))
        #player image
        self.player_img = pg.image.load(path.join(img_folder, PLAYER_IMG)).convert_alpha()
        self.player_img = pg.transform.scale(self.player_img, (60, 80))
        #monster image
        self.mob_img = pg.image.load(path.join(img_folder, MOB_IMG)).convert_alpha()
        self.mob_img = pg.transform.scale(self.mob_img, (60, 80))
        #background image
        self.wall_img = pg.image.load(path.join(img_folder, WALL_IMG)).convert_alpha()
        self.wall_img = pg.transform.scale(self.wall_img, (TILESIZE, TILESIZE))

    def new(self): #start a new game, load map, place player
        self.all_sprites = pg.sprite.Group()
        self.walls = pg.sprite.Group()
        self.mobs = pg.sprite.Group()
        for row, tiles in enumerate(self.map.data):
            for col, tile in enumerate(tiles):
                if tile == '1':
                    Wall(self, col, row)
                if tile == 'M':
                    Mob(self, col, row)
                if tile == 'P':
                    Player(self, col, row)
                    self.player = Player(self, col, row)

        self.camera = Camera(self.map.width, self.map.height)
        self.run()


    def run(self):
        #gameloop

    def update(self): #gameloop update
        self.all_sprites.update()
        if self.player.rect.bottom > self.map.height + TILESIZE * 5:
            self.playing = False
        self.camera.update(self.player) #follows the sprite, change player to other sprite to follow it

        # Gravity
        self.calc_grav()

        # Move left/right
        self.player.rect.x += self.player.change_x

        # See if we hit anything
        block_hit_list = pg.sprite.spritecollide(self.player, self.walls, False)
        for block in block_hit_list:
            # If we are moving right,
            # set our right side to the left side of the item we hit
            if self.player.change_x > 0:
                self.player.rect.right = block.rect.left
            elif self.player.change_x < 0:
                # Otherwise if we are moving left, do the opposite.
                self.player.rect.left = block.rect.right

        # Move up/down
        self.player.rect.y += self.player.change_y

        # Check and see if we hit anything
        block_hit_list = pg.sprite.spritecollide(self.player, self.walls, False)
        for block in block_hit_list:

            # Reset our position based on the top/bottom of the object.
            if self.player.change_y > 0:
                self.player.rect.bottom = block.rect.top
            elif self.player.change_y < 0:
                self.player.rect.top = block.rect.bottom

            # Stop our vertical movement
            self.player.change_y = 0

    def calc_grav(self):
        """ Calculate effect of gravity. """
        if self.player.change_y == 0:
            self.player.change_y = 1
        else:
            self.player.change_y += PLAYER_GRAVITY

    def events(self): #update game events

                if event.key == pg.K_SPACE:
                    self.player.jump()

            if event.type == pg.KEYUP:

    def draw(self): #game loop draw
        for sprite in (self.all_sprites):
            self.screen.blit(sprite.image, self.camera.apply(sprite))
        pg.display.flip()

    def draw_text(self, text, size, color, x, y):
        font = pg.font.Font(self.font_name, size)
        text_surface = font.render(text, True, color)
        text_rect = text_surface.get_rect()
        text_rect.midtop = (x, y)
        self.screen.blit(text_surface, text_rect)

精灵.PY:

import pygame as pg
from settings import *
vec = pg.math.Vector2

class Player(pg.sprite.Sprite):
    def __init__(self, game, x, y):
        self.groups = game.all_sprites
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = game.player_img
        self.rect = self.image.get_rect()
        self.change_x = 0
        self.change_y = 0
        self.pos = vec(x, y) * TILESIZE

    # Player-controlled movement:
    def go_left(self):
        """ Called when the user hits the left arrow. """
        self.change_x = -6

    def go_right(self):
        """ Called when the user hits the right arrow. """
        self.change_x = 6

    def stop(self):
        """ Called when the user lets off the keyboard. """
        self.change_x = 0

    def jump(self):
        """ Called when user hits 'jump' button. """

        # move down a bit and see if there is a platform below us.
        # Move down 2 pixels because it doesn't work well if we only move down 1
        # when working with a platform moving down.
        self.rect.y += 2
        platform_hit_list = pg.sprite.spritecollide(self, self.game.walls, False)
        self.rect.y -= 2

        # If it is ok to jump, set our speed upwards
        if len(platform_hit_list) > 0:
            self.change_y = PLAYER_JUMP


class Mob(pg.sprite.Sprite):
    def __init__(self, game, x, y):
        self.groups = game.all_sprites, game.mobs
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = game.mob_img
        self.rect = self.image.get_rect()
        self.pos = vec(x, y) * TILESIZE
        self.vel = vec(0, 0)
        self.acc = vec(0, 0)
        self.rect.center = self.pos

    def update(self):
        self.acc = vec(MOB_SPEED, 0)
        self.vel += self.acc * self.game.dt
#       self.pos = self.vel * self.game.dt + 0.5 * self.acc * self.game.dt ** 2
        self.rect.center = self.pos

#Temp wallmaker     
class Wall(pg.sprite.Sprite):
    def __init__(self, game, x, y):
        self.groups = game.all_sprites, game.walls
        pg.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = game.wall_img
        self.rect = self.image.get_rect()
        self.x = x
        self.y = y
        self.rect.x = x * TILESIZE
        self.rect.y = y * TILESIZE

SETTINGS.PY:

# Game options and settings
#Player settings
PLAYER_IMG = 'frame-1.png'
PLAYER_GRAVITY = 0.6
PLAYER_JUMP = -16

#Monster settings
MOB_IMG = 'monster.png'
MOB_SPEED = 150

【问题讨论】:

  • 请将您的代码缩减为minimum。这里没有人愿意调试数百行未知代码。
  • 我会这样做的,感谢您的反馈。

标签: python pygame


【解决方案1】:

如果我理解正确,你的问题就在这里:

self.pos = self.vel * self.game.dt + 0.5 * self.acc * self.game.dt ** 2

这基本上是说:

pos = vt + ½at²

您忘记了初始位置 pos0。应该是

pos = pos + vt + ½at²

或者只是

pos += vt + ½at²

【讨论】:

  • 这解决了暴民位置生成和移动的问题!谢谢!
【解决方案2】:

我发现了两个问题:

Player 类中,您必须设置矩形的中心。新创建的矩形默认具有topeft 坐标 (0, 0)。

class Player(pg.sprite.Sprite):
    def __init__(self, game, x, y):
        # ...
        self.pos = vec(x, y) * TILESIZE
        # Set the center of the rect to the self.pos vector.
        self.rect = self.image.get_rect(center=self.pos)

Game 类中,您将创建两个 Player 实例。删除这行Player(self, col, row)即可。

def new(self): #start a new game, load map, place player
    self.all_sprites = pg.sprite.Group()
    self.walls = pg.sprite.Group()
    self.mobs = pg.sprite.Group()
    for row, tiles in enumerate(self.map.data):
        for col, tile in enumerate(tiles):
            if tile == '1':
                Wall(self, col, row)
            if tile == 'M':
                Mob(self, col, row)
            if tile == 'P':
                # Here you create two player instances instead of one.
                Player(self, col, row)  # Delete this line.
                self.player = Player(self, col, row)

Mobs 似乎生成在正确的位置。如果还有其他问题,请告诉我。

【讨论】:

  • 它修复了播放器放置的问题!谢谢!
猜你喜欢
  • 1970-01-01
  • 2015-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多