用协程手动控制基于Lua的两种框架:Codea和Love2D的流程
用协程手动控制基于Lua的两种框架:Codea和Love2D的流程
FreeBlues 发表于5个月前
用协程手动控制基于Lua的两种框架:Codea和Love2D的流程
  • 发表于 5个月前
  • 阅读 35
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   

用协程手动控制基于Lua的两种框架:Codea和Love2D的流程

问题来源

最近在 Codea 官网社区看到有人提问如何在 Codea 中实现暂停, 这个帖子 Triggering the pause function Codea has _ FIXED wrote some Lua code

在 Codea 中通过宿主 Objective-C 来控制

最有效的办法当然是通过修改 Lua 的宿主语言 C 来挂起整个虚拟机, 具体方法如下:

Codea 导出的 XCode 项目中打开包含 StandaloneViewController.m 文件, 然后修改这个:

StandaloneViewController *cc=self.viewController

把视图控制器保存到变量 cc 中, 那么暂停只需执行如下语句

cc.paused=YES;

恢复只需执行如下语句:

cc.paused=NO;

这应该是一种比较彻底的解决方法, 不过显然无法在 Lua 中来执行, 在 Lua 中它只能暂停, 无法恢复.

在 Codea 中通过 debug 函数来控制

也有人提出用利用 debug 函数的钩子来实现, 代码如下:

function setup()
    x=10
    y=400
    xv=1
    yv=1
    cnt=0
    sec=10
    debug.sethook(loop,"l")
end

function loop()
    while pause do
        ct=os.time()
        if ct>st+sec then
            pause=false
        end  
    end
end

function draw()
    background(40, 40, 50)
    fill(255)
    text("tap screen to pause for "..sec.." seconds.",WIDTH/2,HEIGHT/2)
    x=x+xv
    if x>WIDTH or x<0 then
        xv=xv*-1
    end
    y=y+yv
    if y>HEIGHT or y<0 then
        yv=yv*-1
    end
    ellipse(x,y,20)
    cnt=cnt+1
    text(cnt,WIDTH/2,HEIGHT-50)
end

function touched(t)
    if t.state==BEGAN then
        st=os.time()
        pause=true
    end
end

这种办法可以在 Codea 内暂停/恢复, 唯一的问题是没办法精确控制, 只能用定时器.

在 Codea 中通过协程来控制

我想到的就是用协程来控制流程, 代码如下:

function setup()
    pause = false
    -- Create a new coroutine for the function f
    co = coroutine.create(f)

    box = { x = 10, y = 10,
            width = 20, height = 20,
            fillColor = color(24, 28, 202, 255) }

    -- Here we can not use tween.
    -- t = tween(10, box, {x = 1000, y = 1000})
end

-- Put all your draw code in f
function f()
    while not pause do

        background()
        fontSize(40)
        fill(0,255,0)
        text(os.time(),WIDTH/2,HEIGHT/2)

        fill(box.fillColor)
        box.x, box.y = box.x+1,box.y+1
        rect(box.x,box.y,box.width,box.height)

        coroutine.yield()
    end
end

function draw()
    if not pause then
        coroutine.resume(co)
    end
end

function touched(t)
    -- Click left screen to pause, click right screen to resume
    if t.state == BEGAN and t.x >=WIDTH/2 then
        pause = false
    elseif t.state == BEGAN and t.x <WIDTH/2 then
        pause = true
    end
end

用协程的优点是可以精确地控制流程, 缺点是所有的地方都要考虑到, 另外一个问题就是可能带来性能损失.

在 Love2D 中通过协程来控制

上面的代码稍作修改就可以用在 Love2D 中, 修改后的代码如下:


function love.load()
	canvas = love.graphics.newCanvas(800, 600)
	
	love.graphics.setBackgroundColor(0, 0, 0)
    pause = false
    -- Create a new coroutine for the function f
    co = coroutine.create(f)

    box = { x = 10, y = 10, width = 20, height = 20}
end

function f()
    while not pause do
    	--love.graphics.setCanvas(canvas)
    	love.graphics.setBlendMode("alpha")
		love.graphics.setColor(255, 255, 0)
		love.graphics.print(os.time(), 300,400)
        love.graphics.setColor(0, 255, 0)
        box.x, box.y = box.x+1,box.y+1
        love.graphics.rectangle("fill", box.x, box.y, box.width, box.height)
        --love.graphics.setCanvas()
        
        love.graphics.setBlendMode("alpha")

		--love.graphics.draw(canvas)
        coroutine.yield()
    end
end

function love.draw()
	if not pause then
        coroutine.resume(co)
    end
end

function love.update(delta)	
	if love.keyboard.isDown("p") then
		pause = true
	elseif love.keyboard.isDown("s") then
		pause = false
	end	
end

唯一的问题就是每当暂停时, 屏幕就不显示任何内容了, 这种情况显然是因为我对 Love2D 的处理机制理解存在一些小问题, 有时间了再慢慢分析.

标签: 协程 lua love2d codea
共有 人打赏支持
粉丝 92
博文 268
码字总数 483689
×
FreeBlues
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: