Pongo网页版JavaScript源代码及设计思路
来源:互联网 发布:mac 10.12懒人版下载 编辑:程序博客网 时间:2024/05/16 04:01
1.游戏背景介绍(写在前面的废话):
五月初的某天,看到某网推荐了这款游戏,Pongo,看着还不错的样子就用ipad下下来试玩了下,玩了两局感觉还错挺过瘾的,因为是手欠类游戏嘛大家懂的。
但是没一会发现游戏在ipad似乎有些bug,玩一会就会卡住然后只能强退了,真是揪心,记录还等着破呢。
怎么办?玩游戏不如玩自己的游戏的念头又邪恶的出现了,然后就把pad丢给了朋友虐心去,我默默回到电脑前开始动手自己写个不会卡的。
大概两小时吧,写出了基本框架,然后扔sinaapp里试了下效果基本能玩就洗洗睡了。
第二天醒来因为周末没事就花了些时间设计了下界面,同时不幸自己测出了一些比较严重的bug,最后又花了些时间给改掉了。
最后游戏取名”Pongo+“(手机党点我即玩),电脑端暂时不支持,并顺便在Github上上传了源码并去掉了提交成绩模块。
2.游戏试玩网址:
Pongo+(仅限移动端):http://mypongo.sinaapp.com/
github开源(欢迎fork让游戏更好):https://github.com/ChenReason/pongo/blob/gh-pages/index.html
3.游戏规则玩法:
点击屏幕会改变挡板的运动方向,点击一次挡板方向相应改变一次,目的是为了能刚好挡住四处滚动的小球不让其跑出大圆外。时间越长越好!最后可提交自己的成绩进行排名!
4.游戏所用技术:
HTML、CSS、JavaScript、Canvas、PHP
5.游戏设计思路:
a)运用Canvas将游戏的主界面画出,底部为一单色长方形,上面覆盖一个大圆,大圆上再绘制小圆及挡板,挡板中部还有一个大小为1px的超级小圆(作实现碰撞检测)。
b)小圆运动方向一共有8个分别为上、下、左、右、左上、左下、右上和右下。
c)挡板的运动方向只有两个,顺时针和逆时针。
d)碰撞检测未涉及到引擎的使用,而是根据小圆与挡板中部的超级小圆进行距离判断,从而实现简陋的碰撞检测。
e)小球碰撞后反弹的方向确定,利用常识列举,共8种情况。
6.游戏实现难点:
a)碰撞检测。
b)定时器setInterval的清除时机以及是否清楚彻底。
c)定时器周期长短与游戏体验的关系。
d)Android与IOS设备性能不同导致的游戏流畅度问题。
7.游戏现有问题:
a)由于碰撞检测是比较两圆的圆心距,且涉及到定时器的使用,因此由于定时器间隔极短导致在肉眼所见的一次碰撞背后其实已经发生了数十次碰撞,由此会导致小球最后实际的反弹方向与现实的物理定理有所不同,经过优化,出现的概率已经较低,但仍未能避免,因此有些玩家会发现小圆若没有很准地撞在挡板正中央则可能导致游戏失败。
b)由于函数过于冗长,运行效率较低,再加上使用定时器,因此在Andorid与iOS或其他移动端上的游戏体验不尽相同(整体来说iOS由于Android)。
c)排行榜并未实现自动实时更新。(数据库还不会用)
8.游戏界面预览:
(图1为初版,图2去掉了按钮,图3为最终版,图4为排行榜)
图1
图2
图3
图4
9.游戏JavaScript部分源代码:
var ifingame=0;var maxgrade=0,grade=0;var grade1,grade2;var nickname; var gamespeed=1.4;//小球速度var linespeed=Math.PI/95;//跟踪线速度var crashdistancefaild=-7;//碰撞检测参数var crashdistancesucc=15var fantanjuli=7; var themaxgradeline=12.1; function getCookie1(nickname){if (document.cookie.length>0){ c_start=document.cookie.indexOf(nickname + "=")if (c_start!=-1){ c_start=c_start + nickname.length+1;c_end=document.cookie.indexOf(",",c_start);if (c_end==-1) c_end=document.cookie.length;return unescape(document.cookie.substring(c_start,c_end));} }return ""} function getCookie2(mymaxgrade){if (document.cookie.length>0){ c_start=document.cookie.indexOf(mymaxgrade + "=")if (c_start!=-1){ c_start=c_start + mymaxgrade.length+1;c_end=document.cookie.indexOf(";",c_start);if (c_end==-1) c_end=document.cookie.length;return unescape(document.cookie.substring(c_start,c_end));} }return ""} function setCookie(nickname,value,mymaxgrade,maxgrade,expiredays){var exdate=new Date()exdate.setDate(exdate.getDate()+expiredays)document.cookie=nickname+ "=" +escape(value)+"," + mymaxgrade + "=" + escape(maxgrade) + ((expiredays==null) ? "" : "; expires="+exdate.toGMTString());}function checkCookie(){nickname=getCookie1('nickname'); maxgrade=parseInt(getCookie2('mymaxgrade')); if(isNaN(maxgrade)==true) { maxgrade=0; }if (nickname!=null && nickname!="") { alert('欢迎'+nickname+'回来!'+'\n'+"如果喜欢请分享一下哈~"); }else { nickname=prompt('请输入你的昵称:(名字太长上榜可是会显示不完整的哦)',"") if (nickname!=null && nickname!="") { var maxgradestring=maxgrade.toString(); setCookie('nickname',nickname,'mymaxgrade',maxgradestring,365); } }} var objpane=document.getElementById("pane");var ctxpane=objpane.getContext("2d");ctxpane.translate(150,150);//必备 画布中心点平移 function sendmail() { if(grade2>themaxgradeline) var max_grade=grade2; window.location.href='index.php?max_grade='+max_grade+'&nick_name='+nickname; /* { <?php$grade=$_GET['max_grade'];$nickname=$_GET['nick_name'];$mail = new SaeMail();$ret = $mail->quickSend( 'reasonpongo@163.com' , $grade , $nickname ,'reasonpongo@163.com' , 'mypongo' );$mail->clean(); ?> }*/ alert(nickname+"你的成绩为:"+grade2+"提交成功~"); } var gamedirection={shang: 1,xia: 5,zuo: 7,you: 3,zuoshang: 8,zuoxia: 6,youshang: 2,youxia: 4,clock: 0,anticlock: 9,};//方向var canvas={width : 300,height: 300,};//画布var bigcircle = {//大圆参数 x : 0, //圆心的x轴坐标值 y : 0, //圆心的y轴坐标值 r : 150, //圆的半径c : 'rgb(255,255,255)', };//大圆var smallcircle = {//小圆参数 x : 0, //圆心的x轴坐标值 y : 0, //圆心的y轴坐标值 r : 12, //圆的半径c : 'rgb(204,105,106)',direction : gamedirection.xia, };//小圆var line = {//挡板线的参数x : 0, //圆心的x轴坐标值 y : 0, //圆心的y轴坐标值 r : 150 , //圆弧的半径 start:(Math.PI/2-Math.PI/16), end :(Math.PI/2+Math.PI/16),c : 'rgb(55,55,55)',direction: gamedirection.anticlock,};//跟踪线var dot = {//跟踪点参数x:(bigcircle.r*Math.cos(line.start+Math.PI/16)),//以大圆为原点y:(bigcircle.r*Math.sin(line.start+Math.PI/16)),r:1,}//跟踪点function changelinedirection(){if(line.direction==gamedirection.clock){line.direction=gamedirection.anticlock;}else{line.direction=gamedirection.clock;}}function getdistance(){var distance=Math.sqrt((smallcircle.x)*(smallcircle.x )+(smallcircle.y )*(smallcircle.y ));return distance;}//返回小球与大圆中心距离平方 getdistance()function ifgameover(){//判断是否出界if((getdistance() - bigcircle.r)>5)return true;elsereturn false;}//判断游戏是否结束 ifgameover()function ifcrash(){//碰撞检测var dx = dot.x-smallcircle.x;var dy = dot.y-smallcircle.y;var dd=Math.sqrt(dx*dx+dy*dy);if(dd< crashdistancesucc)return true;else return false;}//碰撞检测 ifcrash()function randomback(){var x=Math.floor(Math.random()*3);switch (smallcircle.direction){case gamedirection.shang:{switch (x){case 0:smallcircle.direction=gamedirection.xia; smallcircle.y=smallcircle.y+fantanjuli;break;case 1:smallcircle.direction=gamedirection.zuoxia; smallcircle.x=smallcircle.x-fantanjuli;smallcircle.y=smallcircle.y+fantanjuli;break;case 2:smallcircle.direction=gamedirection.youxia; smallcircle.x=smallcircle.x+fantanjuli;smallcircle.y=smallcircle.y+fantanjuli;break;default:break;}break;}case gamedirection.xia:{switch (x){case 0:smallcircle.direction=gamedirection.shang;smallcircle.y=smallcircle.y-fantanjuli;break;case 1:smallcircle.direction=gamedirection.zuoshang;smallcircle.x=smallcircle.x-fantanjuli;smallcircle.y=smallcircle.y-fantanjuli;break;case 2:smallcircle.direction=gamedirection.youshang;smallcircle.x=smallcircle.x+fantanjuli;smallcircle.y=smallcircle.y-fantanjuli;break;default:break;}break;} case gamedirection.zuo:{switch (x){case 0:smallcircle.direction=gamedirection.you;smallcircle.x=smallcircle.x+fantanjuli;break;case 1:smallcircle.direction=gamedirection.youshang;smallcircle.x=smallcircle.x+fantanjuli;smallcircle.y=smallcircle.y-fantanjuli;break;case 2:smallcircle.direction=gamedirection.youxia;smallcircle.x=smallcircle.x+fantanjuli;smallcircle.y=smallcircle.y+fantanjuli;break;default:break;}break;}case gamedirection.you:{switch (x){case 0:smallcircle.direction=gamedirection.zuo;smallcircle.x=smallcircle.x-fantanjuli;break;case 1:smallcircle.direction=gamedirection.zuoxia;smallcircle.x=smallcircle.x-fantanjuli;smallcircle.y=smallcircle.y+fantanjuli;break;case 2:smallcircle.direction=gamedirection.zuoshang;smallcircle.x=smallcircle.x-fantanjuli;smallcircle.y=smallcircle.y-fantanjuli;break;default:break;}break;}case gamedirection.zuoshang:{switch (x){case 0:smallcircle.direction=gamedirection.youxia;smallcircle.x=smallcircle.x+fantanjuli;smallcircle.y=smallcircle.y+fantanjuli;break;case 1:smallcircle.direction=gamedirection.xia;smallcircle.y=smallcircle.y+fantanjuli;break;case 2:smallcircle.direction=gamedirection.you;smallcircle.x=smallcircle.x+fantanjuli;break;default:break;}break;}case gamedirection.zuoxia:{switch (x){case 0:smallcircle.direction=gamedirection.youshang;smallcircle.x=smallcircle.x+fantanjuli;smallcircle.y=smallcircle.y-fantanjuli;break;case 1:smallcircle.direction=gamedirection.shang;smallcircle.y=smallcircle.y-fantanjuli;break;case 2:smallcircle.direction=gamedirection.you;smallcircle.x=smallcircle.x+fantanjuli;break;default:break;}break;}case gamedirection.youshang:{switch (x){case 0:smallcircle.direction=gamedirection.zuoxia;smallcircle.x=smallcircle.x-fantanjuli;smallcircle.y=smallcircle.y+fantanjuli;break;case 1:smallcircle.direction=gamedirection.zuo;smallcircle.x=smallcircle.x-fantanjuli;break;case 2:smallcircle.direction=gamedirection.xia;smallcircle.y=smallcircle.y+fantanjuli;break;default:break;}break;}case gamedirection.youxia:{switch (x){case 0:smallcircle.direction=gamedirection.zuoshang;smallcircle.x=smallcircle.x-fantanjuli;smallcircle.y=smallcircle.y-fantanjuli;break;case 1:smallcircle.direction=gamedirection.zuo;smallcircle.x=smallcircle.x-fantanjuli;break;case 2:smallcircle.direction=gamedirection.shang;smallcircle.y=smallcircle.y-fantanjuli;break;default:break;}break;}default:{break;}}}//小球随机反向 randomback()function smallcircledirection(){switch (smallcircle.direction){//根据小球方向做移动case gamedirection.shang:{smallcircle.y=smallcircle.y-gamespeed;grade++;if(grade>maxgrade){ maxgrade=grade; newrecoder(); }addone();break;}case gamedirection.xia:{smallcircle.y=smallcircle.y+gamespeed;grade++;if(grade>maxgrade){ maxgrade=grade; newrecoder(); }addone();break;}case gamedirection.zuo:{smallcircle.x=smallcircle.x-gamespeed;grade++;if(grade>maxgrade){ maxgrade=grade; newrecoder(); }addone();break;}case gamedirection.you:{smallcircle.x=smallcircle.x+gamespeed;grade++;if(grade>maxgrade){ maxgrade=grade; newrecoder(); }addone();break;}case gamedirection.zuoshang:{smallcircle.x=smallcircle.x-gamespeed*0.8;smallcircle.y=smallcircle.y-gamespeed*0.8;grade++;if(grade>maxgrade){ maxgrade=grade; newrecoder(); }addone();break;}case gamedirection.zuoxia:{smallcircle.x=smallcircle.x-gamespeed*0.8;smallcircle.y=smallcircle.y+gamespeed*0.8;grade++;if(grade>maxgrade){ maxgrade=grade; newrecoder(); }addone();break;}case gamedirection.youshang:{smallcircle.x=smallcircle.x+gamespeed*0.8;smallcircle.y=smallcircle.y-gamespeed*0.8;grade++;if(grade>maxgrade){ maxgrade=grade; newrecoder(); }addone();break;}case gamedirection.youxia:{smallcircle.x=smallcircle.x+gamespeed*0.8;smallcircle.y=smallcircle.y+gamespeed*0.8;grade++;if(grade>maxgrade){ maxgrade=grade; newrecoder(); }addone();break;}default:{break;}}}//小球移动 smallcircledirection()/*画出底部圆*/ctxpane.beginPath();//大圆ctxpane.arc(bigcircle.x,bigcircle.y,bigcircle.r,0,Math.PI*2,true);ctxpane.fillStyle = bigcircle.c;ctxpane.fill();ctxpane.closePath();/*画出底部追踪线条*/ctxpane.beginPath();ctxpane.lineWidth=6;ctxpane.strokeStyle = line.c;ctxpane.arc(line.x, line.y, line.r, line.start, line.end,false); ctxpane.stroke(); ctxpane.closePath();function tapme()//tapme{ctxpane.beginPath();ctxpane.strokeStyle="rgb(255,222,195)";ctxpane.font = "80px Papyrus";ctxpane.strokeText('TAP',-95,30);ctxpane.fillStyle="rgb(255,205,105)";ctxpane.font = "35px Papyrus";ctxpane.fillText('me',70,30);ctxpane.closePath();}function newrecoder() {ctxpane.beginPath();ctxpane.fillStyle="rgb(255,0,0)";ctxpane.font = "18px Papyrus";ctxpane.fillText("New!",58,80);ctxpane.closePath();} function addone(){grade1=(grade/150).toFixed(1);grade2=(maxgrade/150).toFixed(1);var say1="now";var say2="best"ctxpane.beginPath();ctxpane.strokeStyle="rgb(250,222,185)";ctxpane.font = "60px Papyrus";ctxpane.strokeText(grade1,-45,-60);ctxpane.strokeText(grade2,-45,100);ctxpane.fillStyle="rgb(255,0,100)";ctxpane.font = "15px Papyrus";ctxpane.fillText(say1,58,-60);ctxpane.fillStyle="rgb(255,0,100)";ctxpane.font = "15px Papyrus";ctxpane.fillText(say2,58,100);ctxpane.closePath();}function movetest(){if(ifgameover()){ ifingame=0; if(maxgrade>parseInt(getCookie2('mymaxgrade'))){setCookie('nickname',nickname,'mymaxgrade',maxgrade.toString(),365);}clearInterval(timer);tapme();}else{if(ifcrash()){randomback();}ctxpane.clearRect(-150,-150,300,300);//清屏ctxpane.beginPath();//大圆ctxpane.arc(bigcircle.x,bigcircle.y,bigcircle.r,0,Math.PI*2,true);ctxpane.fillStyle = bigcircle.c;ctxpane.fill();ctxpane.closePath();if(line.direction==gamedirection.clock) //跟踪线顺时针{line.start=line.start + linespeed;line.end=line.end +linespeed;ctxpane.beginPath();ctxpane.lineWidth=4;ctxpane.strokeStyle = line.c;ctxpane.arc(line.x, line.y, line.r, line.start, line.end,false); ctxpane.stroke(); ctxpane.closePath();}if(line.direction==gamedirection.anticlock)//跟踪逆顺时针{line.start=line.start - linespeed;line.end=line.end -linespeed;ctxpane.beginPath();ctxpane.lineWidth=4;ctxpane.strokeStyle = line.c;ctxpane.arc(line.x, line.y, line.r, line.start, line.end,false); ctxpane.stroke(); ctxpane.closePath();}dot.x=bigcircle.r*Math.cos(line.start+Math.PI/32)//跟踪点dot.y=bigcircle.r*Math.sin(line.start+Math.PI/32)ctxpane.beginPath();//线上跟踪点ctxpane.arc(dot.x,dot.y,dot.r,0,Math.PI*2,true);ctxpane.fillStyle = smallcircle.c;ctxpane.fill();ctxpane.closePath();smallcircledirection();//小圆ctxpane.save();ctxpane.beginPath();ctxpane.arc(smallcircle.x,smallcircle.y,smallcircle.r,0,Math.PI*2,true);ctxpane.fillStyle = smallcircle.c;ctxpane.fill();ctxpane.closePath();ctxpane.restore();}}//主函数 ///////////////////////////////////////////tapme();var timer;function startgame(){//开始游戏 if(ifingame==0) { ifingame=1; grade=0; var xx=Math.floor(Math.random()*8); /* switch(xx) { case 0:smallcircle.direction=gamedirection.shang;break;case 1:smallcircle.direction=gamedirection.xia;break;case 2:smallcircle.direction=gamedirection.zuo;break;case 3:smallcircle.direction=gamedirection.you;break;case 4:smallcircle.direction=gamedirection.zuoshang;break;case 5:smallcircle.direction=gamedirection.zuoxia;break;case 6:smallcircle.direction=gamedirection.youshang;break;case 7:smallcircle.direction=gamedirection.youxia;break;default:break; }*/ smallcircle.direction=gamedirection.xia;smallcircle.x=smallcircle.y=0;line.start=Math.PI/2-Math.PI/26;line.end=Math.PI/2+Math.PI/26;line.direction=gamedirection.anticlock;clearInterval(timer);timer=setInterval(movetest,10); }}//开始游戏 startgame() function opentop() { window.location="http://pongotop.sinaapp.com"; }
10.写在最后
这纯属又是一个自娱自乐,写完后的第三天因为开始忙着投简历找实习就没空再管,扔到朋友圈让朋友玩去了。这一个月过去了再重新看这游戏,感觉它不该就这样死掉,本人没什么技术,做得很拙略,因此发出这篇文字希望能帮到一些对pongo感兴趣的朋友,再者就是希望如果有这方面的高手看到了能够给予赐教,一切疑惑和赐教都欢迎给我留言,谢谢!
注:如有转载,标明出处地址及本人署名ChenReason即可,谢谢。
- Pongo网页版JavaScript源代码及设计思路
- 网页自适应设计思路
- javascript查看网页源代码
- SameTree解法思路及源代码
- 无障碍网页设计思路
- 关于网页设计的思路
- 网页设计~登陆页面源代码
- javascript开发植物大战僵尸网页版游戏源代码下载
- javascript实现html网页版的2048游戏源代码
- Max Subarray思路解析及源代码
- 面试题目思路及设计
- sina网页新闻小偷原理及源代码(java版)
- sina网页新闻小偷原理及源代码(java版) .
- 利弊的JavaScript网页设计
- python3爬虫--网页源代码及图片提取
- 项目设计的方案及思路
- HBase数据模型特性及表设计思路
- HBase数据模型特性及表设计思路
- C 调用LUA
- leetode:Palindrome Partitioning II
- LUA 调用C
- 三层浅析及示例分析
- 英语学习-简单词汇翻译
- Pongo网页版JavaScript源代码及设计思路
- 分布式文件系统设计
- hibernte反向工程for eclipse
- 【C++】printf格式控制
- 自定义View自定义属性
- 关于程序工作者的规划与思考
- 用事件表取代时间表
- C++11 新特性之 序列for循环
- SpringMVC 和 Hibernate Validator的结合(初级)- 基于注解后端数据校验