对角移动可以让玩家走得更快

问题描述 投票:0回答:2

我有这个简单的移动脚本。

if x > 0:
    if key[pygame.K_a] or key[pygame.K_LEFT]:
        rect_player.move_ip(-1 * speed, 0)
if x < SCREEN_WIDTH - 110:
    if key[pygame.K_d] or key[pygame.K_RIGHT]:
        rect_player.move_ip(speed, 0)
if y > 0:
    if key[pygame.K_w] or key[pygame.K_UP]:
        rect_player.move_ip(0, -1 * speed)
if y < SCREEN_HEIGHT - 110:
    if key[pygame.K_s] or key[pygame.K_DOWN]:
        rect_player.move_ip(0, speed)

当玩家朝一个方向移动时,一切都会顺利进行。但当它们沿对角线行进时,速度会更快。有什么办法可以解决这个问题吗?

python pygame pygame2
2个回答
4
投票

由于

pygame.Rect
应该代表屏幕上的一个区域,因此
pygame.Rect
对象只能存储整数数据(当您分配浮点数时,小数位会丢失)。

矩形对象的坐标都是整数。 [...]

我建议使用

pygame.math.Vector2
来解决这个问题。将对象的位置存储在
pygame.math.Vector2
对象中:

pos = pygame.math.Vector2(start_x, start_y)

根据按键设置方向向量。使用

speed
 将向量缩放到 
scale_to_length
的长度。移动对象并更新
rect_player
:

key = pygame.key.get_pressed()
up = key[pygame.K_w] or key[pygame.K_UP]
down = key[pygame.K_s] or key[pygame.K_DOWN]
left = key[pygame.K_a] or key[pygame.K_LEFT]
right = key[pygame.K_d] or key[pygame.K_RIGHT]

move = pygame.math.Vector2(right - left, down - up)
if move.length_squared() > 0:
    move.scale_to_length(speed)
    pos += move  
    rect_player.topleft = round(pos.x), round(pos.y)   

如果您不关心浮点精度,只需移动矩形即可:

key = pygame.key.get_pressed()
up = key[pygame.K_w] or key[pygame.K_UP]
down = key[pygame.K_s] or key[pygame.K_DOWN]
left = key[pygame.K_a] or key[pygame.K_LEFT]
right = key[pygame.K_d] or key[pygame.K_RIGHT]

move = pygame.math.Vector2(right - left, down - up)
if move.length_squared() > 0:
    move.scale_to_length(speed)
    rect_player.move_ip(round(move.x), round(move.y))        

最小示例:

import pygame

pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()

rect_player = pygame.Rect(0, 0, 20, 20)
rect_player.center = window.get_rect().center
speed = 5

run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False      

    key = pygame.key.get_pressed()
    up = key[pygame.K_w] or key[pygame.K_UP]
    down = key[pygame.K_s] or key[pygame.K_DOWN]
    left = key[pygame.K_a] or key[pygame.K_LEFT]
    right = key[pygame.K_d] or key[pygame.K_RIGHT]

    move = pygame.math.Vector2(right - left, down - up)
    if move.length_squared() > 0:
        move.scale_to_length(speed)
        rect_player.move_ip(round(move.x), round(move.y))       

    window.fill(0)
    pygame.draw.rect(window, (255, 0, 0), rect_player)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
exit()

如果您通过

math.sqrt(2)
导出速度,但继续使用
pygame.Rect
,它仍然不会导致准确的运动。 pygame.Rect 对象 (
rect_player
) 只能存储整数值(当您分配浮点数时,小数位会丢失)。因此,如果种子值很小(例如 1),这只能近似起作用并且完全失败。该解决方案真正有效的唯一值是
speed=10
,因为
10/math.sqrt(2)
是 7.071 (~7)。


1
投票

感谢@Rabbid76 帮助我解决这个问题,但这对我来说很有效:

count  = 0
if x > 0:
    if key[pygame.K_a] or key[pygame.K_LEFT]:
        count += 1
if x < SCREEN_WIDTH - 110:
    if key[pygame.K_d] or key[pygame.K_RIGHT]:
        count += 1
if y > 0:
    if key[pygame.K_w] or key[pygame.K_UP]:
        count += 1
if y < SCREEN_HEIGHT - 110:
    if key[pygame.K_s] or key[pygame.K_DOWN]:
        count += 1

if count >= 2:
    speed = speed/math.sqrt(2)

if x > 0:
    if key[pygame.K_a] or key[pygame.K_LEFT]:
        rect_player.move_ip(-1 * speed, 0)
if x < SCREEN_WIDTH - 110:
    if key[pygame.K_d] or key[pygame.K_RIGHT]:
        rect_player.move_ip(speed, 0)
if y > 0:
    if key[pygame.K_w] or key[pygame.K_UP]:
        rect_player.move_ip(0, -1 * speed)
if y < SCREEN_HEIGHT - 110:
    if key[pygame.K_s] or key[pygame.K_DOWN]:
        rect_player.move_ip(0, speed)
© www.soinside.com 2019 - 2024. All rights reserved.