javascript异步编程系列【十】—Jscex+Easeljs制作坦克大战
2011-09-15 08:01 【当耐特】 阅读(5534) 评论(13) 编辑 收藏 举报一.简介
为了利用当今和未来的硬件,您可以对代码进行并行化,以将工作分摊在多个处理器上。 往往,并行化需要线程和锁的低级操作,但是Jscex不用,因为javascript这种解释型语言,仅仅需要一个线程来解释它,已其他线程无关,且不冲突!
二.回顾
上面介绍了一下Easeljs以及其优势,并且利用Easeljs+Jscex实现了坦克的右移以及开炮,但是还存在许多问题,比如移动不能开炮,开炮不能移动。
这篇主要利用Jscex并行编程模型搭起游戏的基本框架,并且解决坦克的转弯和开火。
三.架构设计
昨天我仔细想了想,不管是任何东西,拆得越细就越好控制。如果使用Easeljs的tick(也就相当于Jscex的while(true)),任何东西都往里面丢,函数冗长,不能灵活控制。Jscex有个很明显的优势,它可以轻松挂起一个while(true),用于监听,然后根据监听的结果做出相应的操作。所以,我把坦克大战拆成以下七个异步任务,游戏的所有元素都在下面七个异步任务当中:
a.坦克的移动
b.子弹的生产
c.子弹的飞行
d.碰撞检测,比如击中墙壁,击中敌方坦克
e.宝物的生成,比如增加火力的宝物,增加生命的宝物
f.统计任务,比如消灭敌军坦克获取积分
g. GameOver监听,比如老巢被灭,比如自己牺牲并且剩余生命条数为0
这七个任务同时执行,看似相互独立,其实是相互影响,比如
碰撞检测到击中敌方坦克,就会触发统计任务,
击中掉宝坦克,触发宝物的生成
被敌方坦克消灭老巢,触发GameOver
四.转弯和开火
开始打算用rotation属性来旋转图片,实现转弯,并且带有转弯动画,这也算超越了以前的坦克大战。然后rotation旋转图片不会以图片的中心旋转,而会以图片左上角为基准点旋转,这叫我情何以堪!旋转效果如下:
好吧,我还是用四张图片吧,反正素材就提供了4张图片。
我们把转弯与开火拆成三个异步任务:
a.坦克的移动
b.子弹的生产
c.子弹的飞行
坦克的移动:
var moveAsync = eval(Jscex.compile("async", function () { var i = 0; while (true) { if (goRight == true) { bmpR.visible = true; bmpL.visible = false; bmpD.visible = false; bmpU.visible = false; bmpL.x += 1; bmpR.x += 1; bmpD.x += 1; bmpU.x += 1; } if (goLeft == true) { bmpR.visible = false; bmpL.visible = true; bmpD.visible = false; bmpU.visible = false; bmpR.x -= 1; bmpL.x -= 1; bmpD.x -= 1; bmpU.x -= 1; } if (goUp == true) { bmpR.visible = false; bmpL.visible = false; bmpD.visible = false; bmpU.visible = true; bmpR.y -= 1; bmpL.y -= 1; bmpD.y -= 1; bmpU.y -= 1; } if (goDown == true) { bmpR.visible = false; bmpL.visible = false; bmpD.visible = true; bmpU.visible = false; bmpR.y += 1; bmpL.y += 1; bmpD.y += 1; bmpU.y += 1; } stage.update(); $await(Jscex.Async.sleep(10)); } }))
生成子弹:
var bulletStream = new Array(); var createBulletAsync = eval(Jscex.compile("async", function () { var i = 0; while (true) { if (shootHeld == true) { bulletStream[i] = new Bitmap("image/tankmissile.gif"); if (bmpD.visible == true) { bulletStream[i].direction = "down"; bulletStream[i].x = bmpR.x + 21; bulletStream[i].y = bmpR.y + 60; } if (bmpL.visible == true) { bulletStream[i].direction = "left"; bulletStream[i].x = bmpR.x ; bulletStream[i].y = bmpR.y + 21; } if (bmpR.visible == true) { bulletStream[i].direction = "right"; bulletStream[i].x = bmpR.x + 60; bulletStream[i].y = bmpR.y + 21; } if (bmpU.visible == true) { bulletStream[i].direction = "up"; bulletStream[i].x = bmpR.x + 21; bulletStream[i].y = bmpR.y ; } stage.addChild(bulletStream[i]); i++; } stage.update(); $await(Jscex.Async.sleep(200)); } }))
我们要在生成子弹的时候,告诉子弹的方向,也许以后会扩展一个子弹的速度。
子弹的飞行:
var fireAsync = eval(Jscex.compile("async", function () { while (true) { for (bullet in bulletStream) { if (bulletStream[bullet].direction == "up") { bulletStream[bullet].y -= 10; } if (bulletStream[bullet].direction == "down") { bulletStream[bullet].y += 10; } if (bulletStream[bullet].direction == "right") { bulletStream[bullet].x += 10; } if (bulletStream[bullet].direction == "left") { bulletStream[bullet].x -= 10; } } stage.update(); $await(Jscex.Async.sleep(50)); } }))
元素初始化,并行任务开始:
function init() { canvas = document.getElementById("testCanvas"); stage = new Stage(canvas); bmpR = new Bitmap("image/p1tankR.gif"); bmpL = new Bitmap("image/p1tankL.gif"); bmpD = new Bitmap("image/p1tankD.gif"); bmpU = new Bitmap("image/p1tankU.gif"); bmpL.visible = false; bmpD.visible = false; bmpU.visible = false; stage.addChild(bmpR); stage.addChild(bmpL); stage.addChild(bmpD); stage.addChild(bmpU); Ticker.addListener(stage); createBulletAsync().start(); fireAsync().start(); moveAsync().start(); }
五.在线演示
未完待续,下篇加入敌方坦克,ohoh··········
最新的Jscex 库,请上https://github.com/JeffreyZhao/jscex或者http://www.sndacode.com/projects/jscex/wiki下载吧····
六.同步
本文已同步更新至: