首页 > 解决方案 > 在精灵中向前移动

问题描述

我一直在制作一个游戏,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()
pg.display.set_caption("Super Acrobatic Rocket Powered Battle Polygons(SARPBP)")
x = 740
y = 500
x2 = 395
y2 = 15
x_change = 0
y_change = 0
bluespeed = 5
ground_pos = 70
on_ground = False

bluecar = pg.Surface((60, 30))
bluecar.fill((0,0,255))
bluegoal = pg.Surface((60,150))
bluegoal.fill((0,0,255))
BALL = pg.Surface((30, 30), pg.SRCALPHA)
pg.draw.circle(BALL, [0,0,0], [15, 15], 15)
ball_pos = Vector2(x2, y2)
ballrect = BALL.get_rect(center=ball_pos)
ball_vel = Vector2(0, 0)
ball_mask = pg.mask.from_surface(BALL)
mask_blue = pg.mask.from_surface(bluecar)
mask_ball = pg.mask.from_surface(BALL)
pos_blue = Vector2(x,y)
bluerect = bluecar.get_rect(center = pos_blue)
vel_blue = Vector2(bluespeed,0)
# A constant value that you add to the y_change each frame.
GRAVITY = .5
GRAVITY2 = .5
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:
                x_change = -5
            elif event.key == pg.K_d:
                x_change = 5
            elif event.key == pg.K_w:
                if on_ground:  # Only jump if the player is on_ground.
                    y_change = -12
                    on_ground = False
        elif event.type == pg.KEYUP:
            if event.key == pg.K_a and x_change < 0:
                x_change = 0
            elif event.key == pg.K_d and x_change > 0:
                x_change = 0
    ball_vel.y += GRAVITY  # Accelerate downwards.
    ball_pos += ball_vel  # Move the ball.
    ballrect.center = ball_pos
    # Bounce when the ball touches the bottom of the screen.
    if ballrect.bottom >= height - ground_pos:
        # Just invert the y-velocity to bounce.
        ball_vel.y *= -0.7  # Change this value to adjust the elasticity.
        # Don't go below the ground.
        ballrect.bottom = height - ground_pos
        ball_pos.y = ballrect.centery

    # Add the GRAVITY value to y_change, so that
    # the object moves faster each frame.
    y_change += GRAVITY
    x += x_change
    y += y_change

    # Stop the object when it's near the bottom of the screen.
    if y >= height - 100:
        y = height - 100
        y_change = 0
        on_ground = True
    if x == 0:
        x = 5
    elif x == 740:
        x = 735
    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.
        ball_vel = Vector2(vel_blue) * 1.4

    # Draw everything.
    screen.fill(LIGHTBLUE)
    pg.draw.line(screen, (0, 0, 0), (0, height-70), (width, height-70))
    screen.blit(bluecar, (x, y))
    screen.blit(BALL, ballrect)

    pg.display.update()
    clock.tick(60)  
pg.quit()

标签: pythonpygame

解决方案


您必须在每一帧中更新蓝色矩形的位置,否则它将保持在其原始位置并且碰撞检测将不起作用。

然后我建议去掉x, y, x2, y2, x_change, y_change变量,因为你可以只使用向量pos_bluevel_blue.

当玩家与球碰撞时,您可以将球速度的 y 分量设置为某个负值,以便它向上移动(如果玩家正在移动,我只是将 x 分量设置为玩家的 velocity.x)。

ball_vel = Vector2(vel_blue.x, -17)

请注意,您必须使用带有 alpha 通道的表面,否则pygame.mask.from_surface将不起作用,因此我将pygame.SRCALPHA其作为第二个参数传递给pygame.Surface(您也可以调用convert_alpha()or set_colorkey())。

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
on_ground = False
ground_y = height - 100

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:
                if on_ground:  # Only jump if the player is on_ground.
                    vel_blue.y = -12
                    on_ground = False
        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

    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

    # 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
        on_ground = True
    if bluerect.x < 0:
        bluerect.x = 0
        pos_blue.x = bluerect.centerx
    elif bluerect.right > width:
        bluerect.right = width
        pos_blue.x = bluerect.centerx

    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()
    clock.tick(60)

pg.quit()

推荐阅读