【问题标题】:Pygame realistic anglesPygame 逼真的角度
【发布时间】:2018-09-19 00:49:41
【问题描述】:

我一直在制作一个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()

【问题讨论】:

  • 水平方向是什么意思?对我来说它是垂直方向的,正如你所期望的那样
  • 我明白了……但是如果球员是汽车,球怎么会撞到球员的底部?
  • 如果球击中矩形的底边
  • 嗯,好的。对我来说听起来不像一辆车,但我想没有必要为此争论。如果您的模拟中涉及的速度足够低,您可以在圆形和矩形之间进行静态碰撞检测。有关示例方法,请参见 this post
  • 谢谢,不过仍然不知道如何为我自己的代码实现它,你能帮忙吗?

标签: python pygame


【解决方案1】:

最简单的解决方法是让玩家表现得实际上是两个对象。如果球与上半部相交,则将其向上反弹,如果击中下半部,则将其向下束缚。更准确的方法是计算碰撞点并在此基础上应用一些刚体碰撞响应数学,但该方法可能对您的情况足够好。

更简单的方法只有在球移动得不太快的情况下才有效,当球在一个游戏滴答中穿过大部分玩家时,但它可能对你的情况来说已经足够了,你需要做一些测试以确定是否值得额外的复杂性

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-09
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    相关资源
    最近更新 更多