上周用www.tangide.com完成了了一个新游戏 大家都来玩儿玩儿吧
我绝对没收M族一毛钱,只是正好拿他们做例子罢了
0: 在线运行:
http://www.i5r.com.cn/apprun-upyunosgames1%7C591436940011324.html
1: 制作思路
之前在制作横屏过关类型游戏的时候都使用 创建好呢长的虚拟场景,然后不停的生成障碍物和金币的方法去实现.
那时发现这种大场景+多元素动态生成对手机性能有较高的要求. 如果短时间内触发多个事件渣点的手机容易出现卡顿现象.
这次做的<美女弹弹弹>就是带捡金币机制的<忍者弹弹弹>,打算一改这种方法 规避可能卡顿的问题.
这游戏的界面中的主角是小人,
她需要跳跃到的作为落脚点的柱子,
摔下去会淹死的多图层海水
需要无缝拼接并随着小人跳动已一定速率移动的背景图.
碰到可以加分的商品(这里用的是手机)
得分板
游戏界面上需要考虑的就只有这些. 那么该如何不自动生成新柱子 不自动生成新手机 不设置巨大的虚拟场景宽度来规避卡顿呢?
我的方法是.
1: "镜头"位置不变,
2: "小人"位置不变,
3: 玩家按下屏幕时 通过移动"柱子","手机"和"背景"让小人看起来是在往→前进.
4: 当"场景"或"柱子"消失在屏幕左侧时,将他们移动到最后一个"场景"或"柱子"后面.
这样就能保证柱子不停的出现但是不需要做删除和新增柱子的操作了. 所有元素在游戏第一次加载时就已经准备好了不用中途添加.
2: "小人","柱子"和需要展示的"商品"的初始化
小人的本体其实是弹簧! 没错,我是用的是一个有质量的刚体座位弹簧,小人只是随着他移动的图片
win.springMove = function() { //spring.x = man.x+24; man.x = spring.x-24; man.y = spring.y-man.h+2; };
游戏开始前只有一根柱子和一个商品,游戏开始后对它们进行复制,一共得到8个柱子 8个商品
海浪2,和海浪3的层数提高 让他们显示在柱子的上层 这样更有层次感,其中海浪2也是小人淹死的触发器.
win.tubeInit = function() { console.log("dd_tubeInit"); var baseTube = win.find(TUBE+0); baseTube.setPosition(50,win.h-(800-492)); spring.setPosition(baseTube.x+5,baseTube.y-spring.h); man.y = (spring.y-man.h+2); for (var i=1; i<=7 ;i++) { if (!win.find(TUBE+i)) { win.dupChild(TUBE+"0").setName(TUBE+i); } win.find(TUBE+i+"/标号").setText(i); var x = win.getTubeX(i); var y = win.getTubeY(i); win.find(TUBE+i).setPosition(x,y); } win.find("海浪2").setZIndex(30); win.find("海浪3").setZIndex(32); }; win.goodInit = function() { for (var i=1;i<=7;i++) { var tube = win.find(TUBE+i); if (!win.find("商品"+i)) { win.dupChild("商品0").setName("商品"+i); win.find("商品"+i+"/text").setText(i); } win.find("商品"+i).setEnable(true); win.find("商品"+i).setVisible(true); win.find("商品"+i).opacity = 1; win.find("商品"+i).setPosition(tube.x,tube.y-win.find("商品"+i).h); } };
3: 小人跳动,柱子移动
按下屏幕的时间越久小人跳的越远 最多积蓄1秒钟的力量.
实现这点 我需要知道鼠标按下了多久.这里我使用了计时器的getelapsedtime()方法. 当然也有其他简单,和同样可靠的方法.
win.pointDown = function() { timer.stop(); timer.start(); if (manPlaying || amLanding) { return; } if (spring.h < springOH) { console.log("弹簧高度不对! 现在只有: "+spring.h); } }; win.pointUp = function() { if (manPlaying || amLanding) { return; } manPlaying = 1; timer.pause(); var timeGap = timer.getelapsedtime(); if (timeGap > 1000) { timeGap = 1000; }else if (timeGap < 0) { timeGap = 0; } if (timeGap <= 115 && timeGap>=100) { timeGap = 99;//防止连按时失误 } //console.log("dd_pointUp : timeGap = "+timeGap); win.manJump(timeGap); win.tubeMove(timeGap,function() { win.tubeXCheck(); }); };知道了按下时常我就可以将他转化为小人上跳的速度和柱子需要移动的距离了.
我还计算了小人跳起来的滞空时间 以参考柱子可以用来移动的时间
win.tubeMove = function(power,onDone) { power = Math.ceil(power/100);// 1~10 var distance = (MAXdisTANCE - MINdisTANCE)/10 * (power-1) + MINdisTANCE; var during = ((MAXTIME-MINTIME)/10 * (power-1)) + 300 ; win.bgMove(distance,during,function(){ win.bgXCheck(); }); for (var i=0;i<=7;i++) { var tube = win.find(TUBE+i); var moveLeft = { duration:during,xStart:tube.x,xEnd:tube.x-distance,//interpolator:"deceleration" interpolator: "l" }; tube.animate(moveLeft,function onDone(_obj) {}); if (win.find("商品"+i).isVisible()) { var good = win.find("商品"+i); var goodLeft = { duration:during,xStart:good.x,xEnd:good.x-distance,//interpolator:"deceleration" interpolator: "l" }; good.animate(goodLeft,function onDone(_obj) {}); } if (i == 7) { setTimeout(function() {onDone();},during+200); } } }; win.bgMove = function(distance,onDone) { for (var i=2; i>=0; i--) { var bg = win.find(bgPic[i]); var bgLeft = { duration:during,xStart:bg.x,xEnd:bg.x-(distance/3),interpolator: "l" }; bg.animate(bgLeft,function onDone(i) {}); if (i === 0) { setTimeout(function() {onDone();},during+100); } } };
win.addTime = function() {//弹簧压缩效果 if (manPlaying || amLanding) { return; } if (spring.h <= (1/10)*springOH) { console.log("dd_addTime : spring.h is Too low :"+spring.h); return; } spring.resize(spring.w,spring.h-1); man.y = spring.y-man.h+2; };这个样子 在我按下屏幕后小人会蹲下蓄力,松开后跳起,柱子和背景图会左移
起跳的的姿势就完成了.
落地姿势同样主要,有弹簧会弹的效果
win.hitTheGround = function(standing) { if (amLanding == 1 || manPlaying === 0 || firstGame == 1 /*|| getAPhone === 0*/) {//抢到手机才能继续跳 return; } //spring.setDensity(0); if(spring.y <= win.find(TUBE+standing).y-spring.h) {//用台子接住弹簧以免在reSize时滑落. iPlatf.setPosition(spring.x,spring.y+spring.h); } me.playSoundEffect("跳下落地声.mp3",function onDone() {console.log("跳下落地声.mp3 play finished");}); getAPhone = 0; console.log("hitTheGround : "+standing); win.find("计时器2").pause();//计算出飞行所花费时长 var flyTime = win.find("计时器2").getelapsedtime(); win.myLanding(); //console.log("flyTime = "+flyTime); };
win.myLanding = function() { if (amLanding) { console.log("dd_myLanding is landing !!! ERROR"); return; } amLanding = 1; //console.log("dd_myLanding start to land"); var time = 0; var springY = spring.y; //spring.setDensity(0);//防止reSize时站不稳摔下去 function landing() { if (!win.children) { clearInterval(Interval); return; } if (time < (1-BOUNCE)*springOH) { spring.resize(spring.w,spring.h-2); }else if (time > springOH) { //spring.setPosition(spring.x,springY); spring.resize(spring.w,springOH); man.y = spring.y-man.h+2; setTimeout(function() { amLanding = 0; manPlaying = 0; },50); clearInterval(Interval); }else if (time >= (1-BOUNCE)*springOH) { spring.resize(spring.w,spring.h+1); } man.y = spring.y-man.h+2; time++; } var Interval = setInterval(landing,10); };<span style="font-family: Arial,sans-serif; background-color: rgb(255,255,255);">myLanding实现了落地后弹簧了收缩效果. 调整这个效果花了很多时间<img alt="偷笑" src="http://static.blog.csdn.net/xheditor/xheditor_emot/default/titter.gif" /></span>
4: 柱子,背景从屏幕左边消失后需要做的操作
win.tubeXCheck = function() { //console.log("dd_tubeXCheck"); for (var i=0;i<=7;i++) { var tube = win.find(TUBE+i); if (tube.x <= -(tube.w/2)) { win.goToRear(i); } } }; win.bgXCheck = function() { for (var i=0; i<3; i++) { var bg = win.find(bgPic[i]); if (bg.x+480 <= 0 || isNaN(bg.x)) { if (i === 0 ){ bg.setPosition(win.find(bgPic[2]).x + 480,0); }else { bg.setPosition(win.find(bgPic[i-1]).x + 480,0); } } } }; win.goToRear = function(i) { var x = win.getTubeX(i); var y = win.getTubeY(i); //console.log("dd_goToRear : i = "+i+" "+x+" "+y); //console.log("dd_goToRear : old xy = "+win.find(TUBE+i).x+" "+win.find(TUBE+i).y); win.find(TUBE+i).setPosition(x,y); win.find("商品"+i).setPosition(win.find(TUBE+i).x,win.find(TUBE+i).y-win.find("商品"+i).h-2); win.find("商品"+i).setVisible(true); win.find("商品"+i).opacity = 1; win.find("商品"+i).setEnable(true); };循环完成! 这样就可以无限跳跃了
5: 捡"商品"加分
win.addscore = function() { me.playSoundEffect("成功跨格跳跃.mp3",function onDone() {console.log("成功跨格跳跃.mp3 play finished");}); getAPhone = 1; score++ win.find("得分板/分数").setText(score); if (!window.highscore || window.highscore < score) { window.highscore = score; } };
win.gameOver = function() { me.playSoundEffect("落水.mp3",function onDone() {console.log("落水.mp3 play finished");}); //console.log("dd_gameOver : score="+score); var initData = {score:score,highscore:highscore}; this.openWindow("结束界面",function (retData) {console.log("window closed.");},true,initData); };
更多游戏制作案例和教程可以到tangram的官网查看视频教程http://www.tangram7q.com/