使用Lua的协程来实现简单的回合制战斗逻辑

2020-03-07 21:10

在回合制游戏的开发中,控制战斗流程的逻辑有很多种方式。比较常见方式都是使用回调,感觉使用回调的方式可能会有些许凌乱,所以这里试想着使用协程来实现一下,流程应该会比较的清晰。
因为使用了love2d(但并没有使用太多API),这里可能需要对love2d有一些小小的了解才能比较顺畅的阅读,如果你不太熟悉可以在这里做一些简单的了解。

环境

1.Windows 10
2.Love2d 11.3

代码

这里简单的编写一个Role(角色)基类,在init方法中可以传递该人物的名称作为标记。Role里面包含了一个attack(攻击动画过程)动作,动作执行后会将协程暂时挂起并开启一个变量用于储存动作执行时间,时间结束后则触发attacked(攻击结束)方法,将协程继续运行。
这里有一个printf方法,用于在打印时在打印信息前加上当前的运行时间,便于我们观察整个过程,它被声明在main.lua文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
-- Role.lua
local Role = {};

function Role:init(name)
self.name = name;
self.attackDelay = -10;
end

function Role:attack(coroutine_)
printf (self.name .. " attack")
self.coroutine_ = coroutine_;
self.attackDelay = 2;
return coroutine.yield()
end

function Role:update(dt)
self.attackDelay = self.attackDelay - dt;
if self.attackDelay <= 0 and self.attackDelay > -10 then -- 确保完成一次
self:attacked();
self.attackDelay = -10;
end
end

function Role:attacked()
coroutine.resume(self.coroutine_)
end

return Role;

在main的文件开头初始化两个对象并命名为Hero与Monster。

在游戏加载完成后(love.load)。定义了用于执行战斗流程的协程方法。这里将战斗轮次限定为5轮,每一轮战斗开始结束都加上了打印。在每一轮战斗中由Hero与Monster轮流进行attack动作,直到轮数上限后结束。
最后由coroutine.resume来启动战斗。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
-- main.lua
local Role = require("Role")
local hero = setmetatable({} , {__index = Role});
local monster = setmetatable({} , {__index = Role});
hero:init("Hero");
monster:init("Monster");

function printf(...)
print(os.clock() ,...)
end

function love.load()
local coroutine_
local round = 5;
coroutine_ = coroutine.create(function ()
printf "fight begin"
for i=1, round do
printf("round " , i, " begin")

hero:attack(coroutine_);
monster:attack(coroutine_);

printf("round " , i, " end")
print("---------------------")
end
printf "fight end"
end)

coroutine.resume(coroutine_)
end

function love.update(dt)
monster:update(dt);
hero:update(dt);
end

这里是执行之后打印的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
0.606   fight begin
0.607 round 1 begin
0.608 Hero attack
2.61 Monster attack
4.612 round 1 end
---------------------
4.613 round 2 begin
4.613 Hero attack
6.597 Monster attack
8.599 round 2 end
---------------------
8.603 round 3 begin
8.605 Hero attack
10.584 Monster attack
12.586 round 3 end
---------------------
12.596 round 4 begin
12.599 Hero attack
14.572 Monster attack
16.574 round 4 end
---------------------
16.575 round 5 begin
16.576 Hero attack
18.561 Monster attack
20.563 round 5 end
---------------------
20.57 fight end

可以看得到的是打印的信息与战斗流程代码中的逻辑执行顺序一致,这让人观察起来十分的清晰。

后记

这里只是简单编写了基础的结构,如果实际开发可能会遇到其他的一些问题。
(其实本来是想写使用Typescript+Promise,因为一些原因还是使用了Lua协程来实现了


标签: lua,

Creative Commons ©fox 2017 - 2018 | Theme based on fzheng.me &