一个js oop的游戏,和大家交流一下oop的心得(同时谢谢提供原始游戏代码的人) 本帖最后由 amandag 于 2009-08-02 10:35:55 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 ResetSnake: function() { for (var i = 0; i < this._snakeArr.length; i++) { document.body.removeChild(this._snakeArr[i]); } this._snakeArr.splice(0, this._snakeArr.length); this._snakeArr = []; }, get_mapDivObjId: function() { return this._mapDivObjId; }, set_mapDivObjId: function(value) { this._mapDivObjId = value; }, get_footDivObjId: function() { return this._footDivObjId; }, set_footDivObjId: function(value) { this._footDivObjId = value; }, get_bodyNum: function() { return this._bodyNum; }, set_bodyNum: function(value) { this._bodyNum = value; }, get_snakeGame: function() { return this._snakeGame; }, set_snakeGame: function(value) { this._snakeGame = value; }}function keyDown(e) { var snakeGame = $Find("SnakeGame"); var direction = snakeGame.get_direction(); if(e.keyCode==37 && direction !== DirectEnum.Right) //向左 { direction = DirectEnum.Left; } else if(e.keyCode == 38 && direction !== DirectEnum.Down) //向上 { direction = DirectEnum.Up; } else if(e.keyCode == 39 && direction!==DirectEnum.Left) //向右 { direction = DirectEnum.Right; } else if(e.keyCode == 40 && direction !== DirectEnum.Up) //向下 { direction = DirectEnum.Down; } snakeGame.set_direction(direction);} //食物 function Food() { this._totalNum = 10; this.consumeNum = 0; this._footDivObjId=null;}Food.prototype = { NewFood: function() { var randomnum1 = Math.random(); var randomnum2 = Math.random(); var foodx = Math.round(870 * randomnum1) + 50; var foody = Math.round(430 * randomnum2) + 50; var footDivObj = $Get(this._footDivObjId); footDivObj.style.left = foodx + "px"; footDivObj.style.top = foody + "px"; }, CheckFood: function() { if (this._totalNum == this.consumeNum) { return true; } return false; }, ConsumeFood: function() { this.consumeNum++; }, ResetFoods: function() { this.consumeNum = 0; }, get_footDivObjId: function() { return this._footDivObjId; }, set_footDivObjId: function(value) { this._footDivObjId = value; }, get_totalNum: function() { return this._totalNum; }, set_totalNum: function(value) { this._totalNum = value; }}function GetItemPos(item) { return { Left: item.offsetLeft, Right: item.offsetLeft + item.offsetWidth, Top: item.offsetTop, Bottom: item.offsetTop + item.offsetHeight };}Number.prototype.GetWidth=function(){ return isNaN(this)?0:this;}function GetRectangle(foodPos, snakePos) { if ((snakePos.Left <= foodPos.Left) && (snakePos.Top <= foodPos.Top)) { if (snakePos.Right < foodPos.Left || snakePos.Bottom < foodPos.Top) { return -1; } else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) { return 10; } else { return (snakePos.Right - foodPos.Left) * (snakePos.Bottom - foodPos.Top); } } else if ((snakePos.Left >= foodPos.Left) && (snakePos.Top <= foodPos.Top)) { if (foodPos.Right < snakePos.Left || snakePos.Bottom < foodPos.Top) { return -1; } else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) { return 10; } else { return (foodPos.Right - snakePos.Left) * (snakePos.Bottom - foodPos.Top); } } else if ((snakePos.Left <= foodPos.Left) && (snakePos.Top >= foodPos.Top)) { if (snakePos.Right < foodPos.Left || foodPos.Bottom < snakePos.Top) { return -1; } else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) { return 10; } else { return (snakePos.Right - foodPos.Left) * (foodPos.Bottom - snakePos.Top); } } else if ((snakePos.Left >= foodPos.Left) && (snakePos.Top >= foodPos.Top)) { if (foodPos.Right < snakePos.Left || foodPos.Bottom < snakePos.Top) { return -1; } else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) { return 10; } else { return (foodPos.Right - snakePos.Left) * (foodPos.Bottom - snakePos.Top); } }}</script> </head> <body onkeydown="keyDown(event)" style="overflow:hidden" scroll="no"> <div id="map_id" style="position:absolute;left:50px;top:50px;height:480px;width:920px;background-color:rgb(223,223,223)"> </div> <div id="food_div_id" style="position:absolute;left:300px;top:230px;height:20px;width:20px;border:white solid 1px;background-color:red;"> </div> <input type="button" id="start_bt_id" value="Start" onclick="InitGame();"> <input type="text" id="tx_id" readonly> </body> </html> 不是呀,最近在研究js OOP,顺手改写了一下,绝无冒犯他人之意。。 创意没有,有的话也不会去改别人的东西了,不过是想实现一下OOP,实践一下自己的学习结果。标题写的有点那个了,其实我是花三个小时改的,本来是开个玩笑,调侃一下那个花半天写游戏的兄弟。这种做法不对,不过没法改标题了,不好意思。如果可以的话请版主帮我改成:“一个js oop的游戏,和交流一下心得(谢谢提供原始游戏代码的人)”谢谢! 谢谢版主,终于把标题改过来了,这里主要讨论的是js oop,呵呵。有兴趣的进来讨论讨论。 get_sd: function() { return this._sd; }, set_sd: function(value) { this._sd = value; }, get_isPass: function() { return this._isPass; }, set_isPass: function(value) { this._isPass = value; }, get_mode: function() { return this._mode; }, set_mode: function(value) { this._mode = value; }, get_timer: function() { return this._timer; }, set_timer: function(value) { this._timer = value; }, get_foodsId: function() { return this._foodsId; }, set_foodsId: function(value) { this._foodsId = value; }, get_direction: function() { return this._direction; }, set_direction: function(value) { this._direction = value; },邯郸学步,这些东西又长又不香.而且对俄罗斯方块,贪食蛇之类极度审美疲劳了. 楼主不要为了OO而去OO. 看了大概10秒钟代码,提几个小小建议哈.1 new SnakeGame()时没有传入一个参数,那跟定义成直接量又有什么区别呢?2 $get方法刚定义,下面紧跟着就是一个document.getElementById("start_bt_id").disabled = true.3 snake.prototype也一样没有任何必要.只会增加查找的时间开销.假如你这个程序有200行代码,至少有100行是为了讨好OO这个词衍生出的废物.4 若真要OO点的话,可以定义一个基础类,拥有设置位置,边界检测等属性方法.Food类继承基础类,增加食物delete和create方法. Snate类继承基础类,增加移动,判断迟到食物,死亡等方法. 另外这种2D游戏最好提前布置网格,频繁的判断dom节点位置是很消耗性能的. 原始帖子http://topic.csdn.net/u/20090729/09/32164988-96af-4c15-a9d4-b873764b0535.html第34楼的代码是修改后的代码。 楼主对 javascript 的oop很了解啊。我对javascript 的oop不怎么了解,只会函数式的编程。哈哈..一起学习。 我花了半天是因为我之前写过一个java版的。 可以看看这里有一个收集的帖子http://topic.csdn.net/u/20090624/12/d9579640-aa24-4560-9479-1f6e4247afd0.html while(1==1){ System.out.println("太奇妙了");} 呵呵,谢谢你的源码,游戏可以,不过你的代码有很多地方是可以再优化的,即使不用OOP。一起努力吧。 我重新组织了一下代码,加了注释,大家可以方便的看:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>wujinjian </title> <script type="text/javascript"> var ModeEnum = { First: "first", Next: "next" } //定义一个枚举,代表游戏的模式,一个json字符串的例子 var DirectEnum = { Left: "left", Right: "right", Up: "up", Down: "down" };//定义一个枚举,代表方向。 var components = {}; //哈希表,主要保存js对象 var handlers = {}; //哈希表,主要保存handler function $Find(id) { /// <summary> /// 根据id查找相应的对象 /// </summary> /// <param name="id">对象id</param> if (!components[id]) { if (id == "SnakeGame") { components[id] = new SnakeGame(); //new 一个游戏对象 } else if (id == "snake") { components[id] = new Snake(); //new 一个蛇对象 } else if (id == "foods") { components[id] = new Food(); //new 一个食物对象 } } return components[id]; } function $Get(id) { /// <summary> /// 包装getElementById /// </summary> /// <param name="id">对象id</param> return document.getElementById(id); } function $CreateDelegate(instance, method) { /// <summary> /// 创建一个委托 /// </summary> /// <param name="instance"></param> /// <param name="method" type="Function"></param> /// <returns type="Function"></returns> return function() { //返回一个函数定义 return method.apply(instance, arguments); } } function InitGame() { /// <summary> /// 初始化游戏 /// </summary> $Get("tx_id").value = "第 1 关"; var snakeGame = $Find("SnakeGame"); if (snakeGame) { snakeGame.set_snakeId("snake"); snakeGame.set_foodsId("foods"); snakeGame.ResetStart(); } } function SnakeGame() { /// <summary> /// 定义一个游戏对象,包含若干字段 /// </summary> this._sd = 250; //速度默认为250,也就是250毫秒执行一次SnakeMove,该值可以通过get_sd从对象外部获取,或者set_sd从外部设置 this._timer = null; this._foodsId = null; this._snakeId = null; this._direction = null; this._mode = ModeEnum.First; this._isPass = false; } SnakeGame.prototype = { ResetStart: function() { /// <summary> /// 初始化一个游戏对象 /// </summary> document.getElementById("start_bt_id").disabled = true; if (this._mode == ModeEnum.First) $Get("tx_id").value = "第 1 关"; this._timer = null; this._direction = DirectEnum.Right; var foods = $Find(this._foodsId); var snake = $Find(this._snakeId); snake.set_footDivObjId("food_div_id"); snake.set_mapDivObjId("map_id"); foods.set_footDivObjId("food_div_id"); foods.ResetFoods(); snake.ResetSnake(); snake.Initialize(); this._startGame(); }, _startGame: function() { /// <summary> /// 开始进行游戏 /// </summary> this._timer = setInterval(this.raise_move, this._sd); //this.raise_move执行自定义事件 }, // _moveSnake: function() { // this.raise_move(); // }, IsDivSuperpose: function(snakeDivObj, footDivObj) { /// <summary> /// 判断蛇是否吃到食物 /// </summary> /// <param name="snakeDivObj" type="dom element">dom元素蛇</param> /// <param name="footDivObj" type="dom element">dom元素食物</param> var snakePos = GetItemPos(snakeDivObj); //获取蛇头位置 var foodPos = GetItemPos(footDivObj); //获取食物位置 var rectangle = GetRectangle(foodPos, snakePos); //获取蛇与食物的交叉面积 if (rectangle > 0) { //说明吃到食物 var foods = $Find(this._foodsId); foods.ConsumeFood(); //消耗一个食物 if (!foods.CheckFood()) { //如果食物没消耗完 foods.NewFood(); //新增一个食物 var snake = $Find(this._snakeId); snake.AddSnakeBody(); //往蛇上再加一节 } else { // this.set_isPass(true); this.GoToNextLevel(); } } }, GoToNextLevel: function() { /// <summary> /// 进入下一关 /// </summary> alert("恭喜你进入下一关"); this._sd = this._sd - 10; //速度 $Get("tx_id").value = "第 " + ($Get("tx_id").value.split(" ")[1] - 0 + 1) + " 关"; this._mode = ModeEnum.Next; var foods = $Find(this._foodsId); var snake = $Find(this._snakeId); this.ResetStart(); // InitGame(); }, IsKill: function(snakeDivObj, mapDivObj) { /// <summary> /// 判断蛇是否触到边界 /// </summary> /// <param name="snakeDivObj" type="dom element">dom元素蛇</param> /// <param name="footDivObj" type="dom element">dom元素食物</param> var snakePos = GetItemPos(snakeDivObj); var panelRectangle = GetItemPos(mapDivObj); if (snakePos.Right >= panelRectangle.Right || snakePos.Left <= panelRectangle.Left || snakePos.Top <= panelRectangle.Top || snakePos.Bottom >= panelRectangle.Bottom) { this._gameOver(); return true; } return false; }, _gameOver: function() { /// <summary> /// 游戏结束 /// </summary> var obj = clearInterval(this._timer); var snake = $Find(this._snakeId); snake.ClearSnakeHandler(); //清除handler alert("失败!"); $Get("start_bt_id").disabled = false; }, get_sd: function() { return this._sd; }, set_sd: function(value) { this._sd = value; }, get_isPass: function() { return this._isPass; }, set_isPass: function(value) { this._isPass = value; }, get_mode: function() { return this._mode; }, set_mode: function(value) { this._mode = value; }, get_timer: function() { return this._timer; }, set_timer: function(value) { this._timer = value; }, get_foodsId: function() { return this._foodsId; }, set_foodsId: function(value) { this._foodsId = value; }, get_direction: function() { return this._direction; }, set_direction: function(value) { this._direction = value; }, add_move: function(handler) { /// <summary> /// add handler /// </summary> handlers["move"] = handler; }, remove_move: function(handler) { /// <summary> /// remove handler /// </summary> handlers["move"] = null; delete handlers["move"]; }, raise_move: function(eventargs) { /// <summary> /// implement handler /// </summary> var handler = handlers["move"]; if (handler) { handler(this, eventargs); } }, get_snakeId: function() { return this._snakeId; }, set_snakeId: function(value) { this._snakeId = value; } } function Snake() { /// <summary> /// 定义一个蛇对象 /// </summary> this._bodyNum = 3; this._snakeGame = "SnakeGame"; this._snakeArr = []; this._footDivObjId = null; this._mapDivObjId = null; this._moveDelegate = $CreateDelegate(this, this.SnakeMove); this.snakeBodyW_H = 20; } Snake.prototype = { AddSnakeBody: function() { /// <summary> /// 添加一个蛇身 /// </summary> this._snakeArr[this._snakeArr.length] = this._createSnakeBody(); }, _createSnakeBody: function() { /// <summary> /// 创建一个蛇身 /// </summary> var snakeDiv = document.createElement("div"); snakeDiv.style.position = "absolute"; snakeDiv.style.left = "120px"; snakeDiv.style.top = "300px"; snakeDiv.style.width = this.snakeBodyW_H + "px"; snakeDiv.style.height = this.snakeBodyW_H + "px"; document.body.appendChild(snakeDiv); return snakeDiv; }, Initialize: function() { /// <summary> /// 初始化蛇对象 /// </summary> for (var i = 0; i < this._bodyNum; i++) { this.AddSnakeBody(); } var snakeGame = $Find(this._snakeGame); if (snakeGame) { snakeGame.add_move(this._moveDelegate); //把事件绑定到游戏对象上 } }, ClearSnakeHandler: function() { /// <summary> /// 清除handler /// </summary> var snakeGame = $Find(this._snakeGame); if (snakeGame) { snakeGame.remove_move(this._moveDelegate); } }, SnakeMove: function() { /// <summary> /// 移动蛇 /// </summary> var last = this._snakeArr[this._snakeArr.length - 1]; //把最后一个元素移到第一个 for (var i = this._snakeArr.length - 1; i > 0; i--) { this._snakeArr[i] = this._snakeArr[i - 1]; this._snakeArr[i].style.backgroundColor = "red"; this._snakeArr[i].style.border = "white solid 1px"; } this._snakeArr[0] = last; var first = this._snakeArr[0]; var second = this._snakeArr[1]; first.style.backgroundColor = "blue"; var secondPos = GetItemPos(second); var footDivObj = $Get(this._footDivObjId); var mapDivObj = $Get(this._mapDivObjId); var snakeGame = $Find(this._snakeGame); if (snakeGame) { var direction = snakeGame.get_direction(); if (direction == DirectEnum.Left) { first.style.left = secondPos.Left - this.snakeBodyW_H + "px"; first.style.top = secondPos.Top + "px"; } else if (direction == DirectEnum.Up) { first.style.left = secondPos.Left + "px"; first.style.top = secondPos.Top - this.snakeBodyW_H + "px"; } else if (direction == DirectEnum.Right) { first.style.left = secondPos.Left + this.snakeBodyW_H + "px"; first.style.top = secondPos.Top + "px"; } else if (direction == DirectEnum.Down) { first.style.left = secondPos.Left + "px"; first.style.top = secondPos.Top + this.snakeBodyW_H + "px"; } if (!snakeGame.IsKill(first, mapDivObj)) snakeGame.IsDivSuperpose(first, footDivObj); } }, ResetSnake: function() { /// <summary> /// 重置蛇对象 /// </summary> for (var i = 0; i < this._snakeArr.length; i++) { document.body.removeChild(this._snakeArr[i]); } this._snakeArr.splice(0, this._snakeArr.length); this._snakeArr = []; }, get_mapDivObjId: function() { return this._mapDivObjId; }, set_mapDivObjId: function(value) { this._mapDivObjId = value; }, get_footDivObjId: function() { return this._footDivObjId; }, set_footDivObjId: function(value) { this._footDivObjId = value; }, get_bodyNum: function() { return this._bodyNum; }, set_bodyNum: function(value) { this._bodyNum = value; }, get_snakeGame: function() { return this._snakeGame; }, set_snakeGame: function(value) { this._snakeGame = value; } } function keyDown(e) { /// <summary> /// keydown事件 /// </summary> var snakeGame = $Find("SnakeGame"); var direction = snakeGame.get_direction(); if (e.keyCode == 37 && direction !== DirectEnum.Right) //向左 { direction = DirectEnum.Left; } else if (e.keyCode == 38 && direction !== DirectEnum.Down) //向上 { direction = DirectEnum.Up; } else if (e.keyCode == 39 && direction !== DirectEnum.Left) //向右 { direction = DirectEnum.Right; } else if (e.keyCode == 40 && direction !== DirectEnum.Up) //向下 { direction = DirectEnum.Down; } snakeGame.set_direction(direction); } //食物 function Food() { /// <summary> /// 初始化食物对象 /// </summary> this._totalNum = 10; this.consumeNum = 0; this._footDivObjId = null; } Food.prototype = { NewFood: function() { /// <summary> /// 新增一个食物 /// </summary> var randomnum1 = Math.random(); var randomnum2 = Math.random(); var foodx = Math.round(870 * randomnum1) + 50; var foody = Math.round(430 * randomnum2) + 50; var footDivObj = $Get(this._footDivObjId); footDivObj.style.left = foodx + "px"; footDivObj.style.top = foody + "px"; }, CheckFood: function() { /// <summary> /// 检测食物是否消耗完 /// </summary> if (this._totalNum == this.consumeNum) { return true; } return false; }, ConsumeFood: function() { /// <summary> /// 消耗一个食物 /// </summary> this.consumeNum++; }, ResetFoods: function() { /// <summary> /// 重置对象 /// </summary> this.consumeNum = 0; }, get_footDivObjId: function() { return this._footDivObjId; }, set_footDivObjId: function(value) { this._footDivObjId = value; }, get_totalNum: function() { return this._totalNum; }, set_totalNum: function(value) { this._totalNum = value; } } function GetItemPos(item) { return { Left: item.offsetLeft, Right: item.offsetLeft + item.offsetWidth, Top: item.offsetTop, Bottom: item.offsetTop + item.offsetHeight }; } Number.prototype.GetWidth = function() { /// <summary> /// 给number原型添加一个自定义方法,使用例子:10.GetWidth(); /// </summary> return isNaN(this) ? 0 : this; } function GetRectangle(foodPos, snakePos) { /// <summary> /// 获取矩形的四个点位置 /// </summary> if ((snakePos.Left <= foodPos.Left) && (snakePos.Top <= foodPos.Top)) { if (snakePos.Right < foodPos.Left || snakePos.Bottom < foodPos.Top) { return -1; } else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) { return 10; } else { return (snakePos.Right - foodPos.Left) * (snakePos.Bottom - foodPos.Top); } } else if ((snakePos.Left >= foodPos.Left) && (snakePos.Top <= foodPos.Top)) { if (foodPos.Right < snakePos.Left || snakePos.Bottom < foodPos.Top) { return -1; } else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) { return 10; } else { return (foodPos.Right - snakePos.Left) * (snakePos.Bottom - foodPos.Top); } } else if ((snakePos.Left <= foodPos.Left) && (snakePos.Top >= foodPos.Top)) { if (snakePos.Right < foodPos.Left || foodPos.Bottom < snakePos.Top) { return -1; } else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) { return 10; } else { return (snakePos.Right - foodPos.Left) * (foodPos.Bottom - snakePos.Top); } } else if ((snakePos.Left >= foodPos.Left) && (snakePos.Top >= foodPos.Top)) { if (foodPos.Right < snakePos.Left || foodPos.Bottom < snakePos.Top) { return -1; } else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) { return 10; } else { return (foodPos.Right - snakePos.Left) * (foodPos.Bottom - snakePos.Top); } } }</script> </head> <body onkeydown="keyDown(event)" style="overflow:hidden" scroll="no"> <div id="map_id" style="position:absolute;left:50px;top:50px;height:480px;width:920px;background-color:rgb(223,223,223)"> </div> <div id="food_div_id" style="position:absolute;left:300px;top:230px;height:20px;width:20px;border:white solid 1px;background-color:red;"> </div> <input type="button" id="start_bt_id" value="Start" onclick="InitGame();"> <input type="text" id="tx_id" readonly> </body> </html> 说的好~lz都this.xx了,还get_xx浪费资源,你var xx再 get_xx还说的过去...另外我也觉既然是炫技术炫标准,那就用继承撒,要不然和面向过程又有多大区别呢 这位兄弟,this.xx只是在对象内部操作,get,set是对象之间的操作,这里我觉得不需要用到,如果你说需要用到继承,在js里面无非就是原型继承,拷贝继承,构造继承等几种方式。 ,并不难 get_mapDivObjId: function() { return this._mapDivObjId; }, set_mapDivObjId: function(value) { this._mapDivObjId = value; }, get_footDivObjId: function() { return this._footDivObjId; }, set_footDivObjId: function(value) { this._footDivObjId = value; }, get_bodyNum: function() { return this._bodyNum; }, set_bodyNum: function(value) { this._bodyNum = value; }, get_snakeGame: function() { return this._snakeGame; }, set_snakeGame: function(value) { this._snakeGame = value; }可见楼主思维受C#或Java禁锢之深!!!不要以为把js代码来一番C# like或者Java like了就是善举,这样的确像zengtan1021所说的既长又不香!什么脚穿什么鞋嘛。同时,基于RPWT,你应该列出原作者及其链接。 比如你的对象A用this.Name来存放姓名了,那么另外一个对象就可以用A.Name访问它的姓名,包括读和写,何必要通过get_Name函数来读又通过set_Name来写如果你硬是要用get_Name和set_Name,那么A对象的Name就应该是var Name而不是this.Name 呵呵,这位兄弟说的是,我没法改帖子内容,所以不好意思。实话说我觉得直接使用this.xx不是一个很好的习惯,通过get,set我完全可以再使用之前验证数据的有效性,也就是我可以做到js强类型化又比如我可以在执行IsKill: function(snakeDivObj, mapDivObj)之前验证snakeDivObj或者mapDivObj是否是dom元素,不是则抛出异常。。 另外继承并不是为了继承而继承。当你觉得你的代码篇幅太长了,bug太多了,你就用继承吧,如果你觉得没这样的烦恼,那你别管它种类再少,实现起来再容易,也不用管它什么继承不继承,除非你要炫耀你的技术 即使我是炫耀你也不用这么说,对人不对事不是个好习惯。而且我觉得讨论也是一个学习长进的过程,比如一位兄弟说事先布置网格,这是我没接触过的东西,至少我是学到东西了。如果你认为可以这么说,那会不会大家都因为你说的炫耀技术就没人敢贴自己的代码或者发表自己的文章来讨论技术了,因为怕别人说炫耀嘛。=============================当你觉得你的代码篇幅太长了,bug太多了,你就用继承吧==============这句话我不敢苟同,代码多了就用继承?呵呵 我觉得继承就是重用、统一的设计思想,好处就是代码精简、bug更少,节省维护扩充精力,不是么? 原始帖子:http://topic.csdn.net/u/20090729/09/32164988-96af-4c15-a9d4-b873764b0535.html 再次谢谢这个兄弟。如果可以,版主请给我加到楼顶。谢谢! 大家都是对js的Games设计有兴趣的人,讨论一点高层次的东西吧,比如把技术转换成生产力?简单的东西不见得没有经济价值,甚至就像lz做的贪食蛇,比如你把它做成online的那你仅仅是浏览器+js,是办不到的,或者效率太低无法太多人在线,如果有个提供高性能联网对象集的外壳来代替浏览器?如果不代替浏览器,而是把这些基本对象集做成一个控件,下载安装或者在线安装?然后再解决如何提升游戏平台粘度的问题,那就是又一个开心网啊。 zengtan1021兄,网格的事我正要请教你,请教个思路。 你google一下 javascript 泡泡堂这个东西是我前阵子写的.因为时间和精力原因,效果不是很好,但网格的东西你可以借鉴一下哈. 发现了csdn的下载地址.http://u.download.csdn.net/source/1536151鄙视一下转载不注明出处的人. 国外有人写 super mario, 那个比较强! 动态移除下拉框的选项 Jquery 修改页面文字 关于javascript正则的问题 小问题,怎么样点击上传按钮返回值到主窗口的值去? 奇怪的 js 被缓存的问题 表单传递 javascript如何控制Div的滚动条是否显示? 急!父页面和子页面之间的参数怎样传递及设置问题? 怎样使鼠标箭头形状变成沙漏的形状? artdialog 弹出页面使用浏览器打印问题(请教能人志士帮帮忙) 新手关于setInterval()方法的小问题 求助编写一点javascript,点击按钮后调用某个图片(如素材\images\loading.gif)
ResetSnake: function() {
for (var i = 0; i < this._snakeArr.length; i++) {
document.body.removeChild(this._snakeArr[i]);
}
this._snakeArr.splice(0, this._snakeArr.length);
this._snakeArr = [];
},
get_mapDivObjId: function() { return this._mapDivObjId; },
set_mapDivObjId: function(value) { this._mapDivObjId = value; }, get_footDivObjId: function() { return this._footDivObjId; },
set_footDivObjId: function(value) { this._footDivObjId = value; }, get_bodyNum: function() { return this._bodyNum; },
set_bodyNum: function(value) { this._bodyNum = value; }, get_snakeGame: function() { return this._snakeGame; },
set_snakeGame: function(value) { this._snakeGame = value; }
}function keyDown(e)
{
var snakeGame = $Find("SnakeGame");
var direction = snakeGame.get_direction();
if(e.keyCode==37 && direction !== DirectEnum.Right) //向左
{
direction = DirectEnum.Left;
}
else if(e.keyCode == 38 && direction !== DirectEnum.Down) //向上
{
direction = DirectEnum.Up;
}
else if(e.keyCode == 39 && direction!==DirectEnum.Left) //向右
{
direction = DirectEnum.Right;
}
else if(e.keyCode == 40 && direction !== DirectEnum.Up) //向下
{
direction = DirectEnum.Down;
}
snakeGame.set_direction(direction);
}
//食物
function Food()
{
this._totalNum = 10;
this.consumeNum = 0;
this._footDivObjId=null;
}
Food.prototype = {
NewFood: function() {
var randomnum1 = Math.random();
var randomnum2 = Math.random(); var foodx = Math.round(870 * randomnum1) + 50;
var foody = Math.round(430 * randomnum2) + 50; var footDivObj = $Get(this._footDivObjId); footDivObj.style.left = foodx + "px";
footDivObj.style.top = foody + "px";
},
CheckFood: function() {
if (this._totalNum == this.consumeNum) {
return true;
}
return false;
},
ConsumeFood: function() {
this.consumeNum++;
},
ResetFoods: function() {
this.consumeNum = 0;
},
get_footDivObjId: function() { return this._footDivObjId; },
set_footDivObjId: function(value) { this._footDivObjId = value; },
get_totalNum: function() { return this._totalNum; },
set_totalNum: function(value) { this._totalNum = value; }
}
function GetItemPos(item) {
return { Left: item.offsetLeft, Right: item.offsetLeft + item.offsetWidth, Top: item.offsetTop, Bottom: item.offsetTop + item.offsetHeight };
}Number.prototype.GetWidth=function()
{
return isNaN(this)?0:this;
}
function GetRectangle(foodPos, snakePos) {
if ((snakePos.Left <= foodPos.Left) && (snakePos.Top <= foodPos.Top)) {
if (snakePos.Right < foodPos.Left || snakePos.Bottom < foodPos.Top) {
return -1;
}
else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) {
return 10;
}
else {
return (snakePos.Right - foodPos.Left) * (snakePos.Bottom - foodPos.Top);
}
}
else if ((snakePos.Left >= foodPos.Left) && (snakePos.Top <= foodPos.Top)) {
if (foodPos.Right < snakePos.Left || snakePos.Bottom < foodPos.Top) {
return -1;
}
else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) {
return 10;
}
else {
return (foodPos.Right - snakePos.Left) * (snakePos.Bottom - foodPos.Top);
}
}
else if ((snakePos.Left <= foodPos.Left) && (snakePos.Top >= foodPos.Top)) {
if (snakePos.Right < foodPos.Left || foodPos.Bottom < snakePos.Top) {
return -1;
}
else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) {
return 10;
}
else {
return (snakePos.Right - foodPos.Left) * (foodPos.Bottom - snakePos.Top);
}
}
else if ((snakePos.Left >= foodPos.Left) && (snakePos.Top >= foodPos.Top)) {
if (foodPos.Right < snakePos.Left || foodPos.Bottom < snakePos.Top) {
return -1;
}
else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) {
return 10;
}
else {
return (foodPos.Right - snakePos.Left) * (foodPos.Bottom - snakePos.Top);
}
}
}
</script>
</head>
<body onkeydown="keyDown(event)" style="overflow:hidden" scroll="no"> <div id="map_id" style="position:absolute;left:50px;top:50px;height:480px;width:920px;background-color:rgb(223,223,223)">
</div> <div id="food_div_id" style="position:absolute;left:300px;top:230px;height:20px;width:20px;border:white solid 1px;background-color:red;">
</div> <input type="button" id="start_bt_id" value="Start" onclick="InitGame();">
<input type="text" id="tx_id" readonly>
</body>
</html>
标题写的有点那个了,其实我是花三个小时改的,本来是开个玩笑,调侃一下那个花半天写游戏的兄弟。这种做法不对,不过没法改标题了,不好意思。
如果可以的话请版主帮我改成:“一个js oop的游戏,和交流一下心得(谢谢提供原始游戏代码的人)”
谢谢!
有兴趣的进来讨论讨论。
set_sd: function(value) { this._sd = value; }, get_isPass: function() { return this._isPass; },
set_isPass: function(value) { this._isPass = value; }, get_mode: function() { return this._mode; },
set_mode: function(value) { this._mode = value; }, get_timer: function() { return this._timer; },
set_timer: function(value) { this._timer = value; }, get_foodsId: function() { return this._foodsId; },
set_foodsId: function(value) { this._foodsId = value; }, get_direction: function() { return this._direction; },
set_direction: function(value) { this._direction = value; },邯郸学步,这些东西又长又不香.而且对俄罗斯方块,贪食蛇之类极度审美疲劳了.
http://topic.csdn.net/u/20090729/09/32164988-96af-4c15-a9d4-b873764b0535.html第34楼的代码是修改后的代码。
http://topic.csdn.net/u/20090624/12/d9579640-aa24-4560-9479-1f6e4247afd0.html
System.out.println("太奇妙了");
}
呵呵,谢谢你的源码,游戏可以,不过你的代码有很多地方是可以再优化的,即使不用OOP。
一起努力吧。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>wujinjian </title>
<script type="text/javascript">
var ModeEnum = { First: "first", Next: "next" } //定义一个枚举,代表游戏的模式,一个json字符串的例子
var DirectEnum = { Left: "left", Right: "right", Up: "up", Down: "down" };//定义一个枚举,代表方向。
var components = {}; //哈希表,主要保存js对象
var handlers = {}; //哈希表,主要保存handler
function $Find(id) {
/// <summary>
/// 根据id查找相应的对象
/// </summary>
/// <param name="id">对象id</param>
if (!components[id]) {
if (id == "SnakeGame") {
components[id] = new SnakeGame(); //new 一个游戏对象
}
else if (id == "snake") {
components[id] = new Snake(); //new 一个蛇对象
}
else if (id == "foods") {
components[id] = new Food(); //new 一个食物对象
}
}
return components[id];
}
function $Get(id) {
/// <summary>
/// 包装getElementById
/// </summary>
/// <param name="id">对象id</param>
return document.getElementById(id);
}
function $CreateDelegate(instance, method) {
/// <summary>
/// 创建一个委托
/// </summary>
/// <param name="instance"></param>
/// <param name="method" type="Function"></param>
/// <returns type="Function"></returns>
return function() { //返回一个函数定义
return method.apply(instance, arguments);
}
}
function InitGame() {
/// <summary>
/// 初始化游戏
/// </summary>
$Get("tx_id").value = "第 1 关";
var snakeGame = $Find("SnakeGame");
if (snakeGame) {
snakeGame.set_snakeId("snake");
snakeGame.set_foodsId("foods");
snakeGame.ResetStart();
}
}
function SnakeGame() {
/// <summary>
/// 定义一个游戏对象,包含若干字段
/// </summary>
this._sd = 250; //速度默认为250,也就是250毫秒执行一次SnakeMove,该值可以通过get_sd从对象外部获取,或者set_sd从外部设置
this._timer = null;
this._foodsId = null;
this._snakeId = null;
this._direction = null;
this._mode = ModeEnum.First;
this._isPass = false;
}
SnakeGame.prototype = {
ResetStart: function() {
/// <summary>
/// 初始化一个游戏对象
/// </summary>
document.getElementById("start_bt_id").disabled = true; if (this._mode == ModeEnum.First)
$Get("tx_id").value = "第 1 关";
this._timer = null;
this._direction = DirectEnum.Right;
var foods = $Find(this._foodsId);
var snake = $Find(this._snakeId);
snake.set_footDivObjId("food_div_id");
snake.set_mapDivObjId("map_id");
foods.set_footDivObjId("food_div_id");
foods.ResetFoods();
snake.ResetSnake();
snake.Initialize();
this._startGame();
},
_startGame: function() {
/// <summary>
/// 开始进行游戏
/// </summary>
this._timer = setInterval(this.raise_move, this._sd); //this.raise_move执行自定义事件
},
// _moveSnake: function() {
// this.raise_move();
// },
IsDivSuperpose: function(snakeDivObj, footDivObj) {
/// <summary>
/// 判断蛇是否吃到食物
/// </summary>
/// <param name="snakeDivObj" type="dom element">dom元素蛇</param>
/// <param name="footDivObj" type="dom element">dom元素食物</param>
var snakePos = GetItemPos(snakeDivObj); //获取蛇头位置
var foodPos = GetItemPos(footDivObj); //获取食物位置
var rectangle = GetRectangle(foodPos, snakePos); //获取蛇与食物的交叉面积
if (rectangle > 0) { //说明吃到食物
var foods = $Find(this._foodsId);
foods.ConsumeFood(); //消耗一个食物
if (!foods.CheckFood()) { //如果食物没消耗完
foods.NewFood(); //新增一个食物
var snake = $Find(this._snakeId);
snake.AddSnakeBody(); //往蛇上再加一节
}
else {
// this.set_isPass(true);
this.GoToNextLevel();
} }
},
GoToNextLevel: function() {
/// <summary>
/// 进入下一关
/// </summary>
alert("恭喜你进入下一关");
this._sd = this._sd - 10; //速度
$Get("tx_id").value = "第 " + ($Get("tx_id").value.split(" ")[1] - 0 + 1) + " 关";
this._mode = ModeEnum.Next;
var foods = $Find(this._foodsId);
var snake = $Find(this._snakeId);
this.ResetStart();
// InitGame();
},
IsKill: function(snakeDivObj, mapDivObj) {
/// <summary>
/// 判断蛇是否触到边界
/// </summary>
/// <param name="snakeDivObj" type="dom element">dom元素蛇</param>
/// <param name="footDivObj" type="dom element">dom元素食物</param>
var snakePos = GetItemPos(snakeDivObj);
var panelRectangle = GetItemPos(mapDivObj);
if (snakePos.Right >= panelRectangle.Right ||
snakePos.Left <= panelRectangle.Left || snakePos.Top <= panelRectangle.Top
|| snakePos.Bottom >= panelRectangle.Bottom) {
this._gameOver();
return true;
}
return false;
},
_gameOver: function() {
/// <summary>
/// 游戏结束
/// </summary>
var obj = clearInterval(this._timer);
var snake = $Find(this._snakeId);
snake.ClearSnakeHandler(); //清除handler
alert("失败!");
$Get("start_bt_id").disabled = false;
},
get_sd: function() { return this._sd; },
set_sd: function(value) { this._sd = value; }, get_isPass: function() { return this._isPass; },
set_isPass: function(value) { this._isPass = value; }, get_mode: function() { return this._mode; },
set_mode: function(value) { this._mode = value; }, get_timer: function() { return this._timer; },
set_timer: function(value) { this._timer = value; }, get_foodsId: function() { return this._foodsId; },
set_foodsId: function(value) { this._foodsId = value; }, get_direction: function() { return this._direction; },
set_direction: function(value) { this._direction = value; },
add_move: function(handler) {
/// <summary>
/// add handler
/// </summary>
handlers["move"] = handler;
},
remove_move: function(handler) {
/// <summary>
/// remove handler
/// </summary>
handlers["move"] = null;
delete handlers["move"];
},
raise_move: function(eventargs) {
/// <summary>
/// implement handler
/// </summary>
var handler = handlers["move"];
if (handler) {
handler(this, eventargs);
}
},
get_snakeId: function() { return this._snakeId; },
set_snakeId: function(value) { this._snakeId = value; }
}
function Snake() {
/// <summary>
/// 定义一个蛇对象
/// </summary>
this._bodyNum = 3;
this._snakeGame = "SnakeGame";
this._snakeArr = [];
this._footDivObjId = null;
this._mapDivObjId = null;
this._moveDelegate = $CreateDelegate(this, this.SnakeMove);
this.snakeBodyW_H = 20;
}
Snake.prototype = {
AddSnakeBody: function() {
/// <summary>
/// 添加一个蛇身
/// </summary>
this._snakeArr[this._snakeArr.length] = this._createSnakeBody();
},
_createSnakeBody: function() {
/// <summary>
/// 创建一个蛇身
/// </summary>
var snakeDiv = document.createElement("div"); snakeDiv.style.position = "absolute";
snakeDiv.style.left = "120px";
snakeDiv.style.top = "300px";
snakeDiv.style.width = this.snakeBodyW_H + "px";
snakeDiv.style.height = this.snakeBodyW_H + "px"; document.body.appendChild(snakeDiv); return snakeDiv;
},
Initialize: function() {
/// <summary>
/// 初始化蛇对象
/// </summary>
for (var i = 0; i < this._bodyNum; i++) {
this.AddSnakeBody();
}
var snakeGame = $Find(this._snakeGame);
if (snakeGame) {
snakeGame.add_move(this._moveDelegate); //把事件绑定到游戏对象上
}
},
ClearSnakeHandler: function() {
/// <summary>
/// 清除handler
/// </summary>
var snakeGame = $Find(this._snakeGame);
if (snakeGame) {
snakeGame.remove_move(this._moveDelegate);
}
},
SnakeMove: function() {
/// <summary>
/// 移动蛇
/// </summary>
var last = this._snakeArr[this._snakeArr.length - 1]; //把最后一个元素移到第一个
for (var i = this._snakeArr.length - 1; i > 0; i--) {
this._snakeArr[i] = this._snakeArr[i - 1];
this._snakeArr[i].style.backgroundColor = "red";
this._snakeArr[i].style.border = "white solid 1px";
}
this._snakeArr[0] = last; var first = this._snakeArr[0];
var second = this._snakeArr[1]; first.style.backgroundColor = "blue"; var secondPos = GetItemPos(second);
var footDivObj = $Get(this._footDivObjId);
var mapDivObj = $Get(this._mapDivObjId);
var snakeGame = $Find(this._snakeGame);
if (snakeGame) {
var direction = snakeGame.get_direction();
if (direction == DirectEnum.Left) {
first.style.left = secondPos.Left - this.snakeBodyW_H + "px";
first.style.top = secondPos.Top + "px";
}
else if (direction == DirectEnum.Up) {
first.style.left = secondPos.Left + "px";
first.style.top = secondPos.Top - this.snakeBodyW_H + "px";
}
else if (direction == DirectEnum.Right) {
first.style.left = secondPos.Left + this.snakeBodyW_H + "px";
first.style.top = secondPos.Top + "px";
}
else if (direction == DirectEnum.Down) {
first.style.left = secondPos.Left + "px";
first.style.top = secondPos.Top + this.snakeBodyW_H + "px";
}
if (!snakeGame.IsKill(first, mapDivObj))
snakeGame.IsDivSuperpose(first, footDivObj);
} }, ResetSnake: function() {
/// <summary>
/// 重置蛇对象
/// </summary>
for (var i = 0; i < this._snakeArr.length; i++) {
document.body.removeChild(this._snakeArr[i]);
}
this._snakeArr.splice(0, this._snakeArr.length);
this._snakeArr = [];
},
get_mapDivObjId: function() { return this._mapDivObjId; },
set_mapDivObjId: function(value) { this._mapDivObjId = value; }, get_footDivObjId: function() { return this._footDivObjId; },
set_footDivObjId: function(value) { this._footDivObjId = value; }, get_bodyNum: function() { return this._bodyNum; },
set_bodyNum: function(value) { this._bodyNum = value; }, get_snakeGame: function() { return this._snakeGame; },
set_snakeGame: function(value) { this._snakeGame = value; }
} function keyDown(e) {
/// <summary>
/// keydown事件
/// </summary>
var snakeGame = $Find("SnakeGame");
var direction = snakeGame.get_direction();
if (e.keyCode == 37 && direction !== DirectEnum.Right) //向左
{
direction = DirectEnum.Left;
}
else if (e.keyCode == 38 && direction !== DirectEnum.Down) //向上
{
direction = DirectEnum.Up;
}
else if (e.keyCode == 39 && direction !== DirectEnum.Left) //向右
{
direction = DirectEnum.Right;
}
else if (e.keyCode == 40 && direction !== DirectEnum.Up) //向下
{
direction = DirectEnum.Down;
}
snakeGame.set_direction(direction);
}
//食物
function Food() {
/// <summary>
/// 初始化食物对象
/// </summary>
this._totalNum = 10;
this.consumeNum = 0;
this._footDivObjId = null;
}
Food.prototype = {
NewFood: function() {
/// <summary>
/// 新增一个食物
/// </summary>
var randomnum1 = Math.random();
var randomnum2 = Math.random(); var foodx = Math.round(870 * randomnum1) + 50;
var foody = Math.round(430 * randomnum2) + 50; var footDivObj = $Get(this._footDivObjId); footDivObj.style.left = foodx + "px";
footDivObj.style.top = foody + "px";
},
CheckFood: function() {
/// <summary>
/// 检测食物是否消耗完
/// </summary>
if (this._totalNum == this.consumeNum) {
return true;
}
return false;
},
ConsumeFood: function() {
/// <summary>
/// 消耗一个食物
/// </summary>
this.consumeNum++;
},
ResetFoods: function() {
/// <summary>
/// 重置对象
/// </summary>
this.consumeNum = 0;
},
get_footDivObjId: function() { return this._footDivObjId; },
set_footDivObjId: function(value) { this._footDivObjId = value; }, get_totalNum: function() { return this._totalNum; },
set_totalNum: function(value) { this._totalNum = value; }
}
function GetItemPos(item) {
return { Left: item.offsetLeft, Right: item.offsetLeft + item.offsetWidth, Top: item.offsetTop, Bottom: item.offsetTop + item.offsetHeight };
} Number.prototype.GetWidth = function() {
/// <summary>
/// 给number原型添加一个自定义方法,使用例子:10.GetWidth();
/// </summary>
return isNaN(this) ? 0 : this;
}
function GetRectangle(foodPos, snakePos) {
/// <summary>
/// 获取矩形的四个点位置
/// </summary>
if ((snakePos.Left <= foodPos.Left) && (snakePos.Top <= foodPos.Top)) {
if (snakePos.Right < foodPos.Left || snakePos.Bottom < foodPos.Top) {
return -1;
}
else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) {
return 10;
}
else {
return (snakePos.Right - foodPos.Left) * (snakePos.Bottom - foodPos.Top);
}
}
else if ((snakePos.Left >= foodPos.Left) && (snakePos.Top <= foodPos.Top)) {
if (foodPos.Right < snakePos.Left || snakePos.Bottom < foodPos.Top) {
return -1;
}
else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) {
return 10;
}
else {
return (foodPos.Right - snakePos.Left) * (snakePos.Bottom - foodPos.Top);
}
}
else if ((snakePos.Left <= foodPos.Left) && (snakePos.Top >= foodPos.Top)) {
if (snakePos.Right < foodPos.Left || foodPos.Bottom < snakePos.Top) {
return -1;
}
else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) {
return 10;
}
else {
return (snakePos.Right - foodPos.Left) * (foodPos.Bottom - snakePos.Top);
}
}
else if ((snakePos.Left >= foodPos.Left) && (snakePos.Top >= foodPos.Top)) {
if (foodPos.Right < snakePos.Left || foodPos.Bottom < snakePos.Top) {
return -1;
}
else if ((snakePos.Left == foodPos.Left) && (snakePos.Top == foodPos.Top)) {
return 10;
}
else {
return (foodPos.Right - snakePos.Left) * (foodPos.Bottom - snakePos.Top);
}
}
}
</script>
</head>
<body onkeydown="keyDown(event)" style="overflow:hidden" scroll="no"> <div id="map_id" style="position:absolute;left:50px;top:50px;height:480px;width:920px;background-color:rgb(223,223,223)">
</div> <div id="food_div_id" style="position:absolute;left:300px;top:230px;height:20px;width:20px;border:white solid 1px;background-color:red;">
</div> <input type="button" id="start_bt_id" value="Start" onclick="InitGame();">
<input type="text" id="tx_id" readonly>
</body>
</html>
说的好~
lz都this.xx了,还get_xx浪费资源,你var xx再 get_xx还说的过去...
另外我也觉既然是炫技术炫标准,那就用继承撒,要不然和面向过程又有多大区别呢
set_mapDivObjId: function(value) { this._mapDivObjId = value; }, get_footDivObjId: function() { return this._footDivObjId; },
set_footDivObjId: function(value) { this._footDivObjId = value; }, get_bodyNum: function() { return this._bodyNum; },
set_bodyNum: function(value) { this._bodyNum = value; }, get_snakeGame: function() { return this._snakeGame; },
set_snakeGame: function(value) { this._snakeGame = value; }
可见楼主思维受C#或Java禁锢之深!!!
不要以为把js代码来一番C# like或者Java like了就是善举,这样的确像zengtan1021所说的既长又不香!
什么脚穿什么鞋嘛。同时,基于RPWT,你应该列出原作者及其链接。
如果你硬是要用get_Name和set_Name,那么A对象的Name就应该是var Name而不是this.Name
实话说我觉得直接使用this.xx不是一个很好的习惯,通过get,set我完全可以再使用之前验证数据的有效性,也就是我可以做到js强类型化
又比如我可以在执行IsKill: function(snakeDivObj, mapDivObj)之前验证snakeDivObj或者mapDivObj是否是dom元素,不是则抛出异常。。
当你觉得你的代码篇幅太长了,bug太多了,你就用继承吧,如果你觉得没这样的烦恼,那你别管它种类再少,实现起来再容易,也不用管它什么继承不继承,除非你要炫耀你的技术
=============================
当你觉得你的代码篇幅太长了,bug太多了,你就用继承吧
==============
这句话我不敢苟同,代码多了就用继承?呵呵
http://topic.csdn.net/u/20090729/09/32164988-96af-4c15-a9d4-b873764b0535.html 再次谢谢这个兄弟。
如果可以,版主请给我加到楼顶。谢谢!
简单的东西不见得没有经济价值,甚至就像lz做的贪食蛇,比如你把它做成online的
那你仅仅是浏览器+js,是办不到的,或者效率太低无法太多人在线,如果有个提供
高性能联网对象集的外壳来代替浏览器?如果不代替浏览器,而是把这些基本对象集做
成一个控件,下载安装或者在线安装?然后再解决如何提升游戏平台粘度的问题,那就是又一个
开心网啊。
http://u.download.csdn.net/source/1536151鄙视一下转载不注明出处的人.