最近在学习godot这个游戏引擎,之前有相关学习unity来着,不过稍微了解了解一下就放弃,还是因为迈的太大了吧。
之前有用java的一个游戏引擎`libgdx`写过一个`2048`,成品可以看[这里](https://www.coolapk.com/game/241438) ,不过libgdx的局限还是蛮大的,用来写小游戏还行,不过周边的工具还是太少了,比如你要写个2d游戏,tileMap都要用第三方的。所以最近就尝试用这个godot来重新来写了这个游戏。后续可以尝试一下别的
`godot` 相比与 `unity`,`unreal`这种还算是非常轻量的了,而相比比哪些网页游戏引擎,功能要强上不少,这是我初次上手的第一印象。
不过,godot官方主要推荐使用的自研的gdscript游戏脚本,一个类似python的脚本,有着和游戏引擎契合的特殊语法,比如可以用 `&Label` 这种来直接获取界面中的元素。
我个人是不太喜欢这种脚本的,因为我在重写2048d这个游戏的因为这个脚本遇到了一些bug,好久都没有解决,也有可能是我的技术问题。最后选择用了c#,还是静态语言写着舒服。
游戏的成品大概就是这样子
![image.png](https://s2.loli.net/2022/05/02/FIdQ1HXCbqfWpey.png)
后面又用 kotlin的一个web框架 ktor来给他写了个排行榜。
然后就是这样吧,分享一下游戏的主要逻辑:
首先游戏就是 一个n*n的数组,n是游戏的列数,这个我用一个数组保存,数组为null的元素代表这是个空元素,不为空的则是一个块,它有一个power属性,用于储存这是2的几次方,然后两个相同的power相遇时,删除掉之前的那个,后个power+1即可。
```csharp
//右滑的逻辑
private void _Right()
{
for (int x = Size - 2; x > -1; x--)
{
for (int y = 0; y < Size; y++)
{
//循环处理每个方块
var index = GetBlockIndex(x, y);
var block = _blocks[index];
if (block == null) continue;
//方块从右向左依次检查
for (var i = x + 1; i < Size; i++)
{
var targetIndex = GetBlockIndex(i, y);
var target = _blocks[targetIndex];
if (target == null)
{
//下个方块不为空,就移动过去
_blocks[index] = null;
_blocks[targetIndex] = block;
block.Call("moved_to", _blockPositions[targetIndex]);
index = targetIndex;
}
else if (target.Get("power").Equals(block.Get("power"))
&& !(bool) target.Get("come_double")
&& !(bool) block.Get("come_double"))
{
//下个方块和当前方块一样,并且没有合并过,就合并
_blocks[index] = null;
_blocks[targetIndex] = block;
block.Call("moved_to", _blockPositions[targetIndex]);
block.Call("be_double");
AddScore((int) block.Get("power"));
index = targetIndex;
((Node) target).QueueFree();
}
else
{
//其他情况就是当前方块不能移动
break;
}
}
}
}
}
```
```python
#每个方块的逻辑,移动动画与缩放
func _process(delta):
if in_moved:
var x
self.rect_position.x += move_speed_x * delta
self.rect_position.y += move_speed_y * delta
now_time += delta
if now_time > move_animate_time:
in_moved = false
now_time = 0
self.rect_position = new_position
elif come_double:
now_time += delta
var scale = sin((now_time*PI)/double_animate_time)*0.1
self.rect_scale = Vector2(1+scale,1+scale)
var offset = (rect_size.x * scale)/2
self.rect_position = Vector2(new_position.x - offset,new_position.y -offset)
if now_time > double_animate_time:
come_double = false
now_time = 0
self.rect_scale = Vector2(1,1)
self.rect_position = new_position
power += 1
self.texture = blocks_images[power-1]
$Label.text = str(pow(2,power))
pass
```
然后就是这样。
游戏的成品可以去 [game.thetbw.xyz](https://game.thetbw.xyz),我后续的游戏都会放在这里。
最后就是,打包的体积还是大了点,之前libgdx写的2048好像才十几兆,这个已经到四十兆了,这种简单的游戏其实不要1m的html就可以解决,用这个还是太奢侈了,想起之前玩的《天天酷跑》也才将近30兆,后续还要考虑下如何优化游戏尺寸。
用Godot做了个小游戏