/*******************清空上一次内容******************/
$('body')[0].innerHTML=''
+''
+''
+'';
if (timer) window.clearInterval(timer);
/*******************添加canvas**********************/
var width=document.documentElement.clientWidth;//屏幕宽度高度
var height=document.documentElement.clientHeight;
$('body').prepend('');
var canvasEl=$('#canv')[0];
var cv=canvasEl.getContext('2d');
/*******************数学计算函数********************/
var cos=Math.cos, sin=Math.sin, random=Math.random, PI=Math.PI, abs=Math.abs, atan2=Math.atan2, round=Math.round, floor=Math.floor, sqrt=Math.sqrt;
function cube(x)//平方
{
return x*x;
}
function rad(d)//角度-->弧度
{
return d/180*PI;
}
function xy(u)//转极坐标为直角坐标
{
return {x:u.r*cos(u.t), y:u.r*sin(u.t)};
}
function dis2(x1,y1,x2,y2)//距离的平方
{
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
function ran(a,b)//生成[a, b)的随机实数
{
return a+(b-a)*random();
}
function ranInt(a,b)//生成[a, b]的随机整数
{
return floor(a+(b-a+1)*random());
}
function min(a,b)
{
return a>b?b:a;
}
/*******************strings*************************/
var _gamename='ENDLESS SEA';
var _instructions='TUTORIAL';
var _about='ABOUT';
var _startgame='START GAME';
var _pause='PAUSE';
var _continue='CONTINUE';
var _gameover='DREAM AWAKE';
var _scoreis='YOUR SCORE: ';
var _ranking='RANKING';
var _tryagain='TRY AGAIN';
var _top_score='Score: ';
var _top_life='Life: ';
var _top_level='Level: ';
var _life='Life: ';
var _wudi='Superfish';
var _jiansu='Speed Down';
var _qingping='Big Bomb';
var _1up='1 UP';
var _bianxiao='Small World';
/*******************全局变量&常量声明***************/
var mx,my,bg,pl,plSize,cursorSize,ballSize,bigBallSize,bSize,butterflySize,starSize,d1,d2,d3,t1,t2,score,u1,u2,
fps,planeShape,butterflyLine,butterflyShape,diamondShape,Star_6,balls,bigBalls,butterflys,stars,diamonds,waves,ballSpeed,
bigBallSpeed,butterflySpeed,starSpeed,waveSpeed,waveRSpeed,waveWidth,waveMaxR,waveR,waveNum,ballDensity,bigBallDensity,butterflyDensity,starDensity,diamondDensity,ballStyle,instructionsContent,aboutContent,
clock,died,level,judge,startBgColor=ranInt(0,359),bgColorTimer=0,life,wudi,wudiTimer,smallTimer,slowTimer,info,timer,flash,pause,pauseTimes,playNum,scoreArr,gameStarted,slowFactor,smallFactor;
var playNum = 0;//用户玩游戏的总次数
var scoreArr = new Array();//储存玩家得分的数组
var STORAGE_KEYS = {
scores: 'endlessSea.scores'
};
function loadScores()
{
var raw = window.localStorage.getItem(STORAGE_KEYS.scores);
if (!raw) return [];
try
{
var parsed = JSON.parse(raw);
if (!Array.isArray(parsed)) return [];
return parsed.filter(function(item) { return typeof item === 'number' && !isNaN(item); });
}
catch (err)
{
return [];
}
}
function saveScores(scores)
{
window.localStorage.setItem(STORAGE_KEYS.scores, JSON.stringify(scores));
}
function recordScore(totalScore)
{
var scores = loadScores();
scores.push(totalScore);
scores.sort(function(a, b) { return b - a; });
saveScores(scores);
return scores;
}
function getTopScores(limit)
{
var scores = loadScores().sort(function(a, b) { return b - a; });
while (scores.length < limit) scores.push(0);
return scores.slice(0, limit);
}
function renderRanking(scores)
{
var rankContent = '';
for (var i = 0; i < scores.length; i++)
{
rankContent += '
');
$('body').append('');
$('body').append('');
$('body').append('');
layoutPanels();
addHelpInfo();
addAboutInfo();
addRankingInfo();
/*******************各个绘图函数********************/
function hsvToRgb(h,s,v)//hsv转rgb
{
var hi = floor(h/60);
var f = h/60-hi;
var u = floor(255*v);
var p = floor(255*v*(1-s));
var q = floor(255*v*(1-f*s));
var t = floor(255*v*(1-(1-f)*s));
var res=[
{r:u,g:t,b:p},
{r:q,g:u,b:p},
{r:p,g:u,b:t},
{r:p,g:q,b:u},
{r:t,g:p,b:u},
{r:u,g:p,b:q}
];
return res[hi];
}
function drawBG()//画背景
{
if (bgColorTimer%10==0)//变色
{
var b=hsvToRgb((startBgColor+bgColorTimer/10)%360,0.14,0.92);//上方低饱和度颜色
var c=hsvToRgb((startBgColor+bgColorTimer/10)%360,0.57,0.77);//下方高饱和度颜色
bg=cv.createLinearGradient(0,0,0,height);
bg.addColorStop(0,'rgb('+b.r+','+b.g+','+b.b+')');
bg.addColorStop(1,'rgb('+c.r+','+c.g+','+c.b+')');
}
cv.save();
cv.fillStyle=bg;
cv.fillRect(0,0,width,height);
cv.restore();
}
function drawItem(p,x,y,d)//创建(而不是画)任意极坐标表示的多边形,p为极坐标的数组, x&y是该图形的基准位置,d为旋转角度。需在外部指定绘图样式
{
cv.beginPath();
var len=p.length;
cv.moveTo(x+p[0].r*cos(p[0].t+d), y+p[0].r*sin(p[0].t+d));
for (var i=0;iwaveNum) waves.splice(0,1);
}
/*********************位置变化计算&碰撞判定********************/
function ballMove()//根据球的速度,每一帧改变一下各球位置
{
for (var i=balls.length-1;i>=0;i--)
{
balls[i].pos.x+=balls[i].speed*cos(balls[i].degree);
balls[i].pos.y+=balls[i].speed*sin(balls[i].degree);
if (dis2(balls[i].pos.x,balls[i].pos.y,pl.x,pl.y)=0;i--)
{
bigBalls[i].pos.x+=bigBalls[i].speed*cos(bigBalls[i].degree);
bigBalls[i].pos.y+=bigBalls[i].speed*sin(bigBalls[i].degree);
if (dis2(bigBalls[i].pos.x,bigBalls[i].pos.y,pl.x,pl.y)=0;i--)
{
butterflys[i].pos+=butterflys[i].rspeed;
butterflys[i].deg=(butterflys[i].rspeed>0)?(butterflys[i].pos+rad(90)):(butterflys[i].pos-rad(90));
butterflys[i].x=butterflys[i].cx+butterflys[i].r*cos(butterflys[i].pos);
butterflys[i].y=butterflys[i].cy+butterflys[i].r*sin(butterflys[i].pos);
if (dis2(butterflys[i].x,butterflys[i].y,pl.x,pl.y)0&&butterflys[i].y<-50||butterflys[i].rspeed<0&&butterflys[i].y>height+50) butterflys.splice(i,1);
}
}
function starMove()
{
for (var i=stars.length-1;i>=0;i--)
{
stars[i].deg+=stars[i].rspeed;
stars[i].x+=starSpeed*cos(stars[i].aim);
stars[i].y+=starSpeed*sin(stars[i].aim);
if (dis2(stars[i].x,stars[i].y,pl.x,pl.y)=0;i--)
{
diamonds[i].y+=diamonds[i].speed;
if (dis2(diamonds[i].x,diamonds[i].y-15,pl.x,pl.y)height+50) diamonds.splice(i,1);
}
}
function waveMove()
{
for (var i=waves.length-1;i>=0;i--)
{
waves[i].x-=waveSpeed;
waves[i].r+=waveRSpeed;
}
}
function planeMove()
{
var dd=dis2(mx,my,pl.x,pl.y);
pl.ax=(mx-(pl.x+plSize*cos(pl.arc)))-pl.vx/u1;//欠阻尼
pl.ay=(my-(pl.y+plSize*sin(pl.arc)))-pl.vy/u1;
var vv=dis2(pl.vx,pl.vy,0,0);
pl.x+=pl.vx/u2;
pl.y+=pl.vy/u2;
pl.vx+=pl.ax;
pl.vy+=pl.ay;
pl.arc=atan2(100,-(my-(pl.y+plSize*sin(pl.arc))))-PI/2;
}
/*********************设置绘图时钟周期**********************/
function clockStart(){
clearLoop();
gameStarted = true;
timer=setInterval(function() {
if (!pause)
{
drawBG();
drawCursor();
waveMove();
drawWaves();
planeMove();
if (!died) drawPlane();
ballMove();
drawBalls();
bigBallMove();
drawBigBalls();
butterflyMove();
drawButterflys();
starMove();
drawStars();
diamondMove();
drawDiamonds();
if (!died&&(level==1&&clock%25==0||level>1&&clock%20==0)) addWave();//产生与音乐节奏一致的水波
if (random()=1200&&random()6)
{
if (random()=6)
{
if (clock%100==0) addButterfly();
}
if (level==3||level==4||level>=6)
{
if (clock%starDensity==0) addStar();
}
if (!died)
{
cv.save();
var txt=_top_score+(clock+score)+'0 '+_top_life;
for (var i=0;i6?'MAX':level+1);
cv.font="20px Arial";
var u=min(1,dis2(pl.x,pl.y,0,0)/cube(height));
cv.fillStyle='rgba(221,51,85,'+u+')';
cv.fillText(txt,30,30);
cv.restore();
}
clock++;
bgColorTimer++;
if (clock==1800) level++;
if (clock>1800&&clock%1200==600) level++;
if (flash==8||flash==7||flash==2||flash==1) //屏幕闪烁两次
{
cv.save();
cv.fillStyle='rgba(255,255,255,0.5)';
cv.fillRect(0,0,width,height);
cv.restore();
flash--;
}
else if (flash)
{
flash--;
}
}
}, 1000/fps);//fps
}
/*********************事件监听**************************/
document.addEventListener('mousemove',function(e)
{
mx=e.clientX;
my=e.clientY;
});
document.addEventListener('touchstart',function(e)
{
if (!e.touches.length) return;
mx=e.touches[0].clientX;
my=e.touches[0].clientY;
}, {passive:true});
document.addEventListener('touchmove',function(e)
{
if (!e.touches.length) return;
mx=e.touches[0].clientX;
my=e.touches[0].clientY;
}, {passive:true});
document.addEventListener('click',function(e)
{
if (e.target.id=='retry')
retry();
else if (e.target.id=='startbutton')
{
$('#startgame').remove();
$('.title').remove();
$('html').css({cursor:'none'});
clockStart();
$('#music')[0].play();
}
else if (e.target.id=='continue')
{
stopPause();
}
});
document.addEventListener('keydown',startPause);
window.addEventListener('resize', resizeGame);
/*********************帮助&关于信息************************/
bindOverlayHover('#instructions', '#left');
bindOverlayHover('#about', '#right');
function addHelpInfo()
{
$('#left').append(instructionsContent);
}
function addAboutInfo()
{
$('#right').append(aboutContent);
}
function addRankingInfo(t)
{
if (typeof t === 'number')
{
scoreArr = recordScore(t);
}
else
{
scoreArr = loadScores();
}
renderRanking(getTopScores(5));
}
/*********************暂停*********************************/
function startPause(e)
{
if (e.keyCode!=13&&e.keyCode!=32&&e.keyCode!=80)
return;
if (pause)
{
stopPause();
return;
}
if ($('#die').length)
{
retry();
return;
}
if ($('#startgame').length)
{
$('#startgame').remove();
$('html').css({cursor:'none'});
clockStart();
$('#music')[0].play();
$('#left').fadeOut(300);
$('#right').fadeOut(300);
$('.title').remove();
return;
}
if (pauseTimes<0)
return;
$('html').css({cursor:'default'});
pause=true;
pauseTimes--;
$('body').append('
'+_pause+'
'+_instructions+'
'+
'
ABOUT
'+_continue+'
');
layoutPanels();
$('#music')[0].pause();
}
function stopPause()
{
pause=false;
$('html').css({cursor:'none'});
$('#pause').remove();
$('.title').remove();
$('#left').fadeOut(300);
$('#right').fadeOut(300);
$('#music')[0].play();
}
/*********************吃钻石相关***************************/
function eatDiamond(f)
{
if (!died)
{
$('#diamondsound')[0].play();
switch(f)
{
case 0: var s=ranInt(3,6);showInfo('Score +'+s+'000');func_addScore(s);break;
case 1: showInfo(_jiansu);func_slow(2);break;
case 2: showInfo(_1up);func_oneUp();break;
case 3: showInfo(_wudi);func_wudi(6000);break;
case 4: showInfo(_qingping);func_clear();break;
case 5: showInfo(_bianxiao);func_small(2);break;
}
}
}
function showInfo(s)//在小鱼上方显示文字
{
info=s;
var t=clock;
$('body').append('
'+s+'
');
$('#info'+t).css('left',pl.x-100+'px');
$('#info'+t).css('top',pl.y-50+'px');
$('#info'+t).fadeOut(1500);
}
function func_addScore(s)
{
score+=s*100;//对玩家显示加了s千分
}
function func_slow(t)
{
var i;
if (slowFactor !== 1)
{
for (i = 0; i < balls.length; i++) balls[i].speed *= slowFactor;
for (i = 0; i < bigBalls.length; i++) bigBalls[i].speed *= slowFactor;
for (i = 0; i < butterflys.length; i++) butterflys[i].rspeed *= slowFactor;
ballSpeed *= slowFactor;
bigBallSpeed *= slowFactor;
butterflySpeed *= slowFactor;
starSpeed *= slowFactor;
ballDensity *= slowFactor;
bigBallDensity *= slowFactor;
butterflyDensity *= slowFactor;
starDensity /= slowFactor;
waveSpeed *= slowFactor;
window.clearTimeout(slowTimer);
slowFactor = 1;
}
for (i = 0; i < balls.length; i++) balls[i].speed/=t;
for (i = 0; i < bigBalls.length; i++) bigBalls[i].speed/=t;
for (i = 0; i < butterflys.length; i++) butterflys[i].rspeed/=t;
ballSpeed/=t;
bigBallSpeed/=t;
butterflySpeed/=t;
starSpeed/=t;
ballDensity/=t;//密度也要减小,否则满屏幕都是子弹
bigBallDensity/=t;
butterflyDensity/=t;
starDensity*=t;
waveSpeed/=t;//是小球的平均速度
slowFactor = t;
slowTimer=setTimeout(function()
{
for (var resetBall = 0; resetBall < balls.length; resetBall++) balls[resetBall].speed *= slowFactor;
for (var resetBigBall = 0; resetBigBall < bigBalls.length; resetBigBall++) bigBalls[resetBigBall].speed *= slowFactor;
for (var resetButterfly = 0; resetButterfly < butterflys.length; resetButterfly++) butterflys[resetButterfly].rspeed *= slowFactor;
ballSpeed*=slowFactor;
bigBallSpeed*=slowFactor;
butterflySpeed*=slowFactor;
starSpeed*=slowFactor;
ballDensity*=slowFactor;
bigBallDensity*=slowFactor;
butterflyDensity*=slowFactor;
starDensity/=slowFactor;
waveSpeed*=slowFactor;
slowFactor = 1;
},8000);
flash=8;
}
function func_oneUp()
{
life++;
}
function func_wudi(time)
{
if (wudiTimer) window.clearTimeout(wudiTimer);//清除之前无敌的计时器
wudi=true;
wudiTimer=setTimeout(function()
{
wudi=false;
},time);
}
function func_clear()
{
balls=[];
bigBalls=[];
butterflys=[];
stars=[];
flash=8;
}
function func_small(t)
{
var i;
if (smallFactor !== 1)
{
for (i = 0; i < bigBalls.length; i++) bigBalls[i].size*=smallFactor;
bigBallSize*=smallFactor;
bSize*=smallFactor;
butterflySize*=smallFactor;
starSize*=smallFactor;
plSize*=smallFactor;
for (i = 0; i < butterflyShape.length; i++) butterflyShape[i].r*=smallFactor;
rebuildScaledShapes();
rebuildJudge(20);
window.clearTimeout(smallTimer);
smallFactor = 1;
}
for (i = 0; i < bigBalls.length; i++) bigBalls[i].size/=t;
bigBallSize/=t;
bSize/=t;
butterflySize/=t;
starSize/=t;
plSize/=t;
for (i = 0; i < butterflyShape.length; i++) butterflyShape[i].r/=t;
rebuildScaledShapes();
rebuildJudge(15);
smallFactor = t;
smallTimer=setTimeout(function()
{
for (var resetSize = 0; resetSize < bigBalls.length; resetSize++) bigBalls[resetSize].size*=smallFactor;
bigBallSize*=smallFactor;
bSize*=smallFactor;
butterflySize*=smallFactor;
starSize*=smallFactor;
plSize*=smallFactor;
for (var resetShape = 0; resetShape < butterflyShape.length; resetShape++) butterflyShape[resetShape].r*=smallFactor;
rebuildScaledShapes();
rebuildJudge(15);
smallFactor = 1;
},8000);
flash=8;
}
/*********************玩家挂了*****************************/
function kill()
{
if (!wudi&&!died)
{
life--;
showInfo(_life+life);
func_wudi(2500);
$('#killsound')[0].play();
}
if (!life)
{
die();
}
}
function die()
{
if (died) return;
died=true;
clearLoop();
playNum++;
$('html').css({cursor:'default'});
var t=clock+score;
$('body').append('