Попытка привнести гравитацию в игру, похожую на платформу Mario в Pygame - PullRequest
1 голос
/ 28 апреля 2020

Я работаю над созданием игры, похожей на осла-конга, в которой Марио попытается выйти на верхнюю платформу. Для этого мне нужно, чтобы Марио обладал способностью прыгать и падать с гравитацией.

Я работал над реализацией гравитации, но когда я попробовал что-то, что, как я думал, сработало, элемент гравитации сработал, но Аватар игрока начал глючить хаотично. Я считаю, что это потому, что он движется вверх и вниз несколько раз в секунду. Любая помощь в том, как решить эту проблему и получить работу моего гравитационного механизма, будет принята с благодарностью.

Вот мой код:

from pygame.locals import *
import itertools

global moves

pygame.init()
screen_height = 800
screen_width = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Donkey Kong')

FPS = 30

player = pygame.image.load('mario.bmp') #facing right
player_rect = player.get_rect()
player_rect.center = (80, 700)

move_rate = 3
move_left = False
move_right = False
move_up = False
move_down = False

touch_ladder = True
ladder_move_up = False
ladder_move_down = False

gravity = 4
gravity_check = True

jump = False
jump_moves = 0

platform = pygame.image.load('platform.bmp')
platforms = []
platform_x = [60,120,180,240,300,360,420,480]

platform_y = [120,240,360,480,600,720]

ladders = []
ladder_x = [300, 480, 240, 300, 180, 420, 240, 120, 60, 420, 300, 480]
ladder_y = []

class Platform():

    def __init__(self, y, x, x_index, y_index):
        self.platform = platform
        self.rect = self.platform.get_rect()
        self.x_index = x_index
        self.y_index = y_index
        if (self.y_index % 2) != 0 :
            self.rect.y = y + (2 * self.x_index)
        else:
            self.rect.y = y - (2 * self.x_index)
        self.rect.x = x  

    def draw_platform(self):
        if (self.rect.y % 240) != 0:
            screen.blit(self.platform, (self.rect.x, self.rect.y )) #up
        else:
            screen.blit(self.platform, (self.rect.x, self.rect.y)) #down


class Ladder():

    def __init__(self, y, x, y_index, x_index):
        self.y_index = y_index
        self.x_index = x_index
        if (y % 240) != 0:
            self.height = abs(((platform_y[self.y_index - 1] + (2 *(2 * self.x_index)))) - y)
            self.rect = pygame.Rect(x, y - self.height, 20, self.height)
            self.rect.y -= (2 * self.x_index)
        else:
            self.height = abs(((platform_y[self.y_index - 1] - (2 * (2 * self.x_index)))) - y)
            self.rect = pygame.Rect(x, y - self.height, 20, self.height)
            self.rect.y += (2 * self.x_index)
        self.rungs = 0

    def draw_ladder(self):
        #pygame.draw.rect(screen, (255,0,0), self.rect)
        pygame.draw.rect(screen, (255, 255, 255), (self.rect.x, self.rect.y , 4, self.height))
        pygame.draw.rect(screen, (255, 255, 255), (self.rect.x + 16, self.rect.y, 4, self.height))

    def draw_rungs(self):
        pygame.draw.line(screen, (255, 255, 255), (self.rect.x, self.rect.y+self.rungs),(self.rect.x + 19, self.rect.y+self.rungs), 4)
        self.rungs += 14

y_multiplied = platform_y.copy()
y_multiplied.extend(platform_y)
y_multiplied.sort()
print(y_multiplied)
print(ladder_x)

for y in platform_y:
    if platform_y.index(y) < 6:
        for x in platform_x:
            platforms.append(Platform(y, x, platform_x.index(x), platform_y.index(y)))

for y, x in zip(y_multiplied, ladder_x):
    ladders.append(Ladder(y, x, platform_y.index(y), platform_x.index(x)))


while True:
    gravity_check = True

    screen.fill((105, 105, 255))
    screen.blit(player, player_rect)


    for p in platforms:
        p.draw_platform()
        if player_rect.colliderect(p.rect):
            player_rect.bottom = p.rect.top
            gravity_check = False

    for l in ladders:
        if player_rect.colliderect(l.rect):
            touch_ladder = True
            gravity_check = False

    if gravity_check == True:
        player_rect.y += gravity

    for l in ladders:
        if l.y_index > 0:
            l.draw_ladder()
            for i in range(l.height // 14):
                l.draw_rungs()
            l.rungs = 0


    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
            pygame.quit()
        if event.type == KEYDOWN:
            if event.key == K_LEFT:
                player = pygame.transform.flip(player, True, False)
                move_left = True
            if event.key == K_RIGHT:
                move_right = True
                player = pygame.image.load('mario.bmp')
            if event.key == K_UP:
                jump = True
            if event.key == K_DOWN:
                player_rect.y += move_rate

        if event.type == KEYUP:
            if event.key == K_LEFT:
                move_left = False
            if event.key == K_RIGHT:
                move_right = False

    if move_left == True:
        player_rect.x -= move_rate
    if move_right == True:
        player_rect.x += move_rate

    if ladder_move_up == True:
        player_rect.y -= move_rate

    if jump == True:
        gravity_check = True
        if jump_moves <= 60:
            player_rect.y -= 10
            jump_moves += 10
        else:
            jump_moves = 0
            jump = False


    pygame.display.update()
    pygame.time.Clock().tick(FPS)``` 

1 Ответ

3 голосов
/ 28 апреля 2020

Эта строка вызывает проблемы:

if gravity_check == True:
        player_rect.y += gravity

Если вы поставите print():

if gravity_check == True:
        print(player_rect.y)
        player_rect.y += gravity
        print(player_rect.y)

Вы увидите, что player_rect.y постоянно меняется между 56 and 60 (для моего случайное изображение) в начале. Поэтому вам нужно предотвратить изменение player_rect.y в нескольких местах одновременно, чтобы избежать такого поведения. Также, как я упоминал в комментарии, старайтесь избегать загрузки изображений внутри l oop, потому что это потребляет много ресурсов.

РЕДАКТИРОВАТЬ:

 for p in platforms:
        p.draw_platform()
        if player_rect.colliderect(p.rect):
            player_rect.bottom = p.rect.top + gravity
            gravity_check = False

player_rect.bottom = p.rect.top + gravity добавление gravity значение решит проблему. И это строка кода, которая вызывает изменения в player_rect.y, а также строка, упомянутая в исходном посте. Надеюсь, это решит вашу проблему.

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