第29课咱们讲讲在Go游戏后端开发中,如何让游戏中的怪物或NPC能够表现出一定的智能行为。我们以简单的怪物AI为例,让怪物根据玩家的位置做出移动决策,使之不断地靠近玩家,当怪物碰到玩家的时候向玩家发起攻击。
要实现怪物根据玩家的位置做出移动决策,我们需要直到怪物与玩家之间的距离,因为我们的例子是二维游戏,所以我们使用二维空间的
欧几里得距离
来计算。
在二维空间中,对于两点
和
,它们之间的欧几里得距离
的计算公式为:
例如,若有点 和 ,则它们之间的欧几里得距离为:
首先,我们要将游戏中的对象抽象成结构体,本例中涉及玩家和怪物两种游戏对象,我们使用
Player
和
Monster
结构体来表示它们。位置是它们共有的属性,这里使用内嵌
Postion
结构体来表示位置。
内嵌结构体的字段会被提升到外层结构体中,这样我们就可以直接访问嵌套结构体的字段,例如
player.X
和
player.Position.X
是同一个数据。代码如下:
为了更好的展示玩家的位置,我们为
Player
结构体添加一个显示位置的方法,如下所示:
接着我们使用前面介绍的距离公式,编写计算两点之前距离的函数,如下所示:
接下来,本文的重点来了,我们编写怪物AI的核心逻辑,如下所示:
上面这个方法让怪物具有一定的智能行为,它会根据玩家的位置来计算出移动方向,并按照怪物的速度更新怪物的位置,使怪物不断地接近玩家。
当玩家位置更新后,怪物也会根据新的位置来计算移动方向,并更新自己的位置。就好像怪物具有意识一样,它会根据玩家的位置来做出反应。
最后,我们在
main
函数中演示一下怪物靠近玩家的过程,代码如下:
在
main
函数中,我们首先创建了玩家和怪物两个实例,然后展示玩家的位置,接着创建了一个
ch
通道。
然后使用
go
关键字加一个匿名函数的调用启动了一个
Goroutine
,这个匿名函数的逻辑是在一个死循环中,不断地调用怪物的
moveTowards
方法靠近玩家,然后判断玩家的位置是否和怪物的位置相同,如果相同,则打印出
怪物 1 遇上了玩家:leicw,准备攻击...
的信息后使用
break
退出循坏, 否则该 Goroutine 睡眠一秒后进入下一轮循坏。
有读者可能会有疑问,为什么这里要使用一个
ch
通道?这是因为 main 函数是在是 主Goroutine 中执行的,本例中使用 go 关键字启动了另外一个 Goroutine,这两个 Goroutine 是并发执行的,如果不使用通道的话,我们无法在主协程中等待 Goroutine 执行完毕,这样就会导致该 Goroutine 还未执行完就因 主协程退出而提前结束了。
这里通过创建一个没有缓冲的通道
ch
, main函数的末尾使用
<-ch
来等待 Goroutine 执行完毕,当 ch 中没有数据时,main 函数会一直在这里等待,当 Goroutine 执行完毕后,会向 ch 中写入一个
true
的值,main 函数会从 ch 中读取到这个值,然后退出程序。
通过这个例子,读者可以了解到如何使用 Go 语言来编写游戏后端代码,以及如何使用 Go 语言的结构体、方法、Goroutine 和通道等特性来实现游戏中的怪物AI。
当然这只是一个简单的例子,实际的游戏中,怪物AI的逻辑会更加复杂,例如根据玩家的攻击距离来计算移动方向,根据玩家的攻击方式来调整移动速度等。
每一次 点赞 ,都是你无声的鼓励。每一颗爱心,都是我前行的动力。每一次 分享 ,都是知识的传递。 关注我 ,追更不迷路!