【Godot4.2】2D导航02 - AstarGrid2D及其使用方法

概述

AstarGrid2D是Godot4.0新增的A*寻路辅助类型。可以看做是Astar2D的加强版。它允许你通过设置其sizecell_size属性来创建一个虚拟的网格。

并使用set_point_solid()这样的方法来在指定位置创建障碍物。

AstarGrid2D的好处是你不再需要手动的添加点以及点与点之间的连接,而是直接用get_point_path()这样的方法来获取最短路径(也就是一个包含了最短路径经过的点的数组)。

通过遍历这个数组,就可以实现路径移动了。

extends Control

var astar_grid = AStarGrid2D.new()

var cell_size = Vector2.ONE * 100

func _ready():
	astar_grid.size = Vector2i.ONE * 32
	astar_grid.cell_size = Vector2i.ONE * 32
	astar_grid.update()
	


func _draw():
	# 绘制网格
	var grid_width = astar_grid.size.x * astar_grid.cell_size.x
	var cell_width = astar_grid.cell_size.x
	var cell_height = astar_grid.cell_size.y
	
	for i in range(astar_grid.size.x):
		draw_line(i * Vector2i(0,cell_height),i * Vector2i(grid_width,cell_height),Color.DARK_OLIVE_GREEN,2)
	for j in range(astar_grid.size.y):
		draw_line(j * Vector2i(cell_height,0),j * Vector2i(cell_height,grid_width),Color.DARK_OLIVE_GREEN,2)
	# 绘制路径和其上的点
	var path  = astar_grid.get_point_path(Vector2i(0,0),Vector2i(10,10))
	for pot in path:
		draw_circle(pot,5,Color.YELLOW)
	draw_polyline(path,Color.YELLOW,2)

image.png

extends Control

var astar_grid = AStarGrid2D.new()

var path:PackedVector2Array

var solids = []

func _ready():
	randomize()
	astar_grid.size = Vector2i.ONE * 32
	astar_grid.cell_size = Vector2i.ONE * 32
	astar_grid.offset = astar_grid.cell_size/2
	astar_grid.update()
	
	# 随机生成障碍
	for i in range(50):
		var solid_point = Vector2i(randi_range(0,astar_grid.size.x),randi_range(0,astar_grid.size.y))
		astar_grid.set_point_solid(solid_point,true)
		solids.append(solid_point)
		
	


func _draw():
	var grid_width = astar_grid.size.x * astar_grid.cell_size.x
	var cell_width = astar_grid.cell_size.x
	var cell_height = astar_grid.cell_size.y
	# 绘制网格
	for i in range(astar_grid.size.x):
		draw_line(i * Vector2i(0,cell_height),i * Vector2i(grid_width,cell_height),Color.DARK_OLIVE_GREEN,2)
	for j in range(astar_grid.size.y):
		draw_line(j * Vector2i(cell_height,0),j * Vector2i(cell_height,grid_width),Color.DARK_OLIVE_GREEN,2)
	
	# 绘制路径和其上的点
	if path.size() > 0:
		for pot in path:
			draw_circle(pot,5,Color.YELLOW)
				
		draw_polyline(path,Color.YELLOW,2)
	for p in solids:
		draw_rect(Rect2(p * Vector2i(astar_grid.cell_size),astar_grid.cell_size),Color.GRAY)

func _on_gui_input(event):
	if event is InputEventMouseButton:
		if event.button_index == MOUSE_BUTTON_LEFT:
			if event.is_pressed():
				path = astar_grid.get_point_path(Vector2i(0,0),floor(get_global_mouse_position()/astar_grid.cell_size))
				queue_redraw()

  • 13行:将AstarGridoffset 设为 astar_grid.cell_size/2,也就实现了整体的坐标偏移。
  • 48行:floor(get_global_mouse_position()/astar_grid.cell_size)获得的就是鼠标点击所在的单元格的坐标。

AstarGrid寻路2.gif
目前为止,AstarGrid显示对角线形式的连接。

如果我们需要设置其只显示横平竖直的连接,则可以设置AstarGriddiagonal_modeDIAGONAL_MODE_NEVER

astar_grid.diagonal_mode = AStarGrid2D.DIAGONAL_MODE_NEVER

AstarGrid寻路3.gif

DiagonalMode说明
DIAGONAL_MODE_ALWAYS0该寻路算法将忽略目标单元格周围的实体邻居,并允许沿对角线通过。
DIAGONAL_MODE_NEVER1该寻路算法将忽略所有对角线,并且路径始终是正交的。
DIAGONAL_MODE_AT_LEAST_ONE_WALKABLE2如果在特定路径段的相邻单元格周围放置了至少两个障碍物,则该寻路算法将避免使用对角线。
DIAGONAL_MODE_ONLY_IF_NO_OBSTACLES3如果在特定路径段的相邻单元格周围放置了任意障碍物,则该寻路算法将避免使用对角线。
DIAGONAL_MODE_MAX4代表 DiagonalMode 枚举的大小。

实现玩家基于AstarGrid2D的移动

用一个简单Sprite2D作为玩家。将其缩放为原始尺寸128×128的四分之一,也就是32×32。刚好可以填入AstarGrid2D的单元格中。
image.pngimage.png

extends Control

var astar_grid = AStarGrid2D.new()
var path:PackedVector2Array
var solids = [] # 障碍物列表

@onready var icon = $Icon
var speed = 200.0
var can_walk = false
var target_pos:Vector2

func _process(delta):
	if can_walk:
		if path.size()>0:
			target_pos = path[0]
			if icon.position.distance_to(target_pos)>0:
				icon.position = icon.position.move_toward(target_pos,speed * delta)
			else:
				path.remove_at(0)
				queue_redraw()
		else:
			can_walk = false

func _ready():
	randomize()
	astar_grid.size = Vector2i.ONE * 32
	astar_grid.cell_size = Vector2i.ONE * 32
	astar_grid.offset = astar_grid.cell_size/2
	icon.position = astar_grid.cell_size/2
	astar_grid.diagonal_mode = AStarGrid2D.DIAGONAL_MODE_NEVER
	astar_grid.default_compute_heuristic  = AStarGrid2D.HEURISTIC_MANHATTAN

	astar_grid.update()
	
	# 随机生成障碍
	for i in range(150):
		var solid_point = Vector2i(randi_range(0,astar_grid.size.x),randi_range(0,astar_grid.size.y))
		astar_grid.set_point_solid(solid_point,true)
		solids.append(solid_point)
		
	


func _draw():
	var grid_width = astar_grid.size.x * astar_grid.cell_size.x
	var cell_width = astar_grid.cell_size.x
	var cell_height = astar_grid.cell_size.y
	# 绘制网格
	for i in range(astar_grid.size.x):
		draw_line(i * Vector2i(0,cell_height),i * Vector2i(grid_width,cell_height),Color.DARK_OLIVE_GREEN,2)
	for j in range(astar_grid.size.y):
		draw_line(j * Vector2i(cell_height,0),j * Vector2i(cell_height,grid_width),Color.DARK_OLIVE_GREEN,2)
	
	# 绘制路径和其上的点
	if path.size() > 0:
		for pot in path:
			draw_circle(pot,5,Color.YELLOW)
				
		draw_polyline(path,Color.YELLOW,2)
	for p in solids:
		draw_rect(Rect2(p * Vector2i(astar_grid.cell_size),astar_grid.cell_size),Color.GRAY)

func _on_gui_input(event):
	if event is InputEventMouseButton:
		if event.button_index == MOUSE_BUTTON_LEFT:
			if event.is_pressed():
				can_walk = true
				path = astar_grid.get_point_path(floor(icon.position/astar_grid.cell_size),floor(get_global_mouse_position()/astar_grid.cell_size))
				queue_redraw()

每次获取路径的第一个点,利用简单的距离判断和移动,到达后,从路径中删除该点。继续获取路径第一个,如此循环,知道路径中的点删除完毕。

基于AstarGrid2D的简单玩家移动

可行动范围的获取

矩形范围查找法:
先不考虑对角线移动的问题,我们假设玩家可行动点数是4,那么我们只需要遍历一个8×8矩阵的每个点到玩家的是否有可行走的路径,如果有且路径的点数<=4,则标记为可到达的点,否则,标记为不能到达的点。
image.png

extends Control

var astar_grid = AStarGrid2D.new()
var path:PackedVector2Array
var solids = [] # 障碍物列表
var max_step:int = 4 # 玩家单次的最大行动点数
var can_walk_rect:Rect2i
var can_walk_points:PackedVector2Array 

@onready var icon = $Icon
var speed = 200.0
var can_walk = false
var target_pos:Vector2

func _process(delta):
	if can_walk:
		if path.size()>0:
			target_pos = path[0]
			if icon.position.distance_to(target_pos)>0:
				icon.position = icon.position.move_toward(target_pos,speed * delta)
			else:
				path.remove_at(0)
				queue_redraw()
		else:
			can_walk = false
			queue_redraw()

func _ready():
	randomize()
	astar_grid.size = Vector2i.ONE * 32
	astar_grid.cell_size = Vector2i.ONE * 32
	astar_grid.offset = astar_grid.cell_size/2
	icon.position = astar_grid.cell_size/2
	astar_grid.diagonal_mode = AStarGrid2D.DIAGONAL_MODE_NEVER

	astar_grid.update()
	
	# 随机生成障碍
	for i in range(150):
		var solid_point = Vector2i(randi_range(0,astar_grid.size.x),randi_range(0,astar_grid.size.y))
		astar_grid.set_point_solid(solid_point,true)
		solids.append(solid_point)

	
	

func _draw():
	var grid_width = astar_grid.size.x * astar_grid.cell_size.x
	var cell_width = astar_grid.cell_size.x
	var cell_height = astar_grid.cell_size.y
	# 绘制网格
	for i in range(astar_grid.size.x):
		draw_line(i * Vector2i(0,cell_height),i * Vector2i(grid_width,cell_height),Color.DARK_OLIVE_GREEN,2)
	for j in range(astar_grid.size.y):
		draw_line(j * Vector2i(cell_height,0),j * Vector2i(cell_height,grid_width),Color.DARK_OLIVE_GREEN,2)
	
	# 绘制路径和其上的点
	if path.size() > 0:
		for pot in path:
			draw_circle(pot,5,Color.YELLOW)
				
		draw_polyline(path,Color.YELLOW,2)
	# 绘制障碍物
	for p in solids:
		draw_rect(Rect2(p * Vector2i(astar_grid.cell_size),astar_grid.cell_size),Color.GRAY)
	# 绘制可行走范围
	# 遍历矩形
	if !can_walk:
		var player_pos = floor(icon.position/astar_grid.cell_size)
		var top_left = clamp(player_pos - Vector2.ONE * max_step,Vector2.ZERO,player_pos)
		var end =  clamp(player_pos + Vector2.ONE * max_step,player_pos,Vector2(astar_grid.size))
		can_walk_rect = Rect2(top_left,end-top_left) # 获取矩形
		for i in range(can_walk_rect.position.x,can_walk_rect.end.x + 1):
			for j in range(can_walk_rect.position.y,can_walk_rect.end.y + 1):
				var v = Vector2(i,j)
				if astar_grid.get_point_path(player_pos,v).size() <= max_step+1:
					if !astar_grid.is_point_solid(v):
						can_walk_points.append(v)
						draw_rect(Rect2(v * astar_grid.cell_size,astar_grid.cell_size),Color.YELLOW_GREEN,false,2)
	
	
	
func _on_gui_input(event):
	if event is InputEventMouseButton:
		if event.button_index == MOUSE_BUTTON_LEFT:
			if event.is_pressed():
				can_walk = true
				var player_pos = floor(icon.position/astar_grid.cell_size)
				var targ_pos = floor(get_global_mouse_position()/astar_grid.cell_size)
				if targ_pos in can_walk_points: # 如果在可行走的范围内
					path = astar_grid.get_point_path(player_pos,targ_pos)
					can_walk_points.clear() # 清空原来的可行走范围
					queue_redraw()

AstarGrid寻路-显示和限定行走范围.gif
AstarGrid寻路-显示和限定行走范围2.gif

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue3+element Plus form 作为子组件,从父组件如何赋值?

刚开始接触vue3时&#xff0c;碰到一个很low的问题&#xff0c;将form作为子组件&#xff0c;在页面中给form表单项输入内容&#xff0c;输入框不显示值&#xff0c;知道问题出在哪&#xff0c;但因为vue3组合式api不熟悉&#xff0c;不知从哪下手... 效果图&#xff1a; 父组…

ubuntu下samba匿名读写服务器

目的&#xff1a; 局域网内&#xff0c;ubuntu下&#xff0c;创建SAMBA文件共享服务器。匿名读写权限。为了开发项目组文件共享传输方便。 环境&#xff1a; X86_64电脑一台。 操作系统&#xff1a; Ubuntu 20.04 LTS 64位。 安装samba $ sudo apt-get install samba创建…

FPGA通过I2C控制AT24C64

文章目录 前言一、代码设计框图二、IIC_drive模块设计2.1、模块接口&#xff1a;2.2、代码功能描述&#xff1a;2.3、IIC协议实现过程&#xff1a; 三、EEPROM_ctrl模块设计3.1、模块接口&#xff1a;3.2、代码功能描述 四、EEPROM_drive模块五、iic_top模块 前言 继上一篇FPG…

计算机毕业设计-基于深度学习的验证码识别方法设计与实现

概要 验证码是一个系统区分人类与非人类行为的有效方式。验证码识别技术能够使计算机程序输入正确的验证码&#xff0c;伪装成人类用户进入目标系统。另一方面&#xff0c;系统方面需要考虑破解验证码识别技术&#xff0c;修补验证方式的可能漏洞&#xff0c;使之能够更有效地区…

[Uni-app] 微信小程序的圆环进度条

效果图&#xff1a; 组件完整代码如下&#xff1a; <template><view class"base-style":style"position: relative;width: diameter px;height: diameter px;display: flex;flex-direction: row;background-color: bgColor ;"><!…

RK3588+FPGA+AD+AI的智能数据采集与分析解决方案

RK3588是瑞芯微新一代旗舰级高端处理器&#xff0c;具有高算力、低功耗、超强多媒体、丰富数据接口等特点。搭载四核A76四核A55的八核CPU和ARM G610MP4 GPU&#xff0c;内置6.0TOPs算力的NPU。 RK3588复旦微FPGA方案 有五大技术优势 1. 内置多种功能强大的嵌入式硬件引擎&…

【Linux(1)】Linux的一些基本指令(补充上一篇)

思维导图 学习内容 通过上面的学习目标&#xff0c;我们可以列出要学习的内容&#xff1a; linux的一些指令&#xff1a;cd mkdir cp touch which rm cat alias 一些基本的概念&#xff1a;指令的概念&#xff0c;用户家目录是什么...... 一、Linux的一些指令 1.1 重新认识…

基于Spring Boot共享单车信息系统的设计与实现

摘 要 快速发展的社会中&#xff0c;人们的生活水平都在提高&#xff0c;生活节奏也在逐渐加快。为了节省时间和提高工作效率&#xff0c;越来越多的人选择利用互联网进行线上打理各种事务&#xff0c;然后线上管理系统也就相继涌现。与此同时&#xff0c;人们开始接受方便的生…

Opencv入门---绘图篇

目录 一、cv.line() 二,cv.cricle() 三&#xff0c;cv2.rectangle() 一、cv.line() cv.line()是 OpenCV 库中用于在图像上绘制直线的函数。它可以在图像上绘制一条直线&#xff0c;指定直线的起始点和结束点。 函数的语法如下&#xff1a; cv.line(img, pt1, pt2, color, th…

[LLM] 大模型基础|预训练|有监督微调SFT | 推理

现在的大模型在进行预训练时大部分都采用了GPT的预训练任务&#xff0c;即 Next token prediction。 要理解大语言模型&#xff08;LLM&#xff09;&#xff0c;首先要理解它的本质&#xff0c;无论预训练、微调还是在推理阶段&#xff0c;核心都是next token prediction&#…

dockerfile文件编写

文章目录 dockerfile是什么Dockerfile常用指令1. FROM2. MAINTAINER3. WORKDIR4.COPY5.ADD6.ENV7.RUN8.CMD9.ENTRYPOINT dockerfile是什么 Dockerfile是一个文本配置文件&#xff0c;用于自动化构建Docker镜像。 Dockerfile是由一系列命令和参数构成的脚本&#xff0c;它指导D…

zookeeper快速入门(合集)

zookeeper作为一个分布式协调框架&#xff0c;它的创建就是为了方便或者简化分布式应用的开发。除了服务注册与发现之外&#xff0c;它还能够提供更多的功能&#xff0c;但是对于入门来说&#xff0c;看这一篇就够了。后续会讲zookeeper的架构设计与原理&#xff0c;比如zookee…

resize-observer源码解读

resize-observer github 地址&#xff1a;https://github.com/devrelm/resize-observer 本地启动 npm installnpm startnode 18.16.0 (npm 9.5.1) 启动失败报错 node:internal/crypto/hash:71this[kHandle] new _Hash(algorithm, xofLen);^Error: error:0308010C:digital …

1、初识JVM

一、JVM是什么&#xff1f; JVM的英文全称是 Java Virtual Machine&#xff0c;其中文译名为Java虚拟机。它在本质上就是是一个运行在计算机上的程序&#xff0c;他的职责是运行Java字节码文件。 JVM执行流程如下 二、JVM有哪些功能&#xff1f; 2.1 解释和运行 对字节码文…

【Web技术应用基础】HTML(1)——简单界面

题目1&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title>Hello world</title></head> <body bgcolor"F6F3D6"><!--用HTML语言向世界打声招呼吧&#xff01;--><h1 align&…

电脑怎么快速重装系统win7

电脑重装系统是解决软件问题、提升系统性能的常用手段。随着技术发展,一键重装系统成为了许多用户的首选方法,因为它简化了繁琐的操作步骤,节省了大量时间。尤其是对于非技术人员来说,一键重装提供了一种快速高效且不易出错的系统安装方式。如果你需要快速重装win7,那么可…

Spring Boot 自动化单元测试类的编写过程

前言 Web环境模拟测试 企业开发不仅要保障业务层与数据层的功能安全有效&#xff0c;也要保障表现层的功能正常。但是我们一般对表现层的测试都是通过postman手工测试的&#xff0c;并没有在打包过程中代码体现表现层功能被测试通过。那么能否在测试用例中对表现层进行功能测…

Android 项目实战,APP开发,含源码

Android 项目实战&#xff0c;APP开发&#xff0c;含源码 源码项目详情 源码项目详情 切鱼达人&#xff0c;Android休闲游戏开发 打砖块&#xff0c;Android休闲小游戏开发 “牛弹琴”&#xff0c;Android 弹钢琴 app 开发 2048 数字合成大作战&#xff0c;Android小游戏开…

NCV4276BDT50RKG低压差稳压器芯片中文资料PDF数据手册规格书引脚图参数价格

产品概述&#xff1a; NCV4276B是一款输出电流400 mA集成式低压差稳压器系列&#xff0c;设计用于恶劣的汽车环境。它包括宽工作温度和输入电压范围。该器件提供固定和可调电压版本&#xff0c;输出电压精度为 2%。它具有高峰值输入电压容差和反向输入电压保护。它还提供过流保…

【研发管理】产品经理-基础认知

导读&#xff1a;产品经理&#xff08;Product Manager&#xff09;是一个负责产品的全周期管理的职位&#xff0c;他们不仅参与产品的设计、开发、推广和销售&#xff0c;还涉及到产品的市场调研、用户需求分析、竞争分析、产品规划、产品测试以及后续的产品迭代等多个环节。产…
最新文章