Как бороться с «дрожащим» спрайтом и противоречивыми коллизиями? - PullRequest
0 голосов
/ 19 января 2020

Я относительно новичок в программировании и работаю над простой платформерной игрой, использующей 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 

Но это приводит к тому, что спрайт игрока перемещается в верхний левый угол тайла, с которым он связывается с которой я не могу понять, зачем спасать мою жизнь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...