首页 > 其他分享 >(一)pygame保证玩家移动速度与电脑性能无关,pygame中的增量时间(dt)的利用

(一)pygame保证玩家移动速度与电脑性能无关,pygame中的增量时间(dt)的利用

时间:2024-08-02 12:24:21浏览次数:15  
标签:self 玩家 pygame dt 移动 display

前言

在pygame中一般刚入门书籍上的游戏项目玩家移动逻辑如下:

玩家坐标.x += 移动方向 * 速度
玩家坐标.y += 移动方向 * 速度

使用这种移动逻辑的缺点十分明显,就是玩家的移动速度会受到电脑性能的影响。主要体现在游戏运行时候帧率不一样,高性能的电脑帧率比较高,代码调用频率高,玩家移动的速度就会快。虽然可以通过设置固定频率,但是谁也不能保证每一台电脑都能够顶着游戏设置的帧率跑满吧。

解决方案

使用增量时间

增量时间概念

增量时间(Delta Time,通常简写为dt)是用来衡量从上一帧到当前帧所经过的时间量(通常以秒为单位)。这是游戏开发中处理动画、物理模拟等时非常重要的一个概念,它允许游戏以独立于实际帧率的速度运行。

增量时间的使用及解释

使用增量时间后的玩家移动逻辑如下

玩家坐标.x += 移动方向 * 速度 * dt
玩家坐标.y += 移动方向 * 速度 * dt

很好理解帧率高的玩家dt比较小,虽然代码执行效率比较高但是我移动的距离短;帧率比较低的玩家虽然我代码执行效率低,但是每次dt大我移动的距离就大。当帧率高的玩家和帧率低的玩家同时按下移动键相同时间,dt之和基本相同,移动的距离也基本相同。

测试代码

大家可以使用下面代码进行测试,可以在设置玩家文件里面中的move函数中把增量时间dt给删除,然后在设置文件里面更改帧率FPS看看移动速率的变化。再对比之后加上增量时间后的玩家移动速度。

这里还有一个,大家在开发游戏的时候还是要组织好代码结构,不要放在一个文件中后面不好更改,也不好升级优化。

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()

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()

        # 不使用增量时间的可以把dt删除掉
        self.player_rect.x += self.direction.x * self.speed * dt
        self.player_rect.y += self.direction.y * self.speed * dt

        self.draw_player()

level.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)

settings.py(设置文件)

# 屏幕宽度、屏幕高度
SCREEN_WIDTH, SCREEN_HEIGHT = 1200, 800

# 帧率
FPS = 90

遗留问题

现在解决了玩家以独立于实际帧率的速度运行,但是这里又有一个新问题,大家阅读一下玩家移动的代码,想一下在斜着方向上的移动速率和水平方向的移动速率是一样的吗?

标签:self,玩家,pygame,dt,移动,display
From: https://blog.csdn.net/weixin_60062799/article/details/140858888

相关文章

  • P9308 「DTOI-5」#1f1e33 题解
    声明:截止\(2024.8.1\),拿下洛谷最优解最短解,代码长度不到1k。复杂度\(O(n\log\logn)\)。先骂:官方题解菜!这种纯洁的数论题居然敢引入NTT作为标算,说明出题人不会推式子。还有题解区一车\(\log\)的题解凭啥顶那么上面,推的一坨狗屎推出来的复杂度还不优秀。说明:下面除法默......
  • 2000-2022年 上市公司-各企业广告支出数据(原始数据、运行代码、最终结果(Excel 和 Dta
    广告支出是企业推广其商品或服务的关键财务活动之一。通过广告,企业能够提升品牌知名度、增强市场影响力,并最终推动销售增长。本数据资源提供了上市公司广告支出的详细数据,为企业市场策略分析和学术研究提供了丰富的信息。广告支出指标AD1:广告支出的自然对数AD1指标通过将......
  • mapbox 结合deckgl添加3DTiles等操作
    1.初始化import{MapboxOverlay}from"@deck.gl/mapbox";import{LineLayer,GeoJsonLayer}from"@deck.gl/layers"; import{TripsLayer,Tile3DLayer}from"@deck.gl/geo-layers"; import{Tiles3DLoader}from"@loade......
  • 如何通过按键在pygame中移动图像?
    我正在用pygame制作一个简单的游戏,我想移动一张图片,但该图片似乎每次点击都会制作,这根本不是我想要的,我想通过按键来移动它,但每次时间移动了一个代码:#importmodulesimportpygamefrompygame.localsimport*importsysimportos#################pygame.ini......
  • Transport Layer Security for UDP&TCP(TLS/DTLS1.2)
    参考文章:https://blog.csdn.net/alwaysrun/article/details/89076492 https://www.jianshu.com/p/fd0a624d0912 https://cloud.tencent.com/developer/article/1928677文档:https://www.rfc-editor.org/rfc/rfc6347  https://www.rfc-editor.org/rfc/rfc52461.SSL/TL......
  • 代码大全C语言如何使用ADT
    面向对象的编程语言能自动支持对同一ADT的多份实例的处理。如果你只是在面向对象的环境中工作,那你根本就不用自己操心处理多个实例的实现细节了恭喜你(你可以直接去读下一节“ADT和类”。)!如果你是在像C语言这样的非面向对象的环境中工作,你就必须自己手工实现支持处理多个实例的......
  • 代码大全不要让 ADT依赖于其存储介质
    Q:不要让ADT依赖于其存储介质假设你有一张保险费率表,它太大了,因此只能保存到磁盘上。你可能想把它称做一个“费率文件”然后编出类似RateFile.Read()这样的访问器子程序(accessroutine)。然而当你把它称做一个“文件”时,已经暴露了过多的数据信息。一旦对程序进行修改,把这张表......
  • VO、DTO、Entity:Java 应用中的数据对象详解
    在Java应用程序中,特别是在基于微服务架构的应用中,数据对象(DataObjects)扮演着非常重要的角色。它们不仅有助于组织和传输数据,还能确保应用程序各部分之间的解耦。本文将深入探讨VO(ViewObject)、DTO(DataTransferObject)和Entity之间的区别,并讨论它们在实际项目中的应......
  • pygame 文件调用 Pygame 文件时出现 MouduleNotFound 错误
    我遇到的错误如下:ModuleNotFoundError:Nomodulenamed'pygame.rect'我将错误追溯到sprite.py(一个pygame文件),它试图导入文件rect.py。这是我的文件路径:文件路径白色圈出的文件是尝试导入“rect.py”的文件。我能找到的唯一类似文件是用红色圈出的文件“r......
  • 我无法安装 pygame 模块,所以我尝试观看视频,它告诉我这样做。在那个视频中他得到了 pyt
    c:\User\admin>piplistSyntaxError:unexpectedcharacterafterlinecontinuationcharacter我试图获取python模块列表,但出现语法错误出现SyntaxError:unexpectedcharacterafterlinecontinuationcharacter错误是因为你的用户名中包含一个特殊字符......