近期热文(感谢掘友的鼓励与支持🌹🌹🌹)
前言
最近看到一篇文章 JS-VUE-老虎机抽奖,想起来我之前用JS游戏引擎做过一个,所以我也分享下心得体会吧。
先看最终效果
游戏引擎介绍
这里我用了一个可能大家不太熟悉的引擎,叫 annie2x,这个游戏引擎由一个js的2d引擎
和FLASH插件
组成。
怎么还有FLASH
!!
你没看错,annie2x
通过插件的形式让熟练掌握FLASH
软件的开发者更容易的生产和组织美术资源。比如将FLASH
里的MovieClip
直接转成2d引擎里可使用的代码文件。FLASH
仅仅作为美术资源,动画制作的工具而存在,代码并不在FLASH
里编写。如果你熟练掌握FLASH
,annie2x
可以将H5的开发效率大大提升,在时间就是金钱的广告圈里,这个框架用户还是挺多的。
开发思路
虽然使用的是游戏引擎,但思路和逻辑是一样的。
循环滚动
首先将所有元素按相同尺寸排列在一张图片上,排列顺序是1234561
。通过控制图片的y
轴坐标来进行滚动,当最后一个元素显示完时,瞬间将图片的y
轴归零,就可以循环滚动起来了。
我在这里建立了一个独立的对象RollingMC,让一个纵列作为整体去管理自己的运动逻辑。
AnnieRoot.game=AnnieRoot.game||{};
game.RollingMC=function(){
var s = this;
annie.Sprite.call(s);
/*_a2x_need_start*/s.content_mc=null;/*_a2x_need_end*/
annie.initRes(s,"game","RollingMC");
var isRolling = false;
var speed;
var speedVal;
var timer;
var loopCount;
var curLoop;
var tposY;
s.startRoll=function(index,tpos) {
//index指示当前是第几纵列,主要用于控制一个圈数差
//tpos为最后落点的位置序号
isRolling = true;
curLoop=0;
speed = 0;
speedVal=1;
//每次都转10圈打底,按第几纵列的顺序+2圈
loopCount=10+index*2;
//将tpos换算为y轴坐标
tposY = tpos*-204;
// console.log("最后将落在Y:",tposY);
timer=window.requestAnimationFrame(loop);
}
function stopRolling() {
window.cancelAnimationFrame(timer);
isRolling = false;
}
function loop() {
timer=window.requestAnimationFrame(loop);
if (!isRolling) return;
speed += speedVal;
if (speed > 50) speed = 50;
else if (speed < 1) speed = 1;
s.content_mc.y -= speed;
if (s.content_mc.y < -1428) {
curLoop+=1;
s.content_mc.y = -speed;
}
if(curLoop>=loopCount){
if(s.content_mc.y<=tposY){
s.content_mc.y = tposY;
stopRolling();
}
}
}
};
A2xExtend(game.RollingMC,annie.Sprite);
停止
如上面的代码所示,在启动滚动时,我传入了一个index
参数用于让第123列的滚动次数上产生差异。另外还传入了一个tpos
,代表targetPosition,用来控制最终停止位。
//如果当滚动圈数达到预计滚动圈数时
if(curLoop>=loopCount){
//当图片的y轴坐标达到指定坐标时停止滚动
if(s.content_mc.y<=tposY){
s.content_mc.y = tposY;
stopRolling();
}
}
控制三个纵列的滚动,让启动的时间相隔500毫秒
function startRollingContent(index){
s.main_mc["rolling_" + index].startRoll(index,pos_arr[index]);
s.main_mc["rolling_" + index].didRollingStop = function () {
rollingCount+=1;
if (rollingCount>=3){
rollingFinished();
}
}
}
setTimeout(function () { startRollingContent(0) }, 0);
setTimeout(function () { startRollingContent(1) }, 500);
setTimeout(function () { startRollingContent(2) }, 1000);
几率控制
- 抽奖游戏就没有真随机的!
- 抽奖游戏就没有真随机的!
- 抽奖游戏就没有真随机的!
重要的事情说三遍!!!
在每次启动前会通过接口去获取最终要停止的位置
//前端代码片段
utils.RequestApi("luckyroll",{},function(res){
loading.hide();
if(res.err==0){
pos_arr = res.result.posarr;
award=res.result.award;
realStart();
}else{
weui.alert(res.msg);
}
});
服务端也是我写的,在服务端我首先是真的通过随机获得三个纵列的最终停止位。
//后端代码片段
function getRandomPosCheckInventory(){
global $db;
global $openid;
$pos_arr = getRandomPos();
$pos_str = join(",",$pos_arr);
//这里我们会获得一个真正的随机的位置,值是0,0,0这种格式,代表最终三个纵列停止位的序号
但可恨
的是,我会通过查询数据库里奖品表的库存项来决定要不要给你发奖。如果有库存,那就给你。如果没库存,即使你随机中奖了,也会被我强行变为没奖。
//后端代码片段
if ($pos_str === "0,0,0") {
//三个水杯
$award=isEnoughInventory("水杯");
if (!isset($award))return array("posarr"=>getNoAwardPos());
}else if (substr_count($pos_str,'0')==2&&(substr_count($pos_str,'2')==1 || substr_count($pos_str,'3')==1 || substr_count($pos_str,'4')==1 || substr_count($pos_str,'5')==1)) {
//两个水杯+一个宠物
$award=isEnoughInventory("玩偶");
if (!isset($award))return array("posarr"=>getNoAwardPos());
是的,为了服务器效率,我并不会去找一个有库存的小奖给你,而是直接判定为无奖。
可恨
可恨
可恨
运气被白白浪费了呢~
体验地址
在电脑上打开记得开启手机浏览模式
关注大帅搞全栈
感谢大家点赞,我挖到的金子一定全部分给大家