前言
在专栏pygame游戏开发中的第一篇文章中讲解了增量时间的利用,可以使玩家的移动速率不受帧率的影响。但是存在一个问题是玩家斜着移动的时候速率明显更快。
看一下玩家移动的逻辑
玩家坐标.x += 移动方向 * 速度 * dt
玩家坐标.y += 移动方向 * 速度 * dt
这里的移动方向如果是x或y轴正方向则为+1,负方向为-1,但是速度是矢量,当玩家坐标x和y同时更新的时候,斜着的移动速度就如下图所示。
解决方案
将玩家移动方向设置为方向向量,检测按键按下时候,给方向向量赋值,当方向向量长度大于0时将方向向量归一化处理(向量转换为一个新的向量,这个新向量的方向与原有方向向量相同,但长度(或模)被调整为1),这样等同于把速度给分解了。代码思路如下
# 玩家移动方向
self.direction = pygame.math.Vector2()
# 如果方向向量长度大于0才执行相关动作
if self.direction.magnitude() > 0:
self.direction = self.direction.normalize() # 归一化
self.player_rect.x += self.direction.x * self.speed * dt
self.player_rect.y += self.direction.y * self.speed * dt
print(self.direction)
整体代码
player.py(玩家移动逻辑)
import pygame
from settings import *
class Player:
def __init__(self):
# 获取显示界面
self.display_surface = pygame.display.get_surface()
# 玩家设置
self.width, self.height = 20, 20
self.speed = 200 # 玩家速度
# 玩家移动方向
self.direction = pygame.math.Vector2()
# 绘制玩家
left = SCREEN_WIDTH / 2 - self.width / 2
top = SCREEN_HEIGHT / 2 - self.height / 2
self.player_rect = pygame.Rect(left, top, self.width, self.height)
def draw_player(self):
pygame.draw.rect(surface=self.display_surface, color='green', rect=self.player_rect)
def input(self):
"""获取键盘输入"""
keys = pygame.key.get_pressed()
# ↑ and ↓
if keys[pygame.K_UP] or keys[pygame.K_w]:
self.direction.y = -1
elif keys[pygame.K_DOWN] or keys[pygame.K_s]:
self.direction.y = 1
else:
self.direction.y = 0
# ← and →
if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
self.direction.x = 1
elif keys[pygame.K_LEFT] or keys[pygame.K_a]:
self.direction.x = -1
else:
self.direction.x = 0
def move(self, dt):
"""玩家移动"""
self.input()
# 如果方向向量长度大于0才执行相关动作
if self.direction.magnitude() > 0:
self.direction = self.direction.normalize() # 归一化
self.player_rect.x += self.direction.x * self.speed * dt
self.player_rect.y += self.direction.y * self.speed * dt
self.draw_player()
settings.py(设置文件)
# 屏幕宽度、屏幕高度
SCREEN_WIDTH, SCREEN_HEIGHT = 1200, 800
# 帧率
FPS = 90
levle.py(关卡等级)
import pygame
from player import Player
class Level:
def __init__(self):
# 获取显示界面
self.display_surface = pygame.display.get_surface()
self.display_surface_rect = self.display_surface.get_rect()
self.player = Player()
def run(self, dt):
self.display_surface.fill('white') # 填充白色
self.player.move(dt)
main.py(主函数)
import pygame, sys
from level import Level
from settings import *
class Game:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('测试') # 设置标题
self.clock = pygame.time.Clock() # 创建时钟对象
self.level = Level()
def run(self):
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
dt = self.clock.tick(FPS) / 1000 # 计算自上次调用到现在经过的秒数
self.level.run(dt)
pygame.display.flip()
if __name__ == '__main__':
game = Game()
game.run()