今天要来实际运用前两天读的碰撞概念,来为我们的弹珠台加上碰到後的处理与效果。
如果忘了我们的实作目标,影片附上让大家Recap一下。
另外也搬运我们的需求,列出我们要做的事。
一样,加上粗体的就是要做的项目。
首先是颜色钉的产生,颜色钉与其他钉本来的差异只有在被撞到的时候识别,我们这边用 lable 属性来处理,Lable属性在API文件中有这样提到
An arbitrary String name to help the user identify and manage bodies.
也就是拿来让我们识别用的,记得我们昨天是比较粗糙的用 Id 来辨识,但 Id 主要是自动安排的,用label 来在创建方形的时候附上指定 Tag,碰撞事件发生时,就能够使用 label 来知道碰撞的对象。
mainBall.label = "MainBall";
另外今天我们要创造两种颜色钉,一种是黄色,一种是红色。
这边我们对之前的扣做一个小重构,原本的钉跟新的两种钉只差在颜色与 label 属性,我们不需要复制三次产生的代码,应该要抽出来变成函式。
function formBlockWithOptionAndCount(blockCount,blockOptions,blockCoordinateList,labelName)
{
for(var i=0; i<blockCount; i++)
{
var blockCoordinate = getRandomCoordinateForBlocks(blockCoordinateList);
var block = Bodies.rectangle(blockCoordinate.x, blockCoordinate.y, blockSize, blockSize, blockOptions);
blockCoordinateList.push(blockCoordinate);
block.label = labelName;
Composite.add(engine.world, [block]);
}
}
依据传入的参数来决定产生的数量、样式与附加 label。
产生钉子的数量一样用外部丢入,为了制造随机性,我们共用这个数量分配给各种颜色钉,同时颜色钉为随机分配数量。
//input total count as blockCount
var rainbowBlockCount = Math.floor(blockCount/10) + Math.floor(Math.random()*3) - Math.floor(Math.random()*2);
var goldBlockCount = Math.floor(blockCount/6) + Math.floor(Math.random()*3) - Math.floor(Math.random()*2);
var normalBlockCount = blockCount - rainbowBlockCount - goldBlockCount;
再来是碰撞侦测,我们在engine上附加一个侦测碰撞开始的事件。
Events.on(engine, "collisionStart", collisionTriggered);
function collisionTriggered(e)
{
if(e.name == 'collisionStart' && e.pairs.length > 0)
{
if(e.pairs[0].bodyB.label =="EndingBlock") triggerEnding();
if(e.pairs[0].bodyB.label !="GoldBlock" && e.pairs[0].bodyB.label !="RainbowBlock") return;
if(e.pairs[0].bodyB.label =="GoldBlock") ballStatus += 1;
if(e.pairs[0].bodyB.label =="RainbowBlock") ballStatus += 2;
Composite.remove(engine.world, e.pairs[0].bodyB);
}
console.log(ballStatus);
if(ballStatus == 1)
{
mainBall.render.fillStyle = "#FFD700";
}
if(ballStatus >= 2)
{
mainBall.render.fillStyle = "red";
}
}
在碰撞触发後,我们会在碰撞时侦测碰撞对象的 label。
碰撞事件的 pair 有一个规律, id 小的物体会是 bodyA, id 即是创造的先後顺序,所以一开始我们的球是一开始最先创建的。这方便我们侦测被球碰撞物体的时候,都针对 bodyB 做判断就是判断被球撞的对象了。
所以在这段碰撞扣里面,我们都是用 bodyB 做判断,另外有一个全域 BallStatus 的来判断目前的碰撞次数。
由於颜色钉会让球变色,在设计上(影片中)碰一次颜色钉就会消失,我们透过其中的这行来处理物件移除。
Composite.remove(engine.world, e.pairs[0].bodyB);
另外我们掉落到最後想要看到一个结束讯息,这样比较有感觉,所以这边我们创一个比较特别的方形,用到一些选项 isSensor + isStatic, isSensor 不会对碰到的物体产生碰撞改变,只会有碰撞反应。可以想像成是碰撞区域的概念,同时要加上 isStatic 让他不会移动,最後加上 lable 来让我们在碰撞时能够侦测。
function formEndingTrigger()
{
var wallBottom = Bodies.rectangle(canvasWidth/2, canvasHeigh+400, canvasWidth, 100, { isSensor:true, isStatic:true, label:"EndingBlock" });
Composite.add(engine.world, [wallBottom]);
}
function triggerEnding()
{
var resultString;
switch (ballStatus)
{
case 0 : resultString = "White"; break;
case 1 : resultString = "Gold"; break;
case 2 : resultString = "Rainbow"; break;
default : resultString = "Rainbow"; break;
}
alert("Your result is [" + resultString + " Ball] !" );
}
透过以上的代码,我们成功让颜色钉可以碰撞变色,模仿影片中基本机制。
对了读者应该有发现,我们的画面美术上跟影片有些差距,那个不在这次主题的探讨范围中,最後实作会用 sprite 来覆盖,30天的主要文章部分不会特别提到这个。
明天我们来看一下,怎麽样操作镜头的部分,让镜头运行可以更贴近影片中的样子。
前言 各位早安,书接上回我们练习了字串跟变数的应用,今天我们要来认识列表 List python列表...
「不是那个MAC。 不对,也不是汉堡。」 MAC能吃吗? 先前我们介绍了数位签章,今天我们要介绍的是...
虽然与网页互动的过程会花费更多的时间,但它却是吸引人很重要的一项因素,因此在设计部落格版面的时候,有...
Vaadin 简介 Vaadin 是一款由芬兰 Vaadin 公司所开发,用於建构网路应用程序和网站...
最近工作上常会需要对一个 array 做批次处理,所以整理一下 PHP 做 array mappin...