Пигмеи реалистичные углы - PullRequest
       9

Пигмеи реалистичные углы

0 голосов
/ 18 сентября 2018

Я играю в pygame игру, где 2 машины бьют по мячу вокруг поля.Когда игрок сталкивается с мячом, мяч движется вперед, однако, если нижняя часть игрока попадает в верхнюю часть мяча, мяч все равно движется вверх, понимая, как код указывает мячу идти вверх после контакта.Тем не менее, я хочу, чтобы мяч реалистично падал вниз, когда мяч ударяет вниз.У кого-нибудь есть идеи?

import pygame as pg
from pygame.math import Vector2


pg.init()
LIGHTBLUE = pg.Color('lightskyblue2')
DARKBLUE = pg.Color(11, 8, 69)

screen = pg.display.set_mode((800, 600))
width, height = screen.get_size()
clock = pg.time.Clock()
# You need surfaces with an alpha channel for the masks.
bluecar = pg.Surface((60, 30), pg.SRCALPHA)
bluecar.fill((0,0,255))
BALL = pg.Surface((30, 30), pg.SRCALPHA)
pg.draw.circle(BALL, [0,0,0], [15, 15], 15)
ball_pos = Vector2(395, 15)
ballrect = BALL.get_rect(center=ball_pos)
ball_vel = Vector2(0, 0)
mask_blue = pg.mask.from_surface(bluecar)
mask_ball = pg.mask.from_surface(BALL)
pos_blue = Vector2(740, 500)  # Just use the pos vector instead of x, y.
bluerect = bluecar.get_rect(center = pos_blue)
vel_blue = Vector2(0, 0)  # Replace x_change, y_change with vel_blue.
# A constant value that you add to the y-velocity each frame.
GRAVITY = .5

ground_y = height - 100
timer = 3
dt = 1

def bluejumps():
    if timer > 0: 
        vel_blue.y = -12

if pos_blue.y > 469:
    timer -= dt

done = False
while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True
        elif event.type == pg.KEYDOWN:
            if event.key == pg.K_a:
                vel_blue.x = -5
            elif event.key == pg.K_d:
                vel_blue.x = 5
            elif event.key == pg.K_w:
                bluejumps()
        elif event.type == pg.KEYUP:
            if event.key == pg.K_a and vel_blue.x < 0:
                vel_blue.x = 0
            elif event.key == pg.K_d and vel_blue.x > 0:
                vel_blue.x = 0
        if bluerect.bottom >= ground_y:
            bluerect.bottom = ground_y
            pos_blue.y = bluerect.centery
            #vel_blue.y = 0
            timer = 3


    ball_vel.y += GRAVITY  # Accelerate downwards.

    ball_pos += ball_vel  # Move the ball.
    ballrect.center = ball_pos  # Update the rect.
    # Bounce when the ball touches the bottom of the screen.
    if ballrect.bottom >= ground_y:
        # Just invert the y-velocity to bounce.
        ball_vel.y *= -0.7  # Change this value to adjust the elasticity.
        ball_vel.x *= .95  # Friction
        # Don't go below the ground.
        ballrect.bottom = ground_y
        ball_pos.y = ballrect.centery
    # Left and right wall collisions.
    if ballrect.left < 0:
        ball_vel.x *= -1
        ballrect.left = 0
        ball_pos.x = ballrect.centerx
    elif ballrect.right > width:
        ball_vel.x *= -1
        ballrect.right = width
        ball_pos.x = ballrect.centerx
    if ballrect.top <= 0:
        # Just invert the y-velocity to bounce.
        ball_vel.y *= -0.4  # Change this value to adjust the elasticity.
        ballrect.top = 1
        ball_pos.y = ballrect.centery

    # Add the GRAVITY value to vel_blue.y, so that
    # the object moves faster each frame.
    vel_blue.y += GRAVITY
    pos_blue += vel_blue
    bluerect.center = pos_blue  # You have to update the rect as well.

    # Stop the object when it's near the bottom of the screen.
    if bluerect.bottom >= ground_y:
        bluerect.bottom = ground_y
        pos_blue.y = bluerect.centery
        vel_blue.y = 0
        timer = 3
    if bluerect.x < 0:
        bluerect.x = 0
        pos_blue.x = bluerect.centerx
    elif bluerect.right > width:
        bluerect.right = width
        pos_blue.x = bluerect.centerx
    print(timer)

    offset_blue = bluerect[0] - ballrect[0], bluerect[1] - ballrect[1]
    overlap_blue = mask_ball.overlap(mask_blue, offset_blue)
    if overlap_blue:  # Blue collides with the ball.
        if vel_blue.x != 0:  # Player is moving.
            ball_vel = Vector2(vel_blue.x, -17)
        else:  # If the player is standing, I just update the vel.y.
            ball_vel.y = -17

    # Draw everything.
    screen.fill(LIGHTBLUE)
    pg.draw.line(screen, (0, 0, 0), (0, ground_y), (width, ground_y))
    screen.blit(bluecar, bluerect)  # Blit it at the rect.
    screen.blit(BALL, ballrect)

    pg.display.update()
    dt = clock.tick(60)/1000

pg.quit()

1 Ответ

0 голосов
/ 18 сентября 2018

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

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

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