您的位置:首页 > Web前端 > JavaScript

Canvas 类库ZRender开发的接水果的小游戏

2018-01-11 20:34 447 查看
        最近使用了轻量级的 Canvas 类库 ZRender开发了一些自定义图件,所以想试试用zrender开发小游戏怎么样,自己也没什么经验,所以写着玩吧,可能有些逻辑部分写的不是很好。。这个小游戏很简单,内容为用篮子接水果,接到苹果10分,橘子5分,菠萝15分,草莓30分,通过键盘的左右按键控制篮子左右移动,最后得分为累计接到的水果得分。

一:

首先我们需要一些水果的小图标,那么在图标网站上面去下载一些图标。这里下载了苹果、菠萝、橘子、草莓的图标。

当然如果要用篮子接水果的话,我们还需要下载一个篮子的图标。这里下载的图标都是png格式的,一般是用到它的透明背景特点








二:


添加如下标签布局,设置myimg部分display:none 目的是在window.onload的时候,能够确保这些图标都加载完毕,同时放置一个div用于zrender初始化。

<div>
<div id="myimg" style="display:none">
<img src="images/apple.png"/>
<img src="images/orange.png"/>
<img src="images/pineapple.png"/>
<img src="images/strawberry.png"/>
<img src="images/basket.png"/>
</div>
<div class="example-container" style="width:500px;height:600px;border:1px solid black;margin:0 auto"></div>
</div>

   zrender初始化
   var container=document.getElementsByClassName('example-container')[0];

   var zr = zrender.init(container);

三:

这里向zrender中添加了四个group,zrBGGroup用于添加背景元素,zrGroup用于放置水果,bottomGroup用于放置篮子,effectGroup用于放置加分的效果。设置group的position,方便后面元素定位。

this.zrBGGroup=new zrender.Group();
this.zrBGGroup.position=[0,0];
this.zr.add(this.zrBGGroup);

this.zrGroup=new zrender.Group();
this.zrGroup.position=[0,40];
this.zr.add(this.zrGroup);

this.bottomGroup=new zrender.Group();
this.bottomGroup.position=[0,this.h-40];
this.zr.add(this.bottomGroup);

this.effectGroup=new zrender.Group();
this.effectGroup.position=[0,0];
this.zr.add(this.effectGroup


四:

 把背景部分都添加进去,这里背景用到了一个RadialGradient蓝紫渐变色。同时添加了得分是个zrender.Text对象,篮子是个zrender.Image对象。因为要监听键盘的按键,这里监听keydown一个事件如果keyCode等于39,说明按下了这个键->,将篮子向右移动。如果keyCode等于37,按下了<-这个键,将篮子向左移动。注意要限定移动的范围。

//绑定事件
bindEvent:function(){
var self=this;
var w=this.w;

window.addEventListener("keydown", function (e) {
var basket=self.basket;
var x=basket.position[0];
if(e.keyCode==39)   //按下了这个键->
{
if((x+20)<=w-50)
{
basket.attr({
position:[x+20,0]
});
}
}
else if(e.keyCode==37) //按下了<-这个键
{
if((x-20)>=-50)
{
basket.attr({
position:[x-20,0]
});
}
}

}, false);
},


五:

 水果要掉下来状态也需要更新,我们这里用setInterval,每0.1秒更新一次状态。同时要检测是否有水果掉到了篮子里面。因为掉水果和检测水果是在同一个Interval逻辑,不一定每次都会落水果。所以这里在0~100里面的随机数里面,只有随机到0~8时才会掉落水果。这里有一个技巧,因为草莓的分值比较高,所以掉落草莓的概率设置的最小,只有随机到0的时候掉落草莓。每次遍zrGroup的子元素,检测水果是否在篮子的范围,在这个范围则移除改元素,同时加上对应的分值。

//更新效果
updateState:function(){
var self=this;
var w=this.w;
var score=this.score;

this.myinter=setInterval(function(){
var zrGroup=self.zrGroup;
var basket=self.basket;
var random=Math.floor(Math.random()*100); //控制数量
var speed=120-random;
//pos 的范围是-50 ~w-50
var pos=Math.random()*w-50;
switch(random)
{
case 0: //丢草莓
self.throwFruit('strawberry',pos,speed);
break;
case 1:
case 2: //丢苹果
self.throwFruit('apple',pos,speed);
break;
case 3:
case 4: //丢菠萝
self.throwFruit('pineapple',pos,speed);
break;
case 5:
case 6:
case 7:
case 8://丢橘子
self.throwFruit('orange',pos,speed);
break;
}
//检测及更新显示
var basketX=basket.position[0];
zrGroup.eachChild(function(item){
var x=item.position[0];
var y=item.position[1];
//大致的判断范围
if(y>w-35&& x>basketX-15&&x<(basketX+100-15))
{
var type=item.fType;
var winScore=rule[type];
//加分
var scoreNOW=Number(score.style.text)+winScore;
self.scoreEffect(winScore);
score.attr({
style: {
text:scoreNOW
}
});
zrGroup.remove(item);
}
});
},100);
}
六:
最后讲一下水果是如何掉落的吧,用到了zrender的animateTo,设置其position和持续时间。这里传递了三个参数,第一个type表示是那种类型的水果。第二个pos表示水果的x轴坐标,第三个speed水果表示美秒钟移动的像素值。同时这里选用了几种类型的缓动效果,如下图所示。

//丢水果
throwFruit:function(type,pos,speed){
var easeType=['linear','quadraticIn','quadraticOut','cubicIn','cubicOut','linear'];

e3d8
var easing=easeType[Math.floor(Math.random()*5)];
var zrGroup=this.zrGroup;
var h=this.h;
var dur=(h-40)/speed*1000;
var baseStyle=this.fruitStyle;
baseStyle.style.image='images/'+type+'.png';
baseStyle.position=[pos,0];

var onefruit=new zrender.Image(baseStyle);
onefruit.fType=type;
zrGroup.add(onefruit);

onefruit.animateTo({
position: [pos,h-40],
rotation: Math.PI *2
}, dur, 0, easing,function(){
//结束之后要移除该元素
zrGroup.remove(onefruit);
});
},


七:最终效果





整体代码:

<!--created by chencen -->
<!--on 2018/1/11-->
<!--blog cc-fys-->

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>catch fruit</title>
<script type="text/javascript" src="zrender.js"></script>
</head>
<div> <div id="myimg" style="display:none"> <img src="images/apple.png"/> <img src="images/orange.png"/> <img src="images/pineapple.png"/> <img src="images/strawberry.png"/> <img src="images/basket.png"/> </div> <div class="example-container" style="width:500px;height:600px;border:1px solid black;margin:0 auto"></div> </div>
<body>
<script>
window.onload=function() //初始化
{
//为了保证图片加载完成
var container=document.getElementsByClassName('example-container')[0];
new CatchFruit(container);
};

//分数规则
var rule={
apple:10,
orange:5,
pineapple:15,
strawberry:30
};

function CatchFruit(elememt){
this.element=elememt;
this.zr = zrender.init(this.element);
this.w= this.zr.getWidth();
this.h = this.zr.getHeight();

this.keydown={};
this.fruitStyle={
style: {
width:35,
height:35,
x:0,
y:0
}
};
this.zrBGGroup=new zrender.Group();
this.zrBGGroup.position=[0,0];
this.zr.add(this.zrBGGroup);

this.zrGroup=new zrender.Group();
this.zrGroup.position=[0,40];
this.zr.add(this.zrGroup);

this.bottomGroup=new zrender.Group();
this.bottomGroup.position=[0,this.h-40];
this.zr.add(this.bottomGroup);

this.effectGroup=new zrender.Group();
this.effectGroup.position=[0,0];
this.zr.add(this.effectGroup);

this.init();
}
CatchFruit.prototype={
constructor: CatchFruit,
//初始化
init: function () {
var self=this;
//画背景
self.drawBG();
//绑定事件
self.bindEvent();
//更新状态
self.updateState();

},

//画背景
drawBG:function() {
var zrBGGroup=this.zrBGGroup;
var bottomGroup=this.bottomGroup;
var w=this.w;
var h=this.h;
var bg = new zrender.Rect({
shape: {
width: w,
height: h
},
style: {
fill: new zrender.RadialGradient(0.5, -0.1, 1, [
{
offset: 0,
color: '#37B0FF'
},
{
offset: 1,
color: '#efe3ff'
}
])
}
});
zrBGGroup.add(bg);
zrBGGroup.add(new zrender.Rect({
shape: {
width: w,
height: 40
},
style: {
fill:'#33292f'
}
}));
zrBGGroup.add(new zrender.Rect({
shape: {
width: w,
height: 40
},
style: {
fill:'#33292f'
}
}));
zrBGGroup.add(new zrender.Text({
style: {
text:'得分:',
fontSize: '18',
textFill: '#fff'
},
position: [20, 10]
}));
this.score=new zrender.Text({
style: {
text:'0',
fontSize: '18',
textFill: '#fff'
},
position: [70, 10]
});
zrBGGroup.add(this.score);

//篮子
this.basket=new zrender.Image({
style: {
image:'images/basket.png',
width:100,
height:40
},
position:[w/2-50,0]
});
bottomGroup.add(this.basket);

},

//更新效果
updateState:function(){
var self=this;
var w=this.w;
var score=this.score;

this.myinter=setInterval(function(){
var zrGroup=self.zrGroup;
var basket=self.basket;
var random=Math.floor(Math.random()*100); //控制数量
var speed=120-random;
//pos 的范围是-50 ~w-50
var pos=Math.random()*w-50;
switch(random)
{
case 0: //丢草莓
self.throwFruit('strawberry',pos,speed);
break;
case 1:
case 2: //丢苹果
self.throwFruit('apple',pos,speed);
break;
case 3:
case 4: //丢菠萝
self.throwFruit('pineapple',pos,speed);
break;
case 5:
case 6:
case 7:
case 8://丢橘子
self.throwFruit('orange',pos,speed);
break;
}
//检测及更新显示
var basketX=basket.position[0];
zrGroup.eachChild(function(item){
var x=item.position[0];
var y=item.position[1];
//大致的判断范围
if(y>w-35&& x>basketX-15&&x<(basketX+100-15))
{
var type=item.fType;
var winScore=rule[type];
//加分
var scoreNOW=Number(score.style.text)+winScore;
self.scoreEffect(winScore);
score.attr({
style: {
text:scoreNOW
}
});
zrGroup.remove(item);
}
});
},100);
},

//丢水果
throwFruit:function(type,pos,speed){
var easeType=['linear','quadraticIn','quadraticOut','cubicIn','cubicOut','linear'];
var easing=easeType[Math.floor(Math.random()*5)];
var zrGroup=this.zrGroup;
var h=this.h;
var dur=(h-40)/speed*1000;
var baseStyle=this.fruitStyle;
baseStyle.style.image='images/'+type+'.png';
baseStyle.position=[pos,0];

var onefruit=new zrender.Image(baseStyle);
onefruit.fType=type;
zrGroup.add(onefruit);

onefruit.animateTo({
position: [pos,h-40],
rotation: Math.PI *2
}, dur, 0, easing,function(){
//结束之后要移除该元素
zrGroup.remove(onefruit);
});
},

//加分效果
scoreEffect:function(winScore){
var w=this.w;
var h=this.h;
var effectGroup=this.effectGroup;
var addCore=new zrender.Text({
style: {
text:'+ '+winScore,
fontSize: '25',
textFill: '#ff5140',
textAlign: 'center'
},
position: [w/2, h/2]
});
effectGroup.add(addCore);
addCore.animateTo({
style: {
opacity:0
},
position: [10, 10]
}, 1000, 0, 'linear', function () {
effectGroup.remove(addCore);
});
},

//绑定事件
bindEvent:function(){
var self=this;
var w=this.w;

window.addEventListener("keydown", function (e) {
var basket=self.basket;
var x=basket.position[0];
if(e.keyCode==39) //按下了这个键->
{
if((x+20)<=w-50)
{
basket.attr({
position:[x+20,0]
});
}
}
else if(e.keyCode==37) //按下了<-这个键
{
if((x-20)>=-50)
{
basket.attr({
position:[x-20,0]
});
}
}

}, false);
},

dispose:function(){
var myinter=this.myinter;
clearInterval(myinter);

this.zrBGGroup.removeAll();
this.zrGroup.removeAll();
this.bottomGroup.removeAll();
this.effectGroup.removeAll();

var zr = this.zr;
zrender.dispose(zr);
}
};

</script>

</body>
</html>

下载链接:
http://download.csdn.net/download/cc_fys/10200928

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息