在pygame上更改FPS以实现精灵运动的平滑性

时间:2019-11-25 17:33:09

标签: python pygame sprite

我正在开发的游戏有问题。游戏的重点是用木板击球,以使球不会掉落。代码中有很多错误,但是我认为我应该先解决这个问题。基本上,一旦球从木板反弹,我就会增加速度增量。但是,一旦增量变得过高,您将看到球“跳跃”,而不是在屏幕上平稳移动。我尝试增加FPS并减小速度增量,但是速度太慢。下面是我的代码:

import pygame
pygame.init()

win = pygame.display.set_mode((750, 750))

pygame.display.set_caption('Ball Plank')
clock = pygame.time.Clock()

x = 305
y = 650
width = 150
height = 10
vel = 30

score = 0
lives = 3

radius = 35
ball_x = 377
ball_y = 297
ball_vely = 10
ball_velx = 10

font = pygame.font.SysFont('comicsans', 40, True)

def drawing():

    win.fill((0, 0, 0))

    text_score = font.render('Score: ' + str(score), 1, (255, 255, 255))
    text_lives = font.render('Lives: ' + str(lives), 1, (255, 255, 255))
    win.blit(text_score, (570, 20))
    win.blit(text_lives, (30, 20))

    circle = pygame.draw.circle(win, (0, 255, 0), (int(ball_x), int(ball_y)), radius)
    rect = pygame.draw.rect(win, (255, 0, 0), (x, y, width, height))
    pygame.display.update()

run = True

while run:
    clock.tick(40)
    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 > vel:
        x -= vel
    if keys[pygame.K_RIGHT] and x < 750 - width - vel:
        x += vel

    ball_y += ball_vely
    ball_x += ball_velx
    if ball_y - radius - 10 <= 0:
        ball_vely *= -1

    elif ball_y + radius + 8 > y and ball_y <= y and ball_x > x - radius and ball_x < x + width + radius:
        ball_velx = 10
        if ball_vely > 0:
            ball_vely += 0.5
        else:
            ball_vely -= 0.5
        ball_vely *= -1
        score += 1

        if ball_x > x + 75:
            ball_velx *= 1 + (ball_x - x + 75)/150
        elif ball_x < x + 75:
            ball_velx *= -(1 + (ball_x - x + 75)/150)

    if ball_x - radius - 10 <= 0 or ball_x + radius + 10  >= 750:
        ball_velx *= -1
    if ball_y > 760 + radius:
        lives -= 1
    if lives == 0:
        run = False

    drawing()

pygame.display.quit()
pygame.quit()

不确定到底出了什么问题,对不起,代码太多了。

1 个答案:

答案 0 :(得分:0)

您必须根据帧速率计算每帧的移动。

pygame.time.Clock.tick 返回自上次调用以来的毫秒数。当您在应用程序循环中调用它时,这是自上一帧以来经过的毫秒数。将物体速度乘以每帧经过的时间,无论 FPS 多少,都可以获得持续运动。

以像素为单位定义玩家每秒应移动的距离 (ball_move_per_second, paddle_move_per_second)。计算应用程序循环中每帧的距离 (ball_move_per_frame, paddle_move_per_frame)。为球的运动添加一个 pygame.math.Vector2 类型的方向向量:

clock = pygame.time.Clock()
ball_dir = pygame.math.Vector2(1, 1).normalize()
ball_move_per_second = 500
paddle_move_per_second = 500

run = True
while run:
    ms_frame = clock.tick(300)
    ball_move_per_frame = ball_move_per_second * ms_frame / 1000
    paddle_move_per_frame = paddle_move_per_second * ms_frame / 1000 

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        x = max(0, x - paddle_move_per_frame)
    if keys[pygame.K_RIGHT]:
        x = min(x + paddle_move_per_frame, win.get_width() - width)

    ball_x += ball_dir.x * ball_move_per_frame
    ball_y += ball_dir.y * ball_move_per_frame

此外,您的碰撞测试存在一些问题。有关解决方案,请参阅 PongSometimes the ball doesn't bounce off the paddle in pong game


完整示例:

import pygame
pygame.init()

win = pygame.display.set_mode((750, 750))

pygame.display.set_caption('Ball Plank')
clock = pygame.time.Clock()

x, y = 305, 650
width, height = 150, 10
score = 0
lives = 3
radius = 35
ball_x, ball_y = 377, 297
ball_dir = pygame.math.Vector2(1, 1).normalize()
ball_move_per_second = 500
paddle_move_per_second = 500

def drawing():

    win.fill((0, 0, 0))

    text_score = font.render('Score: ' + str(score), 1, (255, 255, 255))
    text_lives = font.render('Lives: ' + str(lives), 1, (255, 255, 255))
    win.blit(text_score, (570, 20))
    win.blit(text_lives, (30, 20))

    circle = pygame.draw.circle(win, (0, 255, 0), (round(ball_x), round(ball_y)), radius)
    rect = pygame.draw.rect(win, (255, 0, 0), (round(x), round(y), width, height))
    pygame.display.update()

font = pygame.font.SysFont('comicsans', 40, True)

run = True
while run:
    ms_frame = clock.tick(300)
    ball_move_per_frame = ball_move_per_second * ms_frame / 1000
    paddle_move_per_frame = paddle_move_per_second * ms_frame / 1000

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN and event.key == pygame.K_r:
            x, y = 305, 650
            ball_x, ball_y = 377, 297
            ball_dir = pygame.math.Vector2(1, 1).normalize()
            ball_move_per_second = 500
            paddle_move_per_second = 500
            score = 0
            lives = 3

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        x = max(0, x - paddle_move_per_frame)
    if keys[pygame.K_RIGHT]:
        x = min(x + paddle_move_per_frame, win.get_width() - width)

    ball_x += ball_dir.x * ball_move_per_frame
    ball_y += ball_dir.y * ball_move_per_frame
    
    if ball_x < radius:
        ball_x = radius
        ball_dir.x *= -1
    if ball_x > win.get_width() - radius:
        ball_x = win.get_width() - radius
        ball_dir.x *= -1
    
    if ball_y < radius:
        ball_y = radius
        ball_dir.y *= -1
    
    if ball_dir.y > 0 and y - radius < ball_y  < y - radius + height and x - radius < ball_x < x + width + radius:
        ball_y = y - radius
        ball_dir.y *= -1
        ball_move_per_second += 10
        score += 1

    elif ball_y > win.get_height() - radius:
        ball_y = win.get_height() - radius
        ball_dir.y *= -1
        lives -= 1

    drawing()

pygame.display.quit()
pygame.quit()