Godot插值、贝塞尔曲线和Astar寻路

一、插值

线性插值是采用一次多项式上进行的插值计算,任意给定两个值A和B,那么在A和B之间的任意值可以定义为:P(t) = A * (1 - t) + B * t,0 <= t <= 1。
数学中用于线性拟合,游戏应用可以做出跟随效果(宠物跟随、npc跟随)

const FOLLOW_SPEED = 4.0func _physics_process(delta):var mouse_pos = get_local_mouse_position()$Sprite2D.position = $Sprite2D.position.lerp(mouse_pos, delta * FOLLOW_SPEED)

在这里插入图片描述

二、贝塞尔

贝塞尔是插值的应用之一。贝塞尔曲线是为工业设计,是图形软件行业中的流行工具。不过在游戏中会出现曲线扭曲的情况,应用并不好。

1.二次贝塞尔:

我们首先使用 0 到 1 之间的值,在两个线段的每个顶点上逐步插值。当我们把 t 值从 0 变成 1 时,就得到了两个沿着线段移动的点。然后,我们插值 q0 和 q1,以获得沿着曲线移动的单点 r。

func _quadratic_bezier(p0: Vector2, p1: Vector2, p2: Vector2, t: float):var q0 = p0.lerp(p1, t)var q1 = p1.lerp(p2, t)var r = q0.lerp(q1, t)return r

在这里插入图片描述

2.三次贝塞尔

同理三个线段的时候称为三次贝塞尔曲线。

func _cubic_bezier(p0: Vector2, p1: Vector2, p2: Vector2, p3: Vector2, t: float):var q0 = p0.lerp(p1, t)var q1 = p1.lerp(p2, t)var q2 = p2.lerp(p3, t)var r0 = q0.lerp(q1, t)var r1 = q1.lerp(q2, t)var s = r0.lerp(r1, t)return s

在这里插入图片描述

三、Astar寻路

Astar算法是最广泛应用的寻路算法,它的特点是基于网格,而且可以快速的求解某个点到另一个点的最短有效路径。Godot种提供了算法的封装类可以直接使用。2D版本是AStar2D、AStarGrid2D。

1.思路

添加可以到达的位置
将可以行走的点两两连接,形成路径
通过其方法直接求取某个位置到目标位置的最短路径
让玩家或其他角色按照路径上点的顺序依次前进,直到到达目标位置
在这里插入图片描述

extends Node2Dvar astar = AStar2D.new() # 实例化func _ready():# 添加可以到达的位置astar.add_point(0,Vector2(0,0))astar.add_point(1, Vector2(0, 0))astar.add_point(2, Vector2(0, 1), 1) # 默认权重为 1astar.add_point(3, Vector2(1, 1))astar.add_point(4, Vector2(2, 0))# 在点之间创建连接,形成路径astar.connect_points(1, 2, false)astar.connect_points(2, 3, false)astar.connect_points(4, 3, false)astar.connect_points(1, 4, false)# 查询某两个位置之间的路径var res = astar.get_id_path(1, 4) # [1,4]

add_point()的时候传入了一个ID,可以将其想象为是一个唯一索引值,对点的标记。
get_id_path()方法获取的是两个对应ID的点之间的最短路径,返回的是包含路径经过的所有点的ID所组成的数组。
你也可以用get_point_path()方法直接获取两个点之间的最短路径,返回的额是包含所有经过的点数组。

2.应用

在Tilemap挂载方法(版本4.2.1):

extends TileMap@onready var astar_node: AStar2D = AStar2D.new()var map_size: Vector2i = get_used_rect().sizefunc _ready():# 遍历所有层,将可以寻路的tile加入Astar图的节点for layer in range(get_layers_count()):var cells = get_used_cells(layer)for cell in cells:var tileData = get_cell_tile_data(layer, cell)var nav = tileData.get_navigation_polygon(0)if nav == null:continuevar point_index = calculate_point_index(cell)astar_node.add_point(point_index, Vector2(cell.x, cell.y))# 移除有碰撞体的点for layer in range(get_layers_count()):var cells = get_used_cells(layer)for cell in cells:var tileData = get_cell_tile_data(layer, cell)var collision = tileData.get_collision_polygons_count(0)if collision <= 0:continuevar point_index = calculate_point_index(cell)if astar_node.has_point(point_index):astar_node.remove_point(point_index)# 连接图的节点for id in astar_node.get_point_ids():var cellPosition = Vector2i(astar_node.get_point_position(id))var relativeCells: Array[Vector2i] = [cellPosition + Vector2i.RIGHT,cellPosition + Vector2i.LEFT,cellPosition + Vector2i.DOWN,cellPosition + Vector2i.UP,			]for relativeCell in relativeCells:var relativeCellIndex = calculate_point_index(relativeCell)if is_outside_map_bounds(relativeCell):continueif astar_node.has_point(relativeCellIndex):astar_node.connect_points(id, relativeCellIndex, false)func calculate_point_index(point: Vector2i) -> int:return point.x + point.y * map_size.xfunc is_outside_map_bounds(point: Vector2i) -> bool:return point.x <0 || point.y < 0 || point.x >= map_size.x || point.y >= map_size.yfunc get_nav_path(startCellPosition: Vector2i, endCellPosition: Vector2i) -> PackedVector2Array:var navCellPath = astar_node.get_point_path(calculate_point_index(startCellPosition), calculate_point_index(endCellPosition))var localPath = PackedVector2Array()for cellPosition in navCellPath:localPath.push_back(map_to_local(Vector2i(cellPosition)))return localPath

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一份完整的软件测试报告长什么样

软件测试报告是软件测试阶段的重要输出&#xff0c;它为软件开发团队、客户或管理层等利益相关方提供了详细的测试结果和软件质量评估。一份完整的软件测试报告通常包含以下几个关键部分&#xff1a; 引言和概述&#xff1a;   报告的开始部分通常有一个引言或概述&#xff…

基于单片机室内温湿度监测系统仿真设计

**单片机设计介绍&#xff0c;基于单片机室内温湿度监测系统仿真设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机室内温湿度监测系统仿真设计的沟通概要主要涉及以下几个方面&#xff1a; 一、项目背景与目标 首…

starganvc2变声器项目实战及其源码解读

1.数据与项目文件解读 数据文件目录如下所示&#xff0c;需要注意的是&#xff0c;我们并不能直接对声音进行建模&#xff0c;而需要对声音数据进行预处理&#xff0c;从而得到一系列数值特征&#xff0c;然后对特征进行建模&#xff0c;特征数据存储到processed文件夹中 2.环…

局域网共享文件夹怎么加密?局域网共享文件夹加密方法介绍

在企业局域网中&#xff0c;共享文件夹扮演着重要的角色。为了保护数据安全&#xff0c;我们需要加密保护局域网共享文件夹。那么&#xff0c;局域网共享文件夹怎么加密&#xff1f;下面我们来了解一下吧。 局域网共享文件夹加密方法 局域网共享文件夹加密推荐使用共享文件夹加…

Java 8 内存管理原理解析及内存故障排查实践

介绍Java8虚拟机的内存区域划分、内存垃圾回收工作原理解析、虚拟机内存分配配置&#xff0c;介绍各垃圾收集器优缺点及场景应用、实践内存故障场景排查诊断&#xff0c;方便读者面临内存故障时有一个明确的思路和方向。 一、背景 Java是一种流行的编程语言&#xff0c;可以在不…

代码随想录阅读笔记-二叉树【删除二叉搜索树节点】

题目 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;删除节点可分为两个步骤&#xff1a;…

[通俗易懂]《动手学强化学习》学习笔记1-第1章 初探强化学习

文章目录 前言第1章 初探强化学习1.1 简介序贯决策&#xff08;sequential decision making&#xff09;任务&#xff1a;强化学习与有监督学习或无监督学习的**区别**&#xff1a;改变未来 1.2 什么是强化学习环境交互与有监督学习的区别1&#xff1a;改变环境 &#xff08;说…

网易邮箱删除指定邮箱

一、 背景&#xff1a; 我们平时经常会收到很多恶意或者一些不重要的邮件&#xff0c;并且经常会堆满邮箱&#xff0c;导致看邮箱的时间一堆未读邮件&#xff0c;手动删除一些不重要的邮件需要一个一个的去点击&#xff0c;并且还要去判断是指定的发件人的邮件&#xff0c;像…

02-JDK新特性-try-with-resources自动管理资源关闭

try-with-resources 为什么要介绍这个了 看看一下以下代码&#xff1a; public static void fileCopyByTryWithResources(File src, File des) throws IOException {try (FileInputStream fis new FileInputStream(src); FileOutputStream fos new FileOutputStream(des);…

Mysql底层原理七:InnoDB 行记录

1.行格式 1.1 Compact行格式 1.1.1 示意图 1.1.2 准备一下 1&#xff09;建表 mysql> CREATE TABLE record_format_demo (-> c1 VARCHAR(10),-> c2 VARCHAR(10) NOT NULL,-> c3 CHAR(10),-> c4 VARCHAR(10)-> ) CHARSETascii ROW_FORMATCOM…

GIS与数字孪生共舞,打造未来智慧场景

作为一名数字孪生资深用户&#xff0c;近日我深刻理解到GIS&#xff08;地理信息系统&#xff09;在构建数字孪生体中的关键作用。 数字孪生技术旨在构建现实世界的虚拟镜像&#xff0c;而GIS则是这一镜像中不可或缺的空间维度框架和导航灯塔。数字孪生的核心是通过数字化方式…

写一个宏,可以将一个整数二进制奇数位和偶数位交换详解

何为一个整数二进制奇数位和偶数位 想要完成解题&#xff0c;我们首先要知道一个整数二进制奇数位和偶数位&#xff0c;具体代表着哪一位 对于一个32位的整型&#xff0c;它的下标是从 0 ~ 31 的&#xff0c;总共32位。 其中下表为0的位是最右边的位&#xff08;即最低有效位…