下面是一个使用canvas API加JS面向对象的方式编写的一个贪吃蛇的简单实现,实现了穿墙、吃食物后智能加速,还缺少障碍物,地图切换,还有就是太丑了,有兴趣的朋友可以修改一下,我觉得这个还算好扩展,特地贴出来大家讨论研究,算法我写得差劲,权当抛砖引玉之用。
Java代码
Java代码
- <!DOCTYPE HTML>
- <html>
- <head>
- <meta charset="utf-8">
- <title>Asphyre</title>
- <script>
- var AsphyreNode = function(x, y, w, h){
- this.x = x;
- this.y = y;
- this.w = w;
- this.h = h;
- this.equals = function(node) {
- if(this.x === node.x && this.y === node.y)
- return true;
- return false;
- }
- };
- function Asphyre(farm, x, y, speed, initNodes){ //对贪吃蛇的描述,相当于实现一个蛇类
- var self = this;
- this.perform = null; //定时器引用
- this.speed = speed;
- this.speedParam = speed * initNodes; //蛇移动的速度
- this.nodeSize = 10; //蛇每一节的大小
- this.nodes = []; //节点数
- this.initNodes = initNodes;
- this.farm = farm;
- this.x = x;
- this.y = y;
- this.direction = 10; //表示向右,初始方向
- this.left = -10,this.right = 10;
- this.down = 1, this.up = -1;
- document.onkeypress = function(event) {
- event = event || window.event;
- var code = event.keyCode || event.charCode();
- var isException = false;
- switch(code) {
- case 37: //向左
- if(self.direction + self.left){
- self.direction = self.left;
- } else isException = true;
- break;
- case 38: //向上
- if(self.direction + self.up){
- self.direction = self.up;
- } else isException = true;
- break;
- case 39: //向右
- if(self.direction + self.right){
- self.direction = self.right;
- } else isException = true;
- break;
- case 40: //向下
- if(self.direction + self.down){
- self.direction = self.down;
- } else isException = true;
- break;
- }
- if(isException){
- alert("方向异常,不能沿反方向后退!");
- }
- }
- };
- Asphyre.prototype = {
- init: function(){
- var self = this, farm = this.farm, x = this.x, y = this.y;
- this.nodes = [];
- for(var i = 0; i < this.initNodes; i ++) {
- this.nodes = new AsphyreNode(this.x - i * 10, this.y, this.nodeSize, this.nodeSize);
- }
- this.farm.food = this.farm.newFood(this);
- this.farm.repaint(this);
- },
- drawNodes: function(context){ //绘制设身体
- var self = this;
- context.fillStyle = "#000000";
- context.strokeStyle = "#ffffff";
- for(var i = 0; i < this.nodes.length; i ++) {
- context.fillRect(this.nodes.x, this.nodes.y, this.nodeSize, this.nodeSize);
- context.strokeRect(this.nodes.x, this.nodes.y, this.nodeSize, this.nodeSize);
- }
- },
- eatFood: function() {//吃食物
- var self = this;
- self.nodes.unshift(self.farm.food);
- self.farm.food = self.farm.newFood(self);
- self.refreshSpeed();
- },
- start: function(){//开始
- var self = this;
- self.init();
- if(!self.perform)
- self.perform = setInterval(self.go, self.speed, this);
- },
- continueRun: function(){ //继续
- var self = this;
- if(!self.perform)
- self.perform = setInterval(self.go, self.speed, this);
- },
- stop: function(){//结束
- var self = this;
- if(!!self.perform)
- clearInterval(self.perform);
- self.perform = null;
- self.farm.clear();
- },
- pause: function() { //暂停
- var self = this;
- if(!!self.perform)
- clearInterval(self.perform);
- self.perform = null;
- },
- go: function(param){//沿着当前方向前进
- var self = param;
- switch(self.direction) {
- case -1: //上
- if(self.nodes[0].equals(self.farm.food)) {//吃到食物,少走一步
- self.farm.food.y -= self.nodeSize
- self.eatFood();
- self.farm.repaint(self);
- return;
- }
- var varluable = self.nodes[0].y - self.nodeSize;
- if(varluable < 0)
- varluable = self.farm.farmElem.height - self.nodeSize
- self.nodes.unshift(new AsphyreNode(self.nodes[0].x, varluable, self.nodeSize, self.nodeSize));
- self.nodes.pop();
- break;
- case 1: //下
- if(self.nodes[0].equals(self.farm.food)) {//吃到食物,少走一步
- self.farm.food.y += self.nodeSize
- self.eatFood();
- self.farm.repaint(self);
- return;
- }
- var varluable = self.nodes[0].y + self.nodeSize;
- if(varluable > self.farm.farmElem.height - self.nodeSize)
- varluable = 0;
- self.nodes.unshift(new AsphyreNode(self.nodes[0].x, varluable, self.nodeSize, self.nodeSize));
- self.nodes.pop();
- break;
- case -10: //左
- if(self.nodes[0].equals(self.farm.food)) {//吃到食物,少走一步
- self.farm.food.x -= self.nodeSize
- self.eatFood();
- self.farm.repaint(self);
- return;
- }
- var varluable = self.nodes[0].x - self.nodeSize;
- if(varluable < 0)
- varluable = self.farm.farmElem.width - self.nodeSize;
- self.nodes.unshift(new AsphyreNode(varluable, self.nodes[0].y, self.nodeSize, self.nodeSize));
- self.nodes.pop();
- break;
- case 10: //右
- if(self.nodes[0].equals(self.farm.food)) {//吃到食物,少走一步
- self.farm.food.x += self.nodeSize
- self.eatFood();
- self.farm.repaint(self);
- return;
- }
- var varluable = self.nodes[0].x + self.nodeSize;
- if(varluable > self.farm.farmElem.width - self.nodeSize)
- varluable = 0;
- self.nodes.unshift(new AsphyreNode(varluable, self.nodes[0].y, self.nodeSize, self.nodeSize));
- self.nodes.pop();
- break;
- }
- self.farm.repaint(self);
- for(var i = 1; i < self.nodes.length; i ++) {
- if(self.nodes[0].equals(self.nodes)) {//吃到身体,死亡
- self.die();
- break;
- }
- }
- },
- refreshSpeed: function() { //吃到食物后调整速度的算法
- var self = this;
- this.speed = Math.round(this.speedParam / this.nodes.length);
- self.stop();
- self.continueRun();
- },
- die: function() { //蛇咬到自己死了
- var self = this, context = this.farm.context;
- self.pause();
- document.getElementById("pause").disabled = true;
- document.getElementById("continue").disabled = true;
- document.getElementById("stop").disabled = true;
- self.drawOver(context);
- },
- drawOver: function(context) {
- context.save();
- context.font="60px impact";
- context.fillStyle="#000000";
- context.textAlign="center";
- context.fillText("GAME OVER!",250,250);
- }
- };
- var Farm = function(farmId){ //对农场的描述,相当于实现农场类
- this.farmElem = document.getElementById(farmId);
- this.context = this.farmElem.getContext("2d");
- this.food = null;
- this.init();
- };
- Farm.prototype = {
- init: function(){ //初始化农场
- var self = this, farm = this.farmElem, context = this.context;
- var w = farm.width,h = farm.height;
- context.fillStyle = "#E8FFFF";
- context.strokeStyle = "#000000";
- context.fillRect(0, 0, w, h);
- context.strokeRect(0, 0, w, h)
- },
- clear: function() { //清理农场
- var self = this, farm = this.farmElem, context = this.context;
- var w = farm.width,h = farm.height;
- context.fillStyle = "#E8FFFF";
- context.strokeStyle = "#000000";
- context.fillRect(0, 0, w, h);
- context.strokeRect(0, 0, w, h)
- },
- repaint: function(snake) { //重绘农场
- var self = this;
- self.clear();
- self.drowFood(snake);
- snake.drawNodes(snake.farm.context);
- },
- newFood: function(snake) { //农场为蛇生成食物
- var x,y;
- var flag = true;
- k:
- while(flag) {
- x = Math.round(Math.random() * (this.farmElem.width-10) / 10) * 10;
- y = Math.round(Math.random() * (this.farmElem.height-10) / 10) * 10;
- for(var i = 0; i < snake.nodes.length; i ++) {
- if(snake.nodes.x === x && snake.nodes.y === y){//食物在蛇的身体上
- break k;
- }
- }
- flag = false;
- }
- return new AsphyreNode(x, y, snake.nodeSize, snake.nodeSize);
- },
- drowFood: function() { //为毒蛇画饼
- this.context.fillStyle = "#FEF045";
- this.context.strokeStyle = "#ffffff";
- this.context.fillRect(this.food.x, this.food.y, this.food.w, this.food.h);
- this.context.strokeRect(this.food.x, this.food.y, this.food.w, this.food.h);
- }
- }
- var Game = function(){ //主程序,用于启动游戏
- this.snake = new Asphyre(new Farm("canvas"), 200, 200, 500, 5);
- };
- Game.prototype = {
- start: function(){
- this.snake.start();
- },
- stop: function() {
- this.snake.stop();
- },
- pause: function() {
- this.snake.pause();
- },
- continueRun: function() {
- this.snake.continueRun();
- }
- }
- </script>
- </head>
- <body>
- <div id="wrapper" style="text-align: center;">
- <canvas id="canvas" width="500"height="500"></canvas><br/>
- <input type="button" value="新游戏" id="start"/>
- <input type="button" value="继续" id="continue" disabled="true"/>
- <input type="button" value="结束" id="stop" disabled="true"/>
- <input type="button" value="暂停" id="pause" disabled="true"/>
- </div>
- <script>
- var game = new Game();
- document.getElementById("start").onclick = function(){
- game.start();
- document.getElementById("continue").disabled = true;
- document.getElementById("pause").disabled = false;
- document.getElementById("stop").disabled = false;
- };
- document.getElementById("stop").onclick = function(){
- game.stop();
- document.getElementById("start").disabled = false;
- document.getElementById("pause").disabled = true;
- document.getElementById("continue").disabled = true;
- this.disabled = true;
- };
- document.getElementById("pause").onclick = function(){
- game.pause();
- document.getElementById("stop").disabled = true;
- document.getElementById("continue").disabled = false;
- document.getElementById("start").disabled = false;
- this.disabled = true;
- };
- document.getElementById("continue").onclick = function(){
- game.continueRun();
- this.disabled = true;
- document.getElementById("stop").disabled = false;
- document.getElementById("start").disabled = false;
- document.getElementById("pause").disabled = false;
- };
- </script>
- </body>
- </html>