Как сделать так, чтобы прямоугольник не падал через платформы?Не делая код слишком сложным или сложным (python 3 с pygame) - PullRequest
0 голосов
/ 18 февраля 2019

Как мне сделать так, чтобы прямоугольник не падал через платформы?Не делая код слишком сложным или сложным (python 3 с pygame)

Вот код, он просто должен быть простым платформером без какой-либо цели.Кто-то, пожалуйста, помогите, не усложняя код.

Заранее спасибо!

import pygame
pygame.init()

win = pygame.display.set_mode((750,750))
pygame.display.set_caption("GAME")

x = 50
y = 680

Width = 40
Height = 60
speed = 6
ScreenWidth = 750
ScreenHeight = 750
jumpCount = 10
isJump = False


run = True

while run:
    pygame.time.delay(50)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    keys = pygame.key.get_pressed()

    if keys[pygame.K_LEFT] and x > speed: 
        x -= speed


    if keys[pygame.K_RIGHT] and x < ScreenWidth - speed - Width:  
        x += speed

    if not(isJump): 
        if keys[pygame.K_SPACE]:
            isJump = True

    else:
        if jumpCount >= -10:
            y -= (jumpCount * abs(jumpCount)) * 0.5
            jumpCount -= 1
            speed = 8
        else: 
            jumpCount = 10
            isJump = False
            speed = 6

    win.fill((0,0,0))
    pygame.draw.rect(win, (255,0,0), (x, y, Width, Height))
    pygame.draw.rect(win, (0,255,0), (100, 600, 300, 50))
    pygame.draw.rect(win, (0,255,0), (300, 400, 300, 50)) 
    pygame.display.update() 

pygame.quit()

Мой пост, по-видимому, в основном кодовый, поэтому по этой причине я просто выложу это предложение здесь.

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Вот моя версия.Немного глючит, но, по крайней мере, вы можете перепрыгивать через платформы:

enter image description here

Код:

import pygame

window_w = 750
window_h = 750

player_x = 50
player_y = player_y_min = bottom = 680
player_w = 40
player_h = 60
player_speed = 6
player_jump_count = 10
jump = False

pygame.init()
win = pygame.display.set_mode((window_w, window_h))
pygame.display.set_caption('GAME')

rectangle1 = 100, 600, 300, 50
rectangle2 = 300, 400, 300, 50
platform1 = pygame.draw.rect(win, (0, 255, 0), rectangle1)
platform2 = pygame.draw.rect(win, (0, 255, 0), rectangle2)
player = pygame.draw.rect(win, (255, 0, 0), (player_x, player_y, player_w, player_h))

run = True
while run:
    pygame.time.delay(50)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    keys = pygame.key.get_pressed()

    if (keys[pygame.K_LEFT] or keys[pygame.K_a]) and player_x > player_speed:
        player_x -= player_speed

    if (keys[pygame.K_RIGHT] or keys[pygame.K_d]) and player_x < window_w - player_speed - player_w:
        player_x += player_speed

    if keys[pygame.K_SPACE] and not jump:
            player_y += 1  # small hack to make this statement False: "player_y != player_y_min"
            jump = True

    if jump:

        if player.colliderect(platform1) or player.colliderect(platform2):
            if player_jump_count > 0:
                player_jump_count *= -1
                player_y += player_speed
            else:
                player_y_min = rectangle1[1]-player_h if player.colliderect(platform1) else rectangle2[1]-player_h

        if player_y != player_y_min:
            player_y -= (player_jump_count * abs(player_jump_count)) * 0.5
            player_jump_count -= 1
        else:
            player_jump_count = 10
            jump = False

    if not player.colliderect(platform1) and not player.colliderect(platform2) and player_y_min != bottom:
        player_y_min = bottom

    player_y = player_y if player_y < player_y_min else player_y_min

    win.fill((0, 0, 0))
    platform1 = pygame.draw.rect(win, (0, 255, 0), rectangle1)
    platform2 = pygame.draw.rect(win, (0, 255, 0), rectangle2)
    player = pygame.draw.rect(win, (255, 0, 0), (player_x, player_y, player_w, player_h))
    pygame.display.update()

pygame.quit()
0 голосов
/ 19 февраля 2019

Хорошо.Это действительно отличный вопрос о базовом программировании.

Как сделать так, чтобы прямоугольник не падал через платформы.[Простыми словами]

Позвольте мне сначала ответить «без усложнения кода [...] до сложного».

Когда вы пишете программы, они пишутся так, чтобынастолько просто, насколько это возможно.Если они «слишком продвинуты», это плохое программирование.Иногда должно быть много кода, потому что он покрывает множество «краевых условий», и это приводит к тому, что код выглядит сложным, но на самом деле это не так, его просто больше.

Итак: Как сделать так, чтобы прямоугольник не падал через платформы ... сначала давайте переформулируем объем работы ~

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

Хотя это описание более сложное, оно более полно описывает программу, которая должна быть написана, и фактически облегчает проектирование.

Одним из замечательных инструментов в библиотеке PyGame является класс спрайтов .Эта библиотека поддерживает прямоугольные объекты с простым обнаружением столкновений.Обычно люди используют это с растровым изображением, чтобы заполнить прямоугольник.Теперь спрайт PyGame - это питон class.Класс - это object, который является просто именем для набора данных и функций, которые имеют что-то общее.

Давайте создадим его сейчас:

class FallingSprite( pygame.sprite.Sprite ):
    def __init__( self ):
        pygame.sprite.Sprite.__init__( self )
        self.image       = pygame.image.load("flower_pot.png").convert_alpha()
        self.rect        = self.image.get_rect()
        self.rect.center = ( WINDOW_WIDTH//2, -50 )
        self.fall_speed  = 150 # pixels / second
        self.last_update = int( time.time() * 1000.0 )

    def update( self ):
        # There should have been movement since the last update
        # calculate the new position
        time_now    = int( time.time() * 1000.0 )
        time_change = time_now - self.last_update      # How long since last update?
        if ( time_change > 0 ):
            distance_moved   = time_change * self.fall_speed / 1000
            now_x, now_y     = self.rect.center        # Where am I, right now
            updated_y        = now_y + distance_moved
            self.rect.center = ( now_x, updated_y )
            self.last_update = time_now
            # Did we fall off the bottom of the screen?
            if ( updated_y > WINDOW_HEIGHT ):
                self.kill()

    def stop( self ):
        self.fall_speed  = 0

Итак, это классдля падающего спрайта.Функция __init__() является особенной и вызывается при создании спрайта.Он загружает растровое изображение для представления прямоугольника и устанавливает несколько статистических данных об объекте - например, где он находится на экране, как быстро он падает.Интересно отметить, что мы используем системные часы для определения положения прямоугольника.Он начинается в верхней части экрана, но каждый раз, когда вызывается функция спрайта update() (обычно каждый кадр), позиция Y увеличивается (перемещение объекта вниз по экрану) в зависимости от реального времени вызова.Функция stop() используется для отмены падения.

Итак, теперь у нас есть «падающий прямоугольник», теперь нужно несколько «платформ» для его блокировки (или нет).Мы снова используем объект спрайта PyGame, но, учитывая, что эта платформа не перемещается (или не изменяется вообще), она немного проще.Тем не менее, требуется координата position в качестве параметра, когда она создается.Таким образом, мы можем сделать их несколько в разных позициях.

class PlatformSprite( pygame.sprite.Sprite ):
    def __init__( self, position ):
        pygame.sprite.Sprite.__init__( self )
        self.image       = pygame.image.load("brick_32.png").convert_alpha()
        self.rect        = self.image.get_rect()
        self.rect.center = ( position )

Платформы не двигаются, поэтому функции update() нет.

Следующий шаг - определить, когдападающий спрайт попадает в спрайт платформы.Еще одна полезная функция в библиотеке спрайтов - обнаружение коллизий.Фактически, возможно иметь группу спрайтов , которая может мгновенно определить, сталкивается ли спрайт с чем-либо в группе.Это то, что нам действительно нужно знать.Всякий раз, когда падающий спрайт перемещается, нам нужно знать, ударил ли он по любому из спрайтов платформы.

Поэтому мы создаем pygame.sprite.Group() для хранения всех платформ.Мы также делаем один для одного падающего спрайта, но только потому, что это делает программу проще.

Чтобы узнать, попадет ли падающий спрайт на спрайты платформы, легко использовать функцию PyGame pygame.sprite.spritecollide().Это берет один спрайт и группу спрайтов и возвращает список пересекающихся спрайтов.Это делает обнаружение столкновений слишком простым:

FALLERS.update() # re-position the flower-pot
# Did it hit anything
if ( len( pygame.sprite.spritecollide( flower_pot_sprite, PLATFORMS, False ) ) > 0 ):
    flower_pot_sprite.stop()

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

import pygame
import random
import time

# Window size
WINDOW_WIDTH  = 400
WINDOW_HEIGHT = 400
# background colour
SKY_BLUE      = (161, 255, 254)


class FallingSprite( pygame.sprite.Sprite ):
    """ A falling flower-pot sprite.  Falls at a constant velocity in real-time """
    def __init__( self ):
        pygame.sprite.Sprite.__init__( self )
        self.image       = pygame.image.load("flower_pot.png").convert_alpha()
        self.rect        = self.image.get_rect()
        self.rect.center = ( WINDOW_WIDTH//2, -50 )
        self.fall_speed  = 150 # pixels / second
        self.last_update = int( time.time() * 1000.0 )

    def update( self ):
        # There should have been movement since the last update
        # calculate the new position
        time_now    = int( time.time() * 1000.0 )
        time_change = time_now - self.last_update      # How long since last update?
        if ( self.fall_speed > 0 and time_change > 0 ):
            distance_moved   = time_change * self.fall_speed / 1000
            now_x, now_y     = self.rect.center        # Where am I, right now
            updated_y        = now_y + distance_moved
            self.rect.center = ( now_x, updated_y )
            self.last_update = time_now
            # Did we fall off the bottom of the screen?
            if ( updated_y > WINDOW_HEIGHT ):
                self.kill()

    def stop( self ):
        self.fall_speed  = 0


class PlatformSprite( pygame.sprite.Sprite ):
    """ A stationay sprite"""
    def __init__( self, position ):
        pygame.sprite.Sprite.__init__( self )
        self.image       = pygame.image.load("brick_32.png").convert_alpha()
        self.rect        = self.image.get_rect()
        self.rect.center = ( position )

    def udpate( self ):
        # does not move
        pass

### MAIN
pygame.init()
WINDOW    = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE )
pygame.display.set_caption("Flowerpot")

# Add some sprites
FALLERS   = pygame.sprite.Group()   # a group, for a single sprite
flower_pot_sprite = FallingSprite()
FALLERS.add( flower_pot_sprite )
PLATFORMS = pygame.sprite.Group()   # a group for all the plaform sprites
for i in range(20):
    # create a platform at a random position
    new_platform = PlatformSprite( ( random.randrange( 0, WINDOW_WIDTH ), random.randrange( 0, WINDOW_HEIGHT ) ) )
    PLATFORMS.add( new_platform )


clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.VIDEORESIZE ):
            WINDOW_WIDTH  = event.w
            WINDOW_HEIGHT = event.h
            WINDOW  = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE )

    # Move the flower-pot, did it hit anything?
    FALLERS.update() # re-position the flower-pot
    if ( len( pygame.sprite.spritecollide( flower_pot_sprite, PLATFORMS, False ) ) > 0 ):
        flower_pot_sprite.stop()

    # Re-draw the screen
    WINDOW.fill( SKY_BLUE )
    FALLERS.draw( WINDOW )    # draw the flower-pot
    PLATFORMS.draw( WINDOW )  # draw the platforms
    pygame.display.update()
    pygame.display.flip()
    # Update the window, but not more than 60fps
    clock.tick_busy_loop( 60 )

pygame.quit()

flower_pot.png brick_32.png

animated demo image.gif

Конечно, будучи такой простой программой, есть ошибки.Например: что происходит, когда падающий объект падает так быстро, чтобы он никогда не существовал в сталкивающейся позиции ?!В результате он может «провалиться» в кирпич - в один момент он был до кирпича, в следующий update() он уже прошел кирпич.Ого.

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