【Godot4.3】匀速和匀变速直线运动粒子

news2024/10/4 4:44:00

概述

本篇论述,如何用加速度在Godot中控制粒子运动。

匀速和匀变速直线运动的统一

以下是匀变速运动的速度和位移公式:

v t = v 0 + a t x t = v 0 t + 1 2 a t 2 v_t=v_0 + at \\ x_t=v_0t + \frac{1}{2}at^2 vt=v0+atxt=v0t+21at2

当a = 0 时:

v t = v 0 x t = v 0 t v_t=v_0 \\ x_t=v_0t vt=v0xt=v0t

所以匀速直线运动可以看成是a = 0 的特殊匀变速直线运动,两者可以共用一套公式。

Godot中的匀变速直线运动实现

另外,我们在Godot的_process()或者_physics_process()中得到的delta其实就是 Δ t \Delta t Δt,而不是一个连续累计的时间 t t t

我们需要计算的当前帧基于前一帧的速度和位移,也就是:

v f r a m e = v f r a m e − 1 + a Δ t x f r a m e = v f r a m e − 1 Δ t + 1 2 a Δ t 2 v_{frame} = v_{frame-1} + a \Delta t \\ x_{frame} = v_{frame-1}\Delta t + \frac{1}{2} a {\Delta t}^2 vframe=vframe1+aΔtxframe=vframe1Δt+21aΔt2

其中:

  • v f r a m e v_{frame} vframe表示当前帧的速度, v f r a m e − 1 v_{frame-1} vframe1表示上一帧的速度
  • x f r a m e x_{frame} xframe表示当前帧的位置, x f r a m e − 1 x_{frame-1} xframe1表示上一帧的位置

其实也就是:

Δ v = v f r a m e − v f r a m e − 1 = a Δ t Δ x = x f r a m e − x f r a m e − 1 = v f r a m e − 1 Δ t + 1 2 a Δ t 2 \Delta v = v_{frame} - v_{frame-1} = a \Delta t \\ \Delta x = x_{frame} - x_{frame-1} = v_{frame-1}\Delta t + \frac{1}{2} a {\Delta t}^2 Δv=vframevframe1=aΔtΔx=xframexframe1=vframe1Δt+21aΔt2

所以当前帧:

v f r a m e = v f r a m e − 1 + Δ v x f r a m e = x f r a m e − 1 + Δ x v_{frame} = v_{frame-1} + \Delta v \\ x_{frame} = x_{frame-1} + \Delta x vframe=vframe1+Δvxframe=xframe1+Δx

速度和位移都变成了基于前一帧的累计值,而与初始的速度 v 0 v_0 v0无关,同样加速度a = 0时, Δ v \Delta v Δv=0,当前帧速度保持不变, Δ x = v f r a m e − 1 Δ t \Delta x = v_{frame-1}\Delta t Δx=vframe1Δt,当前帧的位置 = 上一帧位置 + Δ x \Delta x Δx

实现粒子类

基于上面的认识,我们可以编写一个粒子类。它的代码如下,其中update()用于粒子基于_process()或者_physics_process()中得到的delta更新粒子速度和位置,是完全按照上面的思路实现的。

# 粒子
class Particle:
	var position:Vector2
	var velocity:Vector2
	var acceleration:Vector2

	func _init(position:Vector2,velocity:Vector2,acceleration:Vector2) -> void:
		self.position = position
		self.velocity = velocity
		self.acceleration = acceleration
	
	# 更新速度和位置
	func update(d_t: float)-> void:
		var d_v = acceleration * d_t
		velocity += d_v
		position += velocity * d_t + (d_v * d_t)/2
	
	# 绘制粒子
	func draw_particle(
		canvas_item:CanvasItem,
		color:=Color.AQUAMARINE,
		r:=3.0,
		fill:=true,
		border_width:=1
	):
		canvas_item.draw_circle(position,r,color,fill,border_width)
	
	# 绘制粒子的速度矢量
	func draw_velocity(
		canvas_item:CanvasItem,
		color:=Color.GREEN_YELLOW,
		border_width:=1
	):
		canvas_item.draw_line(position,position+velocity,color,border_width)
	
	# 绘制粒子的加速度矢量
	func draw_acceleration(
		canvas_item:CanvasItem,
		color:=Color.ORANGE_RED,
		border_width:=1
	):
		canvas_item.draw_line(position,position+acceleration,color,border_width)

测试代码

extends Node2D

var pos:Vector2 = Vector2(100,100) # 位置
var v := Vector2()                 # 速度
var a := Vector2.RIGHT * 20        # 加速度


# 创建粒子实例
var p = Particle.new(pos,v,a)

func _process(delta: float) -> void:
	p.update(delta) # 更新粒子的速度和位置
	queue_redraw()  # 请求重绘

# 绘制
func _draw() -> void:
	p.draw_particle(self)     # 绘制粒子
	p.draw_velocity(self)     # 绘制速度向量
	p.draw_acceleration(self) # 绘制加速度向量

可以看到:

  • 我们在创建粒子实例时,只需要设定起始位置、初始速度以及加速度就可以了。
  • 程序便会自动随时间更新粒子的速度和位置,并且绘制出粒子、粒子当前的速度以及加速度

通过设定不同的起始位置、初始速度以及加速度,我们就可以模拟出匀速直线运动、匀加速直线运动和匀减速直线运动。

# 匀减速直线运动
var pos:Vector2 = Vector2(100,100) # 起始位置
var v := Vector2.RIGHT * 100       # 初始速度
var a := Vector2.LEFT * 20         # 加速度
# 初速度为0的匀加速直线运动
var pos:Vector2 = Vector2(100,100) # 起始位置
var v := Vector2()                 # 初始速度
var a := Vector2.RIGHT * 20        # 加速度
# 初速度不为0的匀速直线运动
var pos:Vector2 = Vector2(100,100) # 起始位置
var v := Vector2.RIGHT * 100       # 初始速度
var a := Vector2()                 # 加速度

用曲线控制速度和加速度变化

extends Node2D

# 匀减速直线运动
var pos:Vector2 = Vector2(300,300) # 起始位置
var v := Vector2.RIGHT * 100       # 初始速度
var a := Vector2.LEFT * 0         # 加速度

@export var velocity_curve:Curve

# 创建粒子实例
var p = Particle.new(pos,v,a)

var offset:= 0.0
var step:=0.005


func _process(delta: float) -> void:
	p.velocity = v * velocity_curve.sample(offset)
	offset += step
	if not(offset <=1.0 and offset >= 0.0):
		step *= -1
	
	p.update(delta) # 更新粒子的速度和位置
	queue_redraw()

# 绘制
func _draw() -> void:
	p.draw_particle(self,Color.AQUAMARINE,20.0)     # 绘制粒子
	p.draw_velocity(self)     # 绘制速度向量
	p.draw_acceleration(self) # 绘制加速度向量

效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2187356.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机科学英语词汇汇总(下)Computer Science English Complete Vocabulary )

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…

0基础学习QT——配置开发环境

大纲 安装Qt配置Visual Studio 2022安装插件配置 测试 Qt框架&#xff0c;以其跨平台、高性能以及丰富的UI组件库而著称&#xff0c;是开发图形用户界面应用程序的理想选择。Visual Studio 2022提供了对Qt项目的深度支持&#xff0c;包括智能代码提示、代码导航、调试工具等&am…

(14)MATLAB莱斯(Rician)衰落信道仿真4

文章目录 前言一、改写莱斯分布概率密度函数的理论值二、仿真代码三、仿真结果总结 前言 本文通过将接收信号总功率设置为1&#xff0c;重写了莱斯衰落信道上接收信号幅度的理论PDF式。然后用MATLAB代码生成了在具有不同莱斯因子K的Ricean平坦衰落信道下接收到的信号样本&…

容器适配器-stack、queue、priority_queue和仿函数

目录 1.什么是适配器 2.deque 1.简单了解结构 2.deque的缺陷 3.为什么选择deque作为stack和queue的底层默认容器 3.stack&#xff08;栈&#xff09; 4.queue&#xff08;队列&#xff09; 5.仿函数 6.priority_queue&#xff08;优先级队列&#xff09;&#xff08;堆…

PlantUML中的实体关系图

概述 实体关系图&#xff08;Entity Relationship Diagrams&#xff0c;ERD&#xff09;是一种被广泛用于数据库建模的图。 1976年美籍华裔计算机科学家陈品山&#xff08;Peter Chen&#xff09;首次提出了Entity Relationship Modeling&#xff08;实体关系建模&#xff09…

数据结构-单链表的反转

一直在路上 目录 前言一、普通方法二、头插法三、递归法总结 前言 本篇文章介绍反转单链表的三种方法&#xff0c;分别为普通方法、头插法、递归法。 一、普通方法 普通方法是从第一个结点开始反转&#xff0c;然后反转剩余的结点。 普通方法需要保存当前结点的前驱和后继&a…

DevExpress WinForms v24.1新版亮点:富文本编辑器、电子表格组件功能升级

DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜…

自动驾驶-轨迹拼接

在进行自动驾驶的规划之前&#xff0c;要确定当前帧轨迹规划的起点&#xff0c;这个起点常被误认为是当前车辆的位置&#xff0c;即每次以车辆的当前位置进行轨迹规划&#xff1b;其实不是这样的&#xff0c;直观上&#xff0c;这会导致本次次规划的轨迹同上次规划的轨迹之间是…

如何计算服务需要部署多少台机器?

写在前面 遇到流量激增的性能问题&#xff0c;相信绝大多数人的第一反应不是优化代码而是加机器&#xff01;比如隔壁微博一旦出现爆炸性吃瓜&#xff0c;就会紧急扩机器&#xff0c;防止自己服务被打挂&#xff08;虽然经常被打挂 这篇文章我们就来讲一下如何 计算出一个服务…

项目配置说明

文章目录 一、下载 vscode 并安装相应扩展1.1 下载 vscode1.2 安装扩展 二、git 项目三、git 提交流程3.1 确定要提交的代码 四、git 拉新流程 一、下载 vscode 并安装相应扩展 1.1 下载 vscode vscode 我已经发群里了&#xff0c;或者自己去官网下载也行 1.2 安装扩展 打开…

四舵轮车辆中的舵轮角度计算

对于四舵轮车辆&#xff0c;或者对角线安装的双舵轮车辆来说&#xff0c;当同时存在线速度与角速度的时候&#xff0c;它的两个轮子的角度值是不一样的&#xff0c;而它的角度值与其当时的瞬心相关&#xff08;机器人模型与ICR(Instantaneous Center of Rotation)&#xff09;。…

IP6537_C_30W20V--移动设备快充的得力助手,集成 14 种快充协议的降压 SoC

IP6537_C_30W20V是一款集成同步开关的降压转换器、支 持 14 种输出快充协议、支持 Type-C 输出和 USB PD2.0/PD3.0(PPS)协议的 SoC&#xff0c;为车载充电器、 快充适配器、智能排插提供完整的解决方案。 IP6537_C_30W20V支持 USB Type-C 或者 USB A 输出&#xff0c; 5V 输出功…

火语言RPA流程组件介绍--模拟键盘输入

&#x1f6a9;【组件功能】&#xff1a;在浏览器网页中使用键盘操作模拟输入值 配置预览 配置说明 按键间隔(ms) 支持T或# 输入仅支持整型 两次输入按键的间隔,单位毫秒 输入内容 支持T或# 默认FLOW输入项 需要输入的内容 超时时间 支持T或# 输入仅支持整型 输入的超时时…

我们的赞赏码

每一位粉丝的认可&#xff0c;都是我们前进的动力。欢迎为我们点赞、转发和分享&#xff0c;让我们一起传递美好与快乐&#xff01; 我们真诚地邀请您来赞赏我们&#xff0c;您的认可是我们前进的动力&#xff01; 赞赏我们只要0.99&#xff0c;让我们一起在CSDN增长知识&…

OpenAI 开发者大会!实时语音功能有API了,GPT-4o支持多模态微调,上下文cache功能上线

家人们&#xff01;十一假期第1天&#xff0c; OpenAI一年一度的开发者大会又来了惹&#xff01;今年的开发者大会分成三部分分别在美国、英国、新加坡三个地点举办&#xff0c;刚刚结束的是第一场。 去年的OpenAI开发者大会公布了GPT-4 Turbo和GPTs&#xff0c;今年没有大更新…

【硬件模块】SG90舵机模块

SG90舵机模块实物图 180度舵机&#xff1a;可以控制旋转角度、有角度定位。上电后舵机自动复位到0度&#xff0c;通过一定参数的脉冲信号控制它的角度。 360舵机&#xff1a;不可控制角度&#xff0c;只能控制顺时针旋转、逆时针旋转、停止和调节转速。 如图所示为&#xff1a;…

仅用pygame+python实现植物大战僵尸-----完成比完美更重要

前言 其实这个项目再我上半年就想着做一下的&#xff0c;但是一直拖到现在&#xff0c;我现在深刻的理解到&#xff0c;不要想那么多&#xff0c;先做&#xff0c;因为永远不可能准备好&#xff0c;都是边做边学便准备的&#xff0c;完成比完美更重要&#xff1b;使用python&a…

【YOLO学习】YOLOv2详解

文章目录 1. 概述2. Better2.1 Batch Normalization&#xff08;批归一化&#xff09;2.2 High Resolution Classifier&#xff08;高分辨率分类器&#xff09;2.3 Convolutional With Anchor Boxes&#xff08;带有Anchor Boxes的卷积&#xff09;2.4 Dimension Clusters&…

每日一题|1928. 规定时间内到达终点的最小花费|动态规划、最小路径

本题需要使用动态规划进行解决。 分析&#xff1a; 求解最小值而且每一次的状态是由上一次的状态推导出来的&#xff0c;用动态规划。 难点&#xff1a;dp数组的定义和更新。 1、dp数组的定义 在时刻t&#xff0c;位置i处&#xff0c;此时的花费可以表示为如下的形式&#…

CNN卷积神经网络算法原理

全连接神经网络概述 输入层在左点自外&#xff0c;相应的输出层在右点之外&#xff0c; 这就像一个函数&#xff0c;yf(x)&#xff0c;x即输入&#xff0c;f即隐藏层&#xff0c;y即输出&#xff0c;或者是ymodel(x) 全连接神经网络的结构单元 主要是从单元到整体&#xff0c…