Я относительно новичок в программировании и работаю над простой платформерной игрой, использующей pygame для дальнейшего изучения. До сих пор мне удалось создать спрайт игрока, который может двигаться (ускоряться и замедляться) до удара по краю платформы, а также может подпрыгивать и падать до удара по платформе.
Однако у меня возникают проблемы, когда мой изображение игрока слегка «трясется», когда оно находится над плиткой, что, в свою очередь, нарушает мою функцию прыжка, так как иногда спрайт игрока не прыгает, когда нажимается «пробел», а в других случаях это происходит.
(Я думаю, что то же самое происходит, когда спрайт игрока достигает края слева или справа, но не вызывает такой большой проблемы, но если я могу исправить одно, я, скорее всего, исправлю другое.)
Ниже приведен код для моих спрайтов: (Здесь содержатся функции столкновения и перемещения)
# Sprite classes for platform game
import pygame as pygame
from pygame.locals import *
from settings import *
vec = pygame.math.Vector2
class Player(pygame.sprite.Sprite):
def __init__(self, Game):
pygame.sprite.Sprite.__init__(self)
self.game = Game
self.image = pygame.Surface([40, 40])
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.pos = vec(200, HEIGHT-140)
self.vel = vec(0, 0)
self.acc = vec(0, 0)
def jump(self):
self.pos[1] += 5
hits = pygame.sprite.spritecollide(self, self.game.platforms, False)
self.pos[1] -= 5
if hits:
self.vel[1] -= 16
def keys(self):
self.acc = vec(0,PLAYER_GRAVITY)
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
self.acc.x = -PLAYER_ACCELERATION
if keys[K_RIGHT]:
self.acc.x = PLAYER_ACCELERATION
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
self.jump()
def collision_test(self, tiles):
collisions = []
for tile in tiles:
# check if player rect has collided with tile
if self.rect.colliderect(tile):
# IF ANY COLLISIONS ADD THAT TILE TO LIST
collisions.append(tile)
return collisions
def move(self, tiles):
# X AXIS
self.acc[0] += self.vel[0] * PLAYER_FRICTION
self.vel[0] += self.acc[0]
self.pos[0] += self.vel[0] + 0.5 * self.acc[0]
self.rect.topleft = self.pos
collisions = self.collision_test(self.game.tiles)
for tile in collisions:
if self.vel[0] > 0:
self.acc[0] = 0
self.vel[0] = 0
self.pos[0] = tile.rect.left - 40
if self.vel[0] < 0:
self.acc[0] = 0
self.vel[0] = 0
self.pos[0] = tile.rect.right
# Y AXIS
self.vel[1] = self.vel[1] + self.acc[1]
self.pos[1] += self.vel[1]
self.rect.topleft = self.pos
collisions = self.collision_test(self.game.tiles)
for tile in collisions:
if self.vel[1] > 0:
self.acc[1] = 0
self.vel[1] = 0
self.pos[1] = tile.rect.top - 40
if self.vel[1] < 0:
self.pos[1] = tile.rect.bottom + 4
def do(self):
self.keys()
self.move(self.game.tiles)
class Platform(pygame.sprite.Sprite):
def __init__(self, x, y, w, h):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((w, h))
self.image.fill(GREEN)
self.rect = pygame.Rect(x, y, w, h)
Ниже приведен код для программы main.py:
import pygame as pygame
import random, os
from settings import *
from sprites import *
class Game:
def __init__(self):
# INITALISE PYGAME & GAME WINDOW
pygame.init()
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption(TITLE)
self.clock = pygame.time.Clock()
self.running = True
def new(self):
# START NEW GAME
# NEW GROUPS
self.all_sprites = pygame.sprite.Group()
self.platforms = pygame.sprite.Group()
# NEW SPRITES
self.player = Player(self)
self.tiles = [Platform(0, HEIGHT - 80, WIDTH - 40, 80), Platform(WIDTH/2, HEIGHT - 160, 80, 80), Platform(0, HEIGHT - 160, 80, 80)]
# ADD SPRITES TO GROUPS
self.all_sprites.add(self.player, self.tiles)
self.platforms.add(self.tiles)
self.run()
def run(self):
# GAME LOOP
self.playing = True
while self.playing:
self.clock.tick(FPS)
self.events()
self.update()
self.draw()
def events(self):
self.player.do()
# Process input/events
for event in pygame.event.get():
# check for closing window
if event.type == pygame.QUIT:
if self.playing:
self.playing = False
self.running = False
def update(self):
self.all_sprites.update()
def draw(self):
# Draw/Render
self.screen.fill(WHITE)
self.screen.blit(background_image, (0,0))
self.all_sprites.draw(self.screen)
# ALWAYS FLIP THE DISPLAY LAST AFTER DRAWING
pygame.display.flip()
def start_screen(self):
pass
def game_over_screen(self):
pass
Game = Game()
game_folder = os.path.dirname(__file__)
img_folder = os.path.join(game_folder, "img")
background_image = pygame.image.load(os.path.join(img_folder, "background.png")).convert()
Game.start_screen()
while Game.running:
Game.new()
Game.game_over_screen()
pygame.quit()
Я попытался изменить код столкновения спрайта следующим образом (см. Конечную строку):
def move(self, tiles):
# X AXIS
self.acc[0] += self.vel[0] * PLAYER_FRICTION
self.vel[0] += self.acc[0]
self.pos[0] += self.vel[0] + 0.5 * self.acc[0]
self.rect.topleft = self.pos
collisions = self.collision_test(self.game.tiles)
for tile in collisions:
if self.vel[0] > 0:
self.acc[0] = 0
self.vel[0] = 0
self.rect.right = tile.rect.left
Но это приводит к тому, что спрайт игрока перемещается в верхний левый угол тайла, с которым он связывается с которой я не могу понять, зачем спасать мою жизнь.