ycc-engine
Version:
Mini and powerful canvas engine for creating App or Game.
427 lines (331 loc) • 10.3 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name=viewport content="width=device-width,initial-scale=1,user-scalable=0,viewport-fit=cover">
<title>游戏-别踩白块</title>
<link rel="stylesheet" href="../style.css">
<style>
body{
font-size: 0;
position: relative;
}
</style>
</head>
<body>
<div class="score">分数: <span id="score-number">0</span></div>
</body>
</html>
<script src="../common.js"></script>
<script src="../../build/ycc.js"></script>
<script>
if(!Ycc.utils.isMobile())
alert("此示例在移动端查看效果更佳!");
var canvas = document.createElement('canvas');
console.log(document.documentElement.clientWidth,document.documentElement.clientHeight);
canvas.width=document.documentElement.clientWidth;
canvas.height=document.documentElement.clientHeight;
document.body.appendChild(canvas);
var ycc = new Ycc().bindCanvas(canvas);
var stageW = ycc.getStageWidth();
var stageH = ycc.getStageHeight();
// 所有的图片资源
var images = null;
// 所有音频资源
var audio = null;
// 当前场景
var currentScene = null;
// 帧率
var frameRate = 60;
// 加载资源
ycc.loader.loadResOneByOne([
{name:"start",url:"./images/start.png"},
{name:"restart",url:"./images/restart.png"},
],function (lise,imgs) {
console.log(imgs,222);
images = imgs;
ycc.loader.loadResOneByOne([
{name:'bg',url:"./audio/bg.mp3",type:"audio"},
{name:'over',url:"./audio/over.wav",type:'audio'},
{name:'tap',url:"./audio/tap.mp3",type:'audio'},
],function (audios) {
audio=audios;
currentScene = new StartScene();
ycc.layerManager.reRenderAllLayerToStage();
});
});
// 开启动画,每帧都更新场景
ycc.ticker.start(frameRate);
ycc.ticker.addFrameListener(function () {
currentScene && currentScene.update && currentScene.update();
ycc.layerManager.reRenderAllLayerToStage();
});
function StartScene(){
var self = this;
this.layer = ycc.layerManager.newLayer({enableEventManager:true});
this.layer.addUI(new Ycc.UI.Image({
rect:new Ycc.Math.Rect(stageW/2-200/2,stageH/2-60/2,200,60),
fillMode:"scale",
res:images.start,
ontap:function (e) {
self.delSelf();
ycc.layerManager.deleteAllLayer();
currentScene = new GameScene();
}
}));
}
/**
* 删除自身
*/
StartScene.prototype.delSelf = function () {
ycc.layerManager.deleteLayer(this.layer);
};
function GameScene(){
// 游戏进行中的图层
this.layer = ycc.layerManager.newLayer({enableEventManager:true});
// 游戏结束后的弹出层
this.overLayer = ycc.layerManager.newLayer({enableEventManager:true,show:false});
// 四列
this.col = 4;
// 五行
this.row = 3;
// y轴总的偏移量
this.offsetY = 0;
// 每帧Y轴的步长
this.spaceY = 5;
// 最大速度
this.maxSpaceY = 20;
// 方框宽度
this.rectW = parseInt(stageW/this.col);
// 方框高度
this.rectH = parseInt(stageH/this.row);
// 初始时所有方块可能的y值
this.rectYList = [];
// 已偏移的方块个数
this.offsetNumber=-1;
this.colLines = [];
this.rowLines = [];
this.rects = [];
// 当前得分
this.score = 0;
this.scoreText=null;
// 最终得分的文本UI
this.finalScoreText=null;
// 根据最终得分显示对应的提示文本
this.finalTipText = null;
// 游戏是否结束
this.end = false;
this.bgm = ycc.loader.getResByName('bg',audio);
this.gameOverBgm = ycc.loader.getResByName('over',audio);
this.bgmTap = ycc.loader.getResByName('tap',audio);
this.createRect();
this.createColLine();
this.createRowLine();
this.createTextScore();
this.createGameOverLayer();
console.log('play');
if(this.bgm) {
this.bgm.res.loop = true;
this.bgm.res.play();
}
}
// 添加竖线
GameScene.prototype.createColLine = function () {
for(var i=0;i<this.col;i++){
var x = (this.rectW*i);
var line = new Ycc.UI.Line({
color:'white',
start:new Ycc.Math.Dot(x,0),
end:new Ycc.Math.Dot(x,stageH)
});
this.colLines.push(line);
this.layer.addUI(line);
}
};
// 画横线
GameScene.prototype.createRowLine = function () {
for(var i=-2;i<this.row+2;i++){
var y = (this.rectH*i);
var line = new Ycc.UI.Line({
color:'white',
start:new Ycc.Math.Dot(0,y),
end:new Ycc.Math.Dot(stageW,y)
});
this.rowLines.push(line);
this.layer.addUI(line);
}
};
// 创建方块
GameScene.prototype.createRect = function () {
var self = this;
for(var i=-2;i<this.row+1;i++){
for(var j=0;j<this.col;j++){
var x = (this.rectW*j);
var y = (this.rectH*i);
if(this.rectYList.indexOf(y)===-1)
this.rectYList.push(y);
var rect = new Ycc.UI.Rect({
rect:new Ycc.Math.Rect(x,y,this.rectW,this.rectH),
color:'black',
ontap:function (e) {
self.rectOnTap(e);
}
});
this.rects.push(rect);
this.layer.addUI(rect);
}
}
};
// 创建计分文本
GameScene.prototype.createTextScore = function(){
this.scoreText = new Ycc.UI.SingleLineText({
rect:new Ycc.Math.Rect(0,10,stageW,50),
xAlign:"center",
content:"SCORE: "+this.score +" "+"SPEED:"+this.spaceY,
fontSize:"16px",
color:"green"
});
this.layer.addUI(this.scoreText);
};
// 创建游戏结束的图层页
GameScene.prototype.createGameOverLayer = function(){
// 半透明背景
this.overLayer.addUI(new Ycc.UI.Rect({
rect:new Ycc.Math.Rect(0,0,stageW,stageH),
color:"rgba(0,0,0,0.7)"
}));
var fontSize = "20px";
var lineHeight = 30;
this.overLayer.addUI(new Ycc.UI.SingleLineText({
content:"游戏结束",
xAlign:"center",
rect:new Ycc.Math.Rect(0,stageH/2+lineHeight*-2,stageW,lineHeight),
color:"red",
fontSize:fontSize
}));
this.finalScoreText = new Ycc.UI.SingleLineText({
content:"您最终得了"+this.score+"分",
xAlign:"center",
rect:new Ycc.Math.Rect(0,stageH/2+lineHeight*-1,stageW,lineHeight),
color:"red",
fontSize:fontSize
})
this.overLayer.addUI(this.finalScoreText);
this.finalTipText = new Ycc.UI.SingleLineText({
content:"手速超过了99%的单身狗!",
xAlign:"center",
rect:new Ycc.Math.Rect(0,stageH/2,stageW,lineHeight),
color:"red",
fontSize:fontSize
});
this.overLayer.addUI(this.finalTipText);
var imgW = 200,
imgH = 60;
this.overLayer.addUI(new Ycc.UI.Image({
rect:new Ycc.Math.Rect(stageW/2-imgW/2,stageH/2+lineHeight,imgW,imgH),
fillMode:"scale",
res:images.restart,
ontap:function (e) {
//self.delSelf();
ycc.layerManager.deleteAllLayer();
currentScene = new GameScene();
}
}));
this.overLayer.addUI(new Ycc.UI.SingleLineText({
content:"项目地址",
rect:new Ycc.Math.Rect(stageW/2-10,stageH/2+lineHeight+10+imgH,-14*4,20),
color:"#308eef",
fontSize:"14px",
ontap:function (e) {
window.location.href="https://github.com/lizhiqianduan/ycc/tree/develop";
}
}));
this.overLayer.addUI(new Ycc.UI.SingleLineText({
content:"作者博客",
rect:new Ycc.Math.Rect((stageW)/2+10,stageH/2+lineHeight+10+imgH,14*4,20),
color:"#308eef",
fontSize:"14px",
ontap:function (e) {
window.location.href="http://www.lizhiqianduan.com/blog";
}
}));
};
// 每个方块的点击事件
GameScene.prototype.rectOnTap = function (e) {
//console.log(this,e);
if(e.target.color==="white"){
if(this.bgmTap) {
this.bgmTap.res.currentTime=0;
this.bgmTap.res.play();
}
this.score++;
e.target.color="red";
// 修改分数的文字
this.scoreText.content = "SCORE:"+(" ".slice(0,4-(this.score+'').length))+this.score+" "+"SPEED:"+this.spaceY
}
};
GameScene.prototype.update = function () {
if(this.end) return;
var i=0,j=0;
// 根据时间差计算而得的实际Y轴速度
var spaceY = parseInt(this.spaceY*((Date.now()-ycc.ticker.lastFrameTime)/(1000/frameRate)));
// 如果spaceY超出了最大值的2倍,视为程序被置后台,此帧不更新视图
// if(spaceY>=this.space*3){
// console.log('丢弃帧 spaceY::',spaceY);
// return;
// }
this.offsetY+=spaceY;
if(this.offsetNumber!==parseInt(this.offsetY/this.rectH)){
this.offsetNumber=parseInt(this.offsetY/(this.rectH));
console.log('偏移个数-->',this.offsetNumber);
// 每3行速度就增加1个像素
if(this.offsetNumber%3===2 && this.spaceY<this.rectH-20 && this.spaceY<this.maxSpaceY)
this.spaceY+=1;
// 所有横线减去一个方块的偏移量
for(j=0;j<this.rowLines.length;j++){
this.rowLines[j].start.y-=this.rectH;
this.rowLines[j].end.y-=this.rectH;
}
// 方块的总行数
var rectRow = this.rects.length/this.col;
var rowIndex=rectRow-(this.offsetNumber)%rectRow-1;
// 将最末一行方块的坐标更改至最上方,并随机修改其颜色
for(i=0;i<this.col;i++){
var rect = this.rects[(rowIndex)*this.col+i];
// 存在未点击的白块,游戏结束
if(rect.color==="white") {
this.overLayer.show = true;
this.finalScoreText.content = "您最终得了"+this.score+"分";
if(this.score<50)
this.finalTipText.content = "太菜了,还需努力哦!";
else if(this.score<100)
this.finalTipText.content = "哎哟,不错哟!";
else if(this.score<200)
this.finalTipText.content = "手速超过了99%的单身狗!";
else
this.finalTipText.content = "您的手速已超神!";
if(this.bgm) {
this.bgm.res.currentTime = 0;
this.bgm.res.pause();
}
if(this.gameOverBgm) this.gameOverBgm.res.play();
this.end=true;
break;
}
var before = rect.rect.y;
rect.rect.y = before-(rectRow)*this.rectH;
rect.color=Math.random()>0.2?"black":"white";
// console.log('方块的总行数-->',rectRow,'需要变化的行下标-->',rowIndex,'更改前的y-->',before,'更改后的y-->',rect.y);
}
}
for(i=0;i<this.rects.length;i++){
this.rects[i].rect.y+=spaceY;
}
for(j=0;j<this.rowLines.length;j++){
this.rowLines[j].start.y+=spaceY;
this.rowLines[j].end.y+=spaceY;
}
// 修改分数的文字
this.scoreText.content = "SCORE:"+(" ".slice(0,4-(this.score+'').length))+this.score+" "+"SPEED:"+this.spaceY
};
</script>