玩家和小怪的起始位置无法正常工作。当我在SPRITES,Mob(即代码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)
SPRITES.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
答案 0 :(得分: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²
答案 1 :(得分:0)
我发现了两个问题:
在Player
课程中,你必须设置矩形的中心。默认情况下,新创建的rects具有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)
Mob
似乎在正确的位置产生。如果有更多问题,请告诉我。