一个简单的demo: ajiegao.sinaapp.com/demo/mm.html
源码:
<!DOCTYPE HTML>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style type="text/css">
html,body{margin:0;padding:0;width:100%;height:100%;overflow:hidden;}
section{position:absolute;top:0;left:0;background:rgba(0,0,0,.3);padding:1em;line-height:1.2;}
i{color:red;font-style:normal;}
h3{position:absolute;top:0;margin:0 0 0 -3.33em;color:#999;text-shadow:0 0 1px #fff}
</style>
<title></title>
</head>
<body>
<canvas></canvas>
<section>
<h1>MM养成</h1>
<p>
名词解释: <em>MM</em>(浅红色的圆,包括两个圆形的组合);<br /><br />
按下鼠标或者触碰屏幕移动<i>MM</i>;<br />
两个<i>MM</i>接触,其中一个消失;<br />
<i>MM</i>剩下一个胜利;<br />
<i>MM</i>不能脱离中间白色范围。
</p>
</section>
<h3>level 1-1</h3>
<script>
var width=window.innerWidth;
var height=window.innerHeight;
var c=document.querySelector('canvas');
var ctx=c.getContext('2d');
var radius=Math.floor(Math.min(width,height)/16);
var maxradius=Math.floor(Math.min(width,height)*9/10)/2;
var balls=[];
var keysDown=false;
var tt;
var level=1;
c.width=width;
c.height=height;
var sb=function(x,y,r,c){
this.x=x;//x
this.y=y;//y
this.r=r;//radius
this.xx=Math.floor(this.r*2/5);//小圆中心到大圆中心的距离
this.xr=Math.floor(this.r/5);//小圆半径
this.c=c;//color
this.m=Math.random()*5+2; //move speed
this.h=this.m*0.01; //旋转speed
this.a=Math.PI*2*(Math.random());//angle random start
this.update=function(){
if(keysDown){
this.x += Math.cos(this.a-Math.PI*3/4)*this.m;
this.y += Math.sin(this.a-Math.PI*3/4)*this.m;
}else{
this.a+=this.h;
}
}
this.draw=function(){
ctx.save();
ctx.translate(this.x,this.y)
ctx.rotate(this.a);
ctx.fillStyle = this.c;
ctx.beginPath();
ctx.arc(0, 0, this.r, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
ctx.fillStyle = this.c;
ctx.beginPath();
ctx.arc(-this.xx, -this.xx, this.xr, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
ctx.restore();
}
}
function creatBalls(n){
var i=0;
outerloop:
while (i<n){
var rdm_j=Math.random()*360;
var rdm_r=Math.random()*(maxradius-radius);
var ballx=width/2-Math.cos(rdm_j)*rdm_r;
var bally=height/2-Math.sin(rdm_j)*rdm_r;
var testobj={x:ballx,y:bally,r:radius}
var blen=balls.length;
if(blen!==0){
for(var j=0;j<blen;j++){
if (testhit(testobj,balls[j])) {continue outerloop};
}
}
balls.push(new sb(ballx,bally,radius,'rgba(255,0,0,.33)'));
i++;
}
}
function testhit(v1,v2){
var dx = Math.abs(v1.x-v2.x);
var dy = Math.abs(v1.y-v2.y);
var dl = Math.sqrt(dx*dx+dy*dy);
return (dl<(v1.r+v2.r));
}
function hits(){
/*
var obj = balls;
balls=[];
newouter:
while(obj.length!=0){
var shift = obj.shift();
if(obj.length==0) {
balls.push(shift);
break;
}else{
for(var s=0;s<obj.length;s++){
if(testhit(shift,obj[s])){
break;
}else{
balls.push(shift);
break;
}
}
}
}*/
var newArray=[];
var len=balls.length;
for (var i=0;i<len ;i++){
for(var j=i+1;j<len;j++){
if(testhit(balls[i],balls[j])){
j=++i;
}
}
newArray.push(balls[i]);
}
balls = newArray;
}
function clear(){
ctx.clearRect(0,0,width,height);
ctx.fillStyle='rgba(0,0,0,.1)';
ctx.fillRect(0,0,width,height);
ctx.fillStyle='#fff';
ctx.arc(width/2, height/2, maxradius, 0, Math.PI*2, true);
ctx.fill();
}
function updatelevel(){
level++;
clearInterval(tt);
setTimeout(function(){
document.querySelector('h3').innerHTML='level 1-'+level;
balls=[];
creatBalls(level+1);
tt=setInterval(loop,30);
},555)
}
function loop(){
//clear
clear();
//level
if(balls.length==1){updatelevel();}
//检测是否有MM超出掌控
for(var n=0,nlen=balls.length;n<nlen;n++){
if(!testhit({x:width/2,y:height/2,r:maxradius-radius*2},balls[n])){
clearInterval(tt);
alert('飞走料! ( ̄▽ ̄)~* ');
location.reload()
}
}
//测试碰撞
hits();
//画MM
for(var x=0,xlen=balls.length;x<xlen;x++){
balls[x].update();
balls[x].draw();
}
}
window.onload=init;
function init(){
creatBalls(level+1);
tt=setInterval(loop,30);
addEventListener("mousedown", function (e) {
keysDown = true;
setui();
}, false);
addEventListener("touchstart", function (e) {
keysDown = true;setui();
}, false);
addEventListener("mouseup", function (e) {
keysDown = false;
}, false);
addEventListener("touchend", function (e) {
keysDown = false;
}, false);
addEventListener("resize", function (e) {
location.reload();
}, false);
}
function setui(){
document.querySelector('section').style.display='none';
document.querySelector('h3').style.left=width/2+'px';
}
</script>
</body>
</html>
思路:
游戏为了养成一个强壮的MM;
每关只有一个MM坚持到最后,她会吞噬掉其他的MM;
关数越多,MM越多,难度越大;
代码非常简单,稍懂点js的就看懂了,关键还是游戏思路,我这个游戏的亮点就是:每个MM的移动方向随时在变,并且方向改变的速度和移动速度也不是单一不变;因此越到后面难度几何增加。哈哈