pygame现实角度

时间:2018-09-18 16:33:13

标签: python pygame

我一直在做一个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 :(得分:0)

最简单的解决方法是使玩家实际上是两个对象。如果球与上半部分相交,则使其向上反弹;如果击中下半部分,则将其向下约束。更准确的方法是计算碰撞点,并基于此方法应用一些刚体碰撞响应数学,但是这种方法可能足以满足您的情况。

仅当球的移动速度不是太快时,这种简单的方法才有用,当一次打球时球通过了大部分球员时,但是对于您的情况来说可能就足够了,您需要做一些测试以确定是否值得额外的复杂性