为什么我在pygame中的玩家角色有时会消失在瓷砖后面,但仍然会移动? [英] Why does my player character in pygame sometimes dissappear behind tiles, yet still move?

查看:41
本文介绍了为什么我在pygame中的玩家角色有时会消失在瓷砖后面,但仍然会移动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一般对python还是比较陌生的(大约一个星期的知识),并且我正在做一个相当基本的pygame,并考虑到一个更大的项目.我写的pygame的工作方式应该如何,除了一件我似乎无法弄清为什么会发生的事情之外,也就是说,当我启动游戏时,角色有时是不可见的.这会随着瓷砖的变化而变化,并且每次游戏开始时都是不同的瓷砖.现在我一生都无法弄清楚为什么会发生这种情况,我希望这里的人可能会看到我看不到的东西.

I'm fairly new to python in general (about a weeks knowledge) and I am making a fairly basic pygame with a bigger project in mind. The pygame I've written works how it should except for one thing I can't seem to figure out why it happens, and that is when I start up the game, the character is sometimes invisible. This changes from tile to tile and each time the game starts it's a different tile. Now I for the life of me can't figure out why this is happening and I was hoping somebody here might see what I can't.

谢谢,这里有一些图片.

Thanks in advance, here are some images.

我的主:

import pygame as pg
import sys
from os import path
from settings import *
from sprites import *
from tilemap import *

class Game:
def __init__(self):
    pg.init()
    self.screen = pg.display.set_mode((WIDTH, HEIGHT))
    pg.display.set_caption(TITLE)
    self.clock = pg.time.Clock()
    pg.key.set_repeat(500, 100)
    self.load_data()

def load_data(self):
    game_folder = path.dirname(__file__)
    img_folder = path.join(game_folder, 'img')
    self.map = Map(path.join(game_folder, 'map.txt'))
    self.player_img = pg.image.load(path.join(img_folder, PLAYER)).convert_alpha()
    self.floor_img = pg.image.load(path.join(img_folder, FLOOR)).convert()
    self.wall_img = pg.image.load(path.join(img_folder, WALL)).convert()
    self.water_img = pg.image.load(path.join(img_folder, WATER)).convert()
    self.goal_img = pg.image.load(path.join(img_folder, GOAL)).convert()

def new(self):
    # initialize all variables and do all the setup for a new game
    self.all_sprites = pg.sprite.Group()
    self.walls = pg.sprite.Group()
    self.floors = pg.sprite.Group()
    self.water = pg.sprite.Group()
    self.goal = pg.sprite.Group()
    for row, tiles in enumerate(self.map.data):
        for col, tile in enumerate(tiles):
            if tile == 'X':
                Wall(self, col, row)
            if tile == 'W':
                Water(self, col, row)
            if tile == '.':
                Floor(self, col, row)
            if tile == 'G':
                Goal(self, col, row)
            if tile == 'P':
                self.player = Player(self, col, row)
                Floor(self, col, row)

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

def run(self):
    # game loop - set self.playing = False to end the game
    self.playing = True
    while self.playing:
        self.dt = self.clock.tick(FPS) / 1000
        self.events()
        self.draw()
        self.update()

def quit(self):
    pg.quit()
    sys.exit()

def update(self):
    # update portion of the game loop
    self.all_sprites.update()
    self.camera.update(self.player)

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

def events(self):
    # catch all events here
    for event in pg.event.get():
        if event.type == pg.QUIT:
            self.quit()
        if event.type == pg.KEYDOWN:
            if event.key == pg.K_ESCAPE:
                self.quit()
            if event.key == pg.K_LEFT:
                self.player.move(dx=-1)
            if event.key == pg.K_RIGHT:
                self.player.move(dx=1)
            if event.key == pg.K_UP:
                self.player.move(dy=-1)
            if event.key == pg.K_DOWN:
                self.player.move(dy=1)

# create the game object
g = Game()
while True:
g.new()
g.run()

我的设置:

DARKGREY = (40, 40, 40)

# game settings
WIDTH = 1280   # 16 * 64 or 32 * 32 or 64 * 16
HEIGHT = 720  # 16 * 48 or 32 * 24 or 64 * 12
FPS = 60
TITLE = "Code Avontuur"
BGCOLOR = DARKGREY

TILESIZE = 100
GRIDWIDTH = WIDTH / TILESIZE
GRIDHEIGHT = HEIGHT / TILESIZE

PLAYER = 'player.png'
WALL = 'wall.jpg'
FLOOR = 'floor.jpg'
WATER = 'water.jpg'
GOAL = 'goal.jpg'

我的地图:

XXXXXXXXXXXXXXXX
XP.....X.....XWX
XXX.XX.XXX.XXXXX
XXX..X.XX..XXXXX
XXXX...X..XXXXXX
XWWWX.XX.XXWWWWX
XXXXX....XXXXXXX
XXXXXXXX......GX
XXXXXXXXXXXXXXXX

我的精灵:

import pygame as pg
from PIL import Image
from settings import *

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.x = x
    self.y = y

def move(self, dx=0, dy=0):
    if not self.collide(dx, dy):
        self.x += dx
        self.y += dy

def collide(self, dx=0, dy=0):
    for wall in self.game.walls:
        if wall.x == self.x + dx and wall.y == self.y + dy:
            return True
    for water in self.game.water:
        if water.x == self.x +dx and water.y == self.y +dy:
            return True
    return False

def update(self):
    self.rect.x = self.x * TILESIZE
    self.rect.y = self.y * TILESIZE

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

class Water(pg.sprite.Sprite):
def __init__(self, game, x, y):
    self.groups = game.all_sprites, game.water
    pg.sprite.Sprite.__init__(self, self.groups)
    self.game = game
    self.image = game.water_img
    self.rect = self.image.get_rect()
    self.x = x
    self.y = y
    self.rect.x = x * TILESIZE
    self.rect.y = y * TILESIZE

class Floor(pg.sprite.Sprite):
def __init__(self, game, x, y):
    self.groups = game.all_sprites, game.floors
    pg.sprite.Sprite.__init__(self, self.groups)
    self.game = game
    self.image = game.floor_img
    self.rect = self.image.get_rect()
    self.x = x
    self.y = y
    self.rect.x = x * TILESIZE
    self.rect.y = y * TILESIZE

class Goal(pg.sprite.Sprite):
def __init__(self, game, x, y):
    self.groups = game.all_sprites, game.goal
    pg.sprite.Sprite.__init__(self, self.groups)
    self.game = game
    self.image = game.goal_img
    self.rect = self.image.get_rect()
    self.x = x
    self.y = y
    self.rect.x = x * TILESIZE
    self.rect.y = y * TILESIZE

我的地图处理程序:

import pygame as pg
from settings import *

class Map:
def __init__(self, filename):
    self.data = []
    with open(filename, 'rt') as f:
        for line in f:
            self.data.append(line.strip())

    self.tilewidth = len(self.data[0])
    self.tileheight = len(self.data)
    self.width = self.tilewidth * TILESIZE
    self.height = self.tileheight * TILESIZE

class Camera:
def __init__(self, width, height):
    self.camera = pg.Rect(0, 0, width, height)
    self.width = width
    self.height = height

def apply(self, entity):
    return entity.rect.move(self.camera.topleft)

def update(self, target):
    x = -target.rect.x + int(WIDTH / 2)
    y = -target.rect.y + int(HEIGHT / 2)

    #Limit scrolling off map
    x = min(0, x)
    y = min(0, y)
    x = max(-(self.width - WIDTH), x)
    y = max(-(self.height - HEIGHT), y)
    self.camera = pg.Rect(x, y, self.width, self.height)

我希望这里的任何人都能看到我看不到的东西,因为此时我陷入困境并迷路了.

I hope anybody here can see what I cant, because I'm stuck and lost at this point.

推荐答案

您的问题是您绘制子画面的顺序.

Your problem is the order in which your sprites a drawn.

使用

Instead of a regular Group, use a LayeredUpdates group.

然后给您的精灵一个 _layer 属性(*).这样,您可以控制精灵在屏幕上绘制的顺序.

Then give your sprites a _layer property(*). This way you can control the order in which your sprites a drawn on the screen.

这里是示例.

更改您的 Game 类:

...
def new(self):
    # initialize all variables and do all the setup for a new game
    self.all_sprites = pg.sprite.LayeredUpdates() # <<--- change here
    self.walls = pg.sprite.Group()
    self.floors = pg.sprite.Group()
    self.water = pg.sprite.Group()
    self.goal = pg.sprite.Group()
    ...

更改为您的 Player 类:

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.x = x
        self.y = y
        self._layer = 1 # <<--- add this line


由于您实际上并未使用Group进行绘图,因此可以将其保留为简单的 Group ,只需更改draw函数即可按图层对精灵进行排序:

Since you don't actually use the Group for drawing, you could leave it as simple Group and just change your draw function to sort the sprites by layer:

for sprite in sorted(self.all_sprites, lambda i, s: s._layer):
    ...

或对于Python 3:

or for Python 3:

for sprite in sorted(self.all_sprites, key=lambda s: s._layer):
    ...


*文档说的是 layer ,但实际上是 _layer

这篇关于为什么我在pygame中的玩家角色有时会消失在瓷砖后面,但仍然会移动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆