(新手向教学帖)贪食蛇---js仿面向对象的使用

BeenZ 2009-12-04 10:42:14
最近忙得很少时间上线, 昨天整理代码的时候发现以前学习的时候写的一份贪食蛇.
主要是展示了JS仿面向对象的特性,模拟类的使用,简单的MVC结构.希望对大家有帮助

ps:此代码很简单,没有高深的技巧和复杂的结构, 效果也很粗糙(没时间修改),仅供学习和参考之用,而不是什么XXXX版,有不明白的地方欢迎提出


<html>
<head>
<style>
.unit{
width:20px;
height:20px;
position:absolute;
border:solid 1px black;
}
.backlayer{
width:600px;
height:600px;
border:solid 1px gray;
position:absolute;
margin:0px;
}

</style>
<script language="javascript">
var $$ = function (id) {
return "string" == typeof id ? document.getElementById(id) : id;
};
var INISBODY=10; //身体初始长度
var Global=function(){ //单元格属性
this.WIDTH=30;
this.HEIGHT=30;
this.CELL_SIZE=20;
return this;
}
function fillRect(xpos,ypos,color){
var backlayer=$$("backlayer");
var obj=document.createElement("div");
obj.className="unit";
obj.style.top=600-ypos*(Global().CELL_SIZE);
obj.style.left=xpos*Global().CELL_SIZE;
obj.style.backgroundColor=color;
backlayer.appendChild(obj);
}
function LinkList(){ //模拟链表类
this.x=[];
this.y=[];
}
LinkList.prototype={
removeLast:function(){ //移除尾结点
var x=this.x.pop();
var y=this.y.pop();
return [x,y];
},
addFirst:function(ret){ //增加头结点
var x=[ret[0]];
var y=[ret[1]];
this.x=x.concat(this.x);
this.y=y.concat(this.y);
},
getFirst:function(){ //得到头结点
return [this.x[0],this.y[0]];
},
addLast:function(ret){ //增加尾结点
this.x.push(ret[0]);
this.y.push(ret[1]);
},
getLen:function(){ //得到结点长度
return this.x.length;
}
}
function Snake(){ //蛇身类
this._UP=1; //4个方向用数字来表示
this._DOWN=-1;
this._LEFT=2;
this._RIGHT=-2;
this._oldDirection=''; //前次移动方向
this._newDirection=''; //新移动方向
this._body=new LinkList(); //蛇身体数据结构
this.onInit();
}
Snake.prototype={
onInit:function(){ //初始化,蛇在正中间
var x = Global().WIDTH / 2;
var y = Global().HEIGHT / 2;
for (var bodyno = 0; bodyno < INISBODY; bodyno++) {
this._body.addLast([x - bodyno, y]);
}
this._oldDirection = this._newDirection = this._RIGHT;
this._life=true;//生命,碰到墙壁或者自身都判定为死(false);
},
move:function() { //按方向移动身体,用数据结构来表示就是:增加头结点,移除尾结点
if (!(this._oldDirection + this._newDirection == 0)) {//如果和上一次方向相反的话不做任何动作
this._oldDirection = this._newDirection;
}
this._oldTail=this._body.removeLast();
var x = this._body.getFirst()[0];
var y = this._body.getFirst()[1];
switch (this._oldDirection) {
case this._DOWN:
y--;
if (y <=0) {
this._life=false;
}
break;
case this._UP:
y++;
if (y > Global().HEIGHT) {
this._life=false;
}
break;
case this._LEFT:
x--;
if (x < 0) {
this._life=false;
}
break;
case this._RIGHT:
x++;
if (x >= Global().WIDTH) {
this._life=false;
}
break;
}
var newhead = [x, y];
this._body.addFirst(newhead);
},
changeDirect:function(direction) { //转换方向
this._newDirection = direction;
},
eatFood:function() {
this._body.addLast(this._oldTail);
},
getHead:function(){
return this._body.getFirst();
},
onDraw:function() { //画出单元格结点所在位置,就是蛇身
for(var bodyno=0;bodyno< this._body.getLen(); bodyno++){
fillRect(this._body.x[bodyno],this._body.y[bodyno],"blue");
}
},
isEatBody:function(){ //判断是否吃到身体
var isEat=false;
for(var bodyno=1;bodyno< this._body.getLen(); bodyno++){
if((this._body.x[bodyno]==this.getHead()[0])&&(this._body.y[bodyno]==this.getHead()[1])){
isEat=true;
};
}
return isEat;
},
isInBody:function(point){ //判断某点是否在身体内,主要是避免产生的食物点在蛇身内
var isIn=false;
for(var bodyno=0;bodyno< this._body.getLen(); bodyno++){
if((this._body.x[bodyno]==point[0])&&(this._body.y[bodyno]==point[1])){
isIn=true;
};
}
return isIn;
},
isEatGround:function(){//是否撞到墙壁死
return !this._life;
}
}
function Food(){ //食物类
this.x=0;
this.y=0;
}
Food.prototype={
onDraw:function() {
fillRect(this.x,this.y,"red");
},
isSnakeEatFood:function(snake) { //判断蛇是否吃到食物,用蛇头点坐标和食物坐标位置判断
return (this.x==snake.getHead()[0]&&this.y==snake.getHead()[1]);
},
setLocation:function(point){ //设置食物所在位置
this.x=point[0];
this.y=point[1];
}
}
function Controller(){
this.snake=new Snake();
this.food=new Food();
}
Controller.prototype={ //控制器类,用来对上面几个对象进行操控,对外进行事件监听
newGame:function(){
var point=this.getFoodLocation();
this.food.setLocation(point);
this.run();
},
changeDirect:function(direction){
this.snake.changeDirect(direction);
},
getFoodLocation:function(){ //随机获得食物位置,while作用是避免食物出现在蛇身内
var point=[];
point[0]=parseInt(Math.random()*Global().WIDTH);
point[1]=parseInt(Math.random()*Global().HEIGHT)+1;
while(this.snake.isInBody(point)){
point[0]=parseInt(Math.random()*Global().WIDTH);
point[1]=parseInt(Math.random()*Global().HEIGHT)+1;
}
return point;
},
run:function(){
this.snake.move();
if(this.food.isSnakeEatFood(this.snake)){
this.snake.eatFood();
var point=this.getFoodLocation();
this.food.setLocation(point);
}
if(this.snake.isEatGround()||(this.snake.isEatBody())){
clearTimeout(this._timer);
$$("gameover").style.display="block"
return;
}
$$("backlayer").innerHTML='';
this.snake.onDraw();
this.food.onDraw();
this._timer=setTimeout('game.run()',100);
}
}
var game;
window.onload=function(){
game=new Controller();
game.newGame();
document.onkeydown= function(){
var e=window.event||arguments[0];
var code=e.keyCode;
var dire=(code==37&&2)||(code==38&&1)||(code==39&&-2)||(code==40&&-1);
game.changeDirect(dire);
}
}
</script>
</head>
<body>
<div class="backlayer" id="backlayer"></div>
<div id="gameover" style="position:absolute;left:300px;top:300px;display:none;font-size:30px">Game Over</div>
</body>
</html>
...全文
530 72 打赏 收藏 转发到动态 举报
写回复
用AI写文章
72 条回复
切换为时间正序
请发表友善的回复…
发表回复
zouhaifeng2012 2010-09-03
  • 打赏
  • 举报
回复
依旧学习中。。。。
BeenZ 2009-12-09
  • 打赏
  • 举报
回复
[Quote=引用 66 楼 gengjian271147608 的回复:]
在游戏中(除了上下左右的键)按其他键都会gameover。为什么不把它设定关数呢?
[/Quote]
前面这个问题已解决,在楼上帖子上,这个代码主要是分享js面向对象的作用和结构,这几天有空就优化出个比较完善的版本
mark620 2009-12-08
  • 打赏
  • 举报
回复
windy2007 2009-12-08
  • 打赏
  • 举报
回复
不错啊 学习学习
netyinqing 2009-12-08
  • 打赏
  • 举报
回复
好,不错
阿萌 2009-12-08
  • 打赏
  • 举报
回复
不错,学习了
xxq0235 2009-12-08
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 serapsignore 的回复:]
引用 5 楼 sohighthesky 的回复:
引用 3 楼 click_me 的回复:
分数不错


那就jf

[/Quote] 我觉得这样很好
Owenini 2009-12-08
  • 打赏
  • 举报
回复
LZ 强悍
ck1892 2009-12-08
  • 打赏
  • 举报
回复
好贴帮忙顶起来
gengjian271147608 2009-12-08
  • 打赏
  • 举报
回复
在游戏中(除了上下左右的键)按其他键都会gameover。为什么不把它设定关数呢?
ksx_5288 2009-12-08
  • 打赏
  • 举报
回复
好东西,顶
sisiskipbeat 2009-12-08
  • 打赏
  • 举报
回复
很好的东西,谢了
BeenZ 2009-12-08
  • 打赏
  • 举报
回复
还有几个类似结构的小游戏,过两天整理后放上来给大家参考
YnSky 2009-12-08
  • 打赏
  • 举报
回复
Up
wumeng53521 2009-12-08
  • 打赏
  • 举报
回复
好东西,接分学习
chrome_ 2009-12-07
  • 打赏
  • 举报
回复
lz很强大的说
hitlcyu19 2009-12-07
  • 打赏
  • 举报
回复
jf
lovesiyile 2009-12-07
  • 打赏
  • 举报
回复
[Quote=引用 53 楼 ck1892 的回复:]
LZ用的啥编辑器?
[/Quote]
c:\windows\notepad.exe
ck1892 2009-12-07
  • 打赏
  • 举报
回复
LZ用的啥编辑器?
yongyu211 2009-12-06
  • 打赏
  • 举报
回复
还不错的!
加载更多回复(49)

87,910

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧