limej 写一个HTML5的贪吃蛇小游戏

        之前用limejs框架写了一个贪吃蛇的小游戏。现在想迁移到cocos2d-x上。可是一直找不到好的贪吃蛇的移动算法。想想还是用之前js写的笨方法吧,可是才过了个5.1就忘了。还是赶紧回顾一下代码,先把思路记录一下。
这个贪吃蛇移动的方法有几个不理想的地方。
  1. 身体块必须是正方形的。//这样就限制了给蛇渲染图片的限制。
  2. 每次移动必须是一个身体块的大小。
  3. 只能上下左右4个方向移动
  4. 其他
如果有好的方法,欢迎指教。谢谢!
  • 思路
先把我的思路记录一下吧。
  1. 首先是把蛇的身体分成N个正方形的精灵(Sprite),"000000o"精灵个数就是蛇的长度,通过在尾部增加精灵个数来增加蛇的长度。每个精灵是一个实体,在动画帧变化的时候每个精灵都跟着变化。
  2. 蛇运动最复杂的就是转弯的时候。必须考虑到多次转弯的情况。比如下面这种情况:
0000
0     000o
0000
我的思路是,给身体的每一个点都设置一个移动方向,每次运动,后一个点就跟着上一个的移动方向移动,就可以完成上面的效果了。
3. 把蛇身体的精灵大小作为每次移动的举例,比如向上,就Y轴增加一个bodysize。所以要求精灵必须是正方形的。
4. 通过帧率或者多少帧运动一次来控制蛇运动的速度。
  • 代码
直接结合注释,贴上代码吧。
1、 蛇的对象类。snake_playe.js
goog.provide( 'snake.game');

goog.require( 'lime.Sprite');
goog.require( 'lime.fill.LinearGradient');

goog.require( "snake.food");

snake.game = function(level){
lime.Sprite.call( this);
this.foodList = [] ;
this.level = level ;
this.WIDTH = 300 ;
this.HEIGHT = 440 ;
this.nFrame = 10 ; //10帧的运动1次
this.bodyList = [] ; //存放蛇身体块的数组
this.bodySize = 10 ; //蛇身体块的大小
this.length = 5 ; //初始蛇的长度,也就是精灵个数。
this.score = 0 ;

this.setAnchorPoint( 0, 0);
this.setSize( 320, 460);

//设置背景
var back = new lime.fill.LinearGradient().addColorStop( 1, '#FF8000').addColorStop( 1, '#FF8000');
this.setFill(back);

this.scoreLabel = new lime.Label().setText( 'score: 0').setPosition( 30, 5).setFontSize( 12);
this.appendChild( this.scoreLabel);

this.world = new lime.Sprite().setFill( '#FFFFFF').setSize( this.WIDTH, this.HEIGHT).setPosition( 10, 10).setAnchorPoint( 0, 0);
this.appendChild( this.world);

this.start();

}

goog.inherits(snake.game, lime.Sprite);


snake.game.prototype.start = function(){
//初始化蛇的身体
this.initBody();
this.addFood(); //随机生成食物,注意不要和墙壁和蛇重合就可以了。
goog.events.listen( this, 'keydown', this.kdControl); //监听按键事件
lime.scheduleManager.schedule( this.step, this); //祯运动方法
}

snake.game.prototype.addFood = function(){
if( this.foodList.length > 0 ){
for( var i = 0 ; i < this.foodList.length ; i ++){
this.world.removeChild( this.foodList[i]);
}
this.foodList = [];
}
var food = new snake.food();
var fSize = food.getSize();
var rx,ry;
while(true){
rx = Math.round(Math.random() * ( this.WIDTH - food.getSize().width)) ;
rx = Math.round(rx / 10) * 10 ;
ry = Math.round(Math.random() * ( this.HEIGHT - food.getSize().height)) ;
ry = Math.round(ry / 10) * 10 ;
var flag = true ;
for( var i = 0 ; i < this.bodyList.length ; i ++){
var bPos,bSize ;
bPos = this.bodyList[i].getPosition();
bSize = this.bodyList[i].getSize();
if(((rx + fSize.width) > bPos.x) && ( rx < (bPos.x + bSize.width))){
if(((ry + fSize.height) > bPos.y ) &&( ry < (bPos.y + bSize.height))){
flag = false ;
}
}
}
if(flag) {
food.setPosition(rx,ry);
this.foodList.push(food);
this.world.appendChild(food);
return;
}
}
}

var FrameTemp = 0 ;
//控制10帧运动一次,以控制速度。
snake.game.prototype.step = function(){
// var pos = this.player.getPosition(), size = this.world.getSize(),pSize = this.player.getSize();
FrameTemp ++ ;
if(FrameTemp > this.nFrame){
FrameTemp = 0 ;
}
if(FrameTemp == this.nFrame){
//蛇运动
this.snakeRun();
}
}

snake.game.prototype.snakeRun = function(){
var i , pDirection;
var bodyList = this.bodyList;
//遍历每一个点
for(i = 0 ; i < bodyList.length ; i ++){
var bx = bodyList[i].getPosition().x;
var by = bodyList[i].getPosition().y;
//根据当前运动方向控制精灵的运动
if(bodyList[i].m_direction == 'up'){
by -= this.bodySize ;
} else if(bodyList[i].m_direction == 'down'){
by += this.bodySize ;
} else if(bodyList[i].m_direction == 'left'){
bx -= this.bodySize ;
} else if(bodyList[i].m_direction == 'right'){
bx += this.bodySize ;
}
//控制游戏结束,只有i==0,也就头撞到墙才会游戏结束。
if(i == 0 && this.endRule()) {
this.endGame();
return;
}
bodyList[i].setPosition(bx,by);
//改变每一个节点的运动方向,即运动完之后,自己运动方向向后传递。
if(bodyList[i]._type == "header"){
pDirection = bodyList[i].m_direction;
} else{
_tempDir = pDirection;
//bodyList[i].p_direction = bodyList[i].m_direction ;
pDirection = bodyList[i].m_direction;
bodyList[i].m_direction = _tempDir;
}
}
//食物碰撞检验
this.searchFood();
}

snake.game.prototype.searchFood = function(){
var hBlock = this.bodyList[ 0];
var hPos = hBlock.getPosition();
var hSize = hBlock.getSize();
var food = this.foodList[ 0];
var fPos ,fSize , food ;
if( this.foodList.length > 0 ){
food = this.foodList[ 0] ;
fPos = food.getPosition();
fSize = food.getSize();
// console.log("hPos.x :" + hPos.x + " y:" + hPos.y);
// console.log("fPos.x :" + fPos.x + " y:" + fPos.y);
if(((hPos.x + hSize.width) > fPos.x) && (hPos.x < fPos.x + fSize.width) && ((hPos.y + hSize.height) > fPos.y) && (hPos.y < fPos.y +fSize.height)){
this.world.removeChild(food);
this.foodList.splice( 0, 1);
this.addBlock();
this.addFood();
this.score ++;
this.scoreLabel.setText( "score : " + this.score);
}
}
}

snake.game.prototype.kdControl = function(e){
var direction ;
if(e.event.keyCode == 37){ //左
direction = "left" ;
} else if(e.event.keyCode == 38){ //上
direction = "up" ;
} else if(e.event.keyCode == 39){ //右
direction = "right" ;
} else if(e.event.keyCode == 40){ //下
direction = "down" ;
}
this.bodyList[ 0].m_direction = direction ; //改变头的方向

this.snakeRun();
};

//在尾部增加一个身体块
snake.game.prototype.addBlock = function(){
var tBlock = this.bodyList[ this.bodyList.length - 1] ;
var tDirection = tBlock.m_direction;
var tPos = tBlock.getPosition();

var front_color = '#AACDEF';
var back_color = '#AACDEF';
var grad = new lime.fill.LinearGradient().
addColorStop( 0, back_color).
addColorStop( 1, front_color);

var bodyBlock = new lime.RoundedRect().setSize( this.bodySize, this.bodySize).setFill(grad).setAnchorPoint( 0, 0);
if(tDirection == "up"){
bodyBlock.setPosition(tPos.x ,tPos.y + this.bodySize);
} else if(tDirection == "down"){
bodyBlock.setPosition(tPos.x ,tPos.y - this.bodySize);
} else if(tDirection == "left"){
bodyBlock.setPosition(tPos.x + this.bodySize ,tPos.y);
} else if(tDirection == "right"){
bodyBlock.setPosition(tPos.x - this.bodySize ,tPos.y);
}
bodyBlock.m_direction = tBlock.m_direction ;
bodyBlock.p_direction = tBlock.m_direction ;
this.world.appendChild(bodyBlock);
this.bodyList.push(bodyBlock);
}

snake.game.prototype.initBody = function(){
//如果游戏开始就存在bodyList , 则清空
if( this.bodyList.length > 0 ){
for( var i = 0 ; i < this.bodyList.length ; i ++){
this.world.removeChild( this.bodyList[i]);
}
this.bodyList = [];
}
var i ;
this.start_direction = "left" ; //开始前进方向
var front_color = '#AACDEF';
var back_color = '#AACDEF';
var grad = new lime.fill.LinearGradient().
addColorStop( 0, back_color).
addColorStop( 1, front_color);
for(i = 0 ; i < this.length ; i ++){
var bodyBlock = new lime.RoundedRect().setSize( this.bodySize, this.bodySize).setFill(grad).setAnchorPoint( 0, 0); //绘制蛇的身体精灵
bodyBlock.setPosition( 250 +i * this.bodySize, 250); //设置初始坐标
if (i == 0){
bodyBlock._type = "header" ; // 设置_type为头
bodyBlock.m_direction = this.start_direction ; //设置当前移动方向
} else if(i == ( this.length - 1)){
bodyBlock._type = "tail";
bodyBlock.m_direction = this.start_direction ;
// bodyBlock.p_direction = this.start_direction ;
} else {
bodyBlock._type = "body" ;
bodyBlock.m_direction = this.start_direction ;
// bodyBlock.p_direction = this.start_direction ;
}

this.bodyList.push(bodyBlock);
this.world.appendChild(bodyBlock);
}
}

snake.game.prototype.endRule = function(){
var hBlock = this.bodyList[ 0];
var hPos = hBlock.getPosition() , hSize = hBlock.getSize();
var hDirection = hBlock.m_direction;
if((hDirection == "up") && ((hPos.y - this.bodySize) < 0 )){
return true ;
} else if( (hDirection == "down") && ((hPos.y + this.bodySize) > = this.HEIGHT ) ){
return true ;
} else if((hDirection == "left") && ((hPos.x - this.bodySize) < 0 )) {
return true ;
} else if((hDirection == "right") && ((hPos.x + this.bodySize) > = this.WIDTH )){
return true ;
}
for( var i = 1 ; i < this.bodyList.length ; i ++){
var bPos,bSize ;
bPos = this.bodyList[i].getPosition();
bSize = this.bodyList[i].getSize();
if(((hPos.x + hSize.width) > bPos.x) && ( hPos.x < (bPos.x + bSize.width))){
if(((hPos.y + hSize.height) > bPos.y ) &&( hPos.y < (bPos.y + bSize.height))){
return true ;
}
}
}
return false;
}

snake.game.prototype.endGame = function(){
lime.scheduleManager.unschedule( this.step, this);

goog.events.unlisten( this, "keydown", this.kdControl);
// this.dispatchEvent("keydown");
this.score = 0 ;

var back = new lime.fill.LinearGradient().addColorStop( 0, 255, 150, 0, . 4)
.addColorStop( 0. 9, 250, 150, 0, . 05).addColorStop( 1, 0, 0, 0, 0);
var notice = new lime.RoundedRect();
notice.setSize( 150, 100).setFill(back).setAnchorPoint(. 5, 0);

var title = new lime.Label().setText( "GAME OVER").setPosition( 0, 20);
notice.appendChild(title);
notice.setPosition( 150 , 250);
this.world.appendChild(notice);

//var show = new lime.animation.FadeTo(1);
goog.events.listen(notice, "click", function() {
notice.setHidden(true);
this.start();
},false, this);
//notice.runAction(show);
}
demo运行查看地址(上下左右键控制方向): http://www.517one.com/demo/snake.html 
源码百度网盘下载地址:http://pan.baidu.com/share/link?shareid=428666&uk=1477240704
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值