维苏威的血

使用TypeScript实现简单的HTML5贪吃蛇游戏

  TypeScript是一种由微软开发的自由开源的编程语言。它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程安德斯·海尔斯伯格C#的首席架构师,已工作于TypeScript的开发。2012年十月份,微软发布了首个公开版本的TypeScript,2013年6月19日,在经历了一个预览版之后微软正式发布了正式版TypeScript
0.9,向未来的TypeScript 1.0版迈进了很大一步。——摘自百度百科

  我个人感觉这个最大的优势就是建模比较方便了,因为它通过对JS的扩充实现了类、接口、枚举等(都是编译器在干活),感觉它把一些C#的语法加进去了,从而简化了大型JS应用程序的开发。

  对于使用VS2012/2013的开发者来说,需要下载一个插件才行,地址如下:http://www.microsoft.com/en-us/download/details.aspx?id=34790

  代码比较简单,直接上代码了,希望对typescript有兴趣的大牛给点建议吧。

   下面是typescript源码,typescript源文件默认后缀为.ts,在HTML页面引用这个文件的时候需要使用后缀为.js,在请求该脚本文件时,编译器会把typescript代码编译为其等价的JavaScript代码,并保证其兼容性(官方说法,没有验证)。

  1 //方向类,方向数值和键盘方向键一致
  2 enum Direction {
  3     Up= 38,
  4     Down= 40,
  5     Right= 39,
  6     Left= 37
  7 }
  8 
  9 //贪吃蛇类
 10 class Snake {
 11     //当前运动方向
 12     direction: Direction;
 13     //蛇位置数组
 14     body: number[] = [];
 15     //在移动蛇
 16     move() {
 17         var i = 0;
 18         for (; i < this.body.length - 1; i++) {
 19             this.body[i] = this.body[i + 1];
 20         }
 21         //根据方向计算蛇头位置
 22         var cubeNumber = new Game().cubeNumber;
 23         var y = parseInt(this.body[i] / cubeNumber + "");
 24         var x = this.body[i] - y * cubeNumber;
 25         switch (this.direction) {
 26             case Direction.Up:
 27                 this.body[i] = (y - 1) * cubeNumber + x;
 28                 break;
 29             case Direction.Down:
 30                 this.body[i] = (y + 1) * cubeNumber + x;
 31                 break;
 32             case Direction.Right:
 33                 this.body[i] = y * cubeNumber + x + 1;
 34                 break;
 35             case Direction.Left:
 36                 this.body[i] = y * cubeNumber + x - 1;
 37                 break;
 38         }
 39     }
 40 }
 41 
 42 class Game {
 43     canvas: HTMLCanvasElement;
 44     Width: number = 602;
 45     Height: number = 602;
 46     cubeWidth: number = 30;
 47     cubeNumber: number = 20;
 48     wallNum: number = -1;
 49     comNum: number = 0;
 50     snakeNum: number = 1;
 51     frogNum:number = 2;
 52     boardArray: number[] = [];
 53     snake: Snake;
 54     wallColor: string = "#cccccc";
 55     snakeColor: string = "#000000";
 56     comColor: string = "#ffffff";
 57     frogColor: string = "#00cc33";
 58 
 59     snakeMoveInterval: number;
 60     frogInterval: number;
 61     moveInterval:number = 1000;
 62 
 63     //初始化贪吃蛇界面(本贪吃蛇比较简单,只有一个canvas)
 64     initialUI() {
 65         //创建canvas并设置格式
 66         this.canvas = document.createElement("canvas");
 67         this.canvas.height = this.Height;
 68         this.canvas.width = this.Width;
 69         this.canvas.style.margin = "30px auto auto auto";
 70         //this.canvas.style.border = "1px solid red";
 71         document.body.style.margin = "0px";
 72         document.body.style.textAlign = "center";
 73         document.body.appendChild(this.canvas);
 74     }
 75     //在(x,y)坐标处绘制一块墙
 76     drawWall(x: number, y: number) {
 77         var ctx = this.canvas.getContext("2d");
 78         ctx.fillStyle = this.wallColor;
 79         //alert("(x,y)=>(" + (this.cubeWidth * x) + "," + (this.cubeWidth * y) + ")");
 80         //(x,y)各加0.5用来修正位置
 81         ctx.fillRect(x * this.cubeWidth + 0.5, y * this.cubeWidth + 0.5, this.cubeWidth - 1, this.cubeWidth - 1);
 82     }
 83 
 84     //初始化一条蛇(此处简化处理了)
 85     initialSnake() {
 86         this.snake = new Snake();
 87         this.snake.direction = Direction.Right;
 88         for (var i = 0; i < 4; i++) {
 89             //从第二行开始位置设置一条向右运动的蛇
 90             this.snake.body.push(this.cubeNumber + 1 + i);
 91         }
 92     }
 93 
 94     //绘制蛇
 95     drawSnake() {
 96         //遍历蛇身
 97         var ctx = this.canvas.getContext("2d");
 98         ctx.fillStyle = this.snakeColor;
 99         for (var i = 0; i < this.snake.body.length; i++) {
100             //计算坐标
101             var y = parseInt(this.snake.body[i] / this.cubeNumber + "");
102             var x = this.snake.body[i] - y * this.cubeNumber;
103             ctx.fillRect(x * this.cubeWidth + 0.5, y * this.cubeWidth + 0.5, this.cubeWidth - 1, this.cubeWidth - 1);
104         }
105     }
106 
107     //清除蛇
108     eraseSnake() {
109         var ctx = this.canvas.getContext("2d");
110         ctx.fillStyle = this.comColor;
111         for (var i = 0; i < this.snake.body.length; i++) {
112             var y = parseInt(this.snake.body[i] / this.cubeNumber + "");
113             var x = this.snake.body[i] - y * this.cubeNumber;
114             ctx.fillRect(x * this.cubeWidth + 0.5, y * this.cubeWidth + 0.5, this.cubeWidth - 1, this.cubeWidth - 1);
115         }
116     }
117 
118     //检查蛇的位置状态
119     checkSnake() {
120 
121         var head = this.snake.body[this.snake.body.length - 1];
122         //如果蛇头在墙上,则弹出蛇已经死亡的消息
123         if (this.boardArray[head] == this.wallNum) {
124             //停止蛇的移动
125             clearInterval(this.snakeMoveInterval);
126             alert("Your snake has gone !");
127         }
128         //如果蛇头位置在蛇身上
129         for (var i = 0; i < this.snake.body.length - 2; i++) {
130             if (this.snake.body[i] == head) {
131                 //停止蛇的移动
132                 clearInterval(this.snakeMoveInterval);
133                 alert("Your snake has gone !");
134             }
135         }
136 
137         //如果设的下一个位置是青蛙,则吃掉青蛙
138         //计算当前位置
139         var y = parseInt("" + head / this.cubeNumber);
140         var x = head - y * this.cubeNumber;
141         var next = 0;
142         //计算下一个位置
143         switch (this.snake.direction) {
144             case Direction.Up:
145                 next = head - this.cubeNumber;
146                 break;
147             case Direction.Down:
148                 next = head + this.cubeNumber;
149                 break;
150             case Direction.Right:
151                 next = head +1;
152                 break;
153             case Direction.Left:
154                 next = head - 1;
155                 break;
156         }
157         //如果是青蛙,吃掉青蛙
158         if (this.boardArray[next] == this.frogNum) {
159             this.boardArray[next] = this.comNum;
160             this.snake.body.push(next);
161             this.setFrog();
162         }
163     }
164     //绘制面板
165     drawBoard() {
166         var ctx = this.canvas.getContext("2d");
167         //画横线
168         ctx.beginPath();
169         ctx.translate(0.5, 0.5);
170         for (var y = 0; y <= this.cubeNumber; y++) {
171             ctx.moveTo(0, y * this.cubeWidth);
172             ctx.lineTo(this.cubeNumber * this.cubeWidth, y * this.cubeWidth);
173         }
174         //画竖线
175         for (var x = 0; x <= this.cubeNumber; x++) {
176             ctx.moveTo(x * this.cubeWidth, 0);
177             ctx.lineTo(x * this.cubeWidth, this.cubeNumber * this.cubeWidth);
178         }
179         ctx.stroke();
180 
181         //数学化面板,以行序存储
182         for (var y = 0; y < this.cubeNumber; y++) {
183             for (var x = 0; x < this.cubeNumber; x++) {
184                 //如果是四周,则设置值为墙的值
185                 if (x == 0 || y == 0 || x == this.cubeNumber - 1 || y == this.cubeNumber - 1) {
186                     this.boardArray.push(this.wallNum);
187                 } else {
188                     this.boardArray.push(this.comNum);
189                 }
190             }
191         }
192 
193         //遍历boardArray绘制其中表示墙的区域
194         for (var i = 0; i < this.boardArray.length; i++) {
195             if (this.boardArray[i] == this.wallNum) {
196                 var y = parseInt(i / this.cubeNumber + "");
197                 var x = i - y * this.cubeNumber;
198                 this.drawWall(x, y);
199             }
200         }
201 
202 
203     }
204     //随机设置一个位置为青蛙(保证青蛙不在墙上或蛇身上)
205     getRandomFrog() {
206         var position = parseInt(""+ Math.random() * this.boardArray.length);
207         if (this.boardArray[position] == this.wallNum) {
208             //递归
209             return this.getRandomFrog();
210         }
211         //检查是否在蛇身上
212         if (this.snake.body.indexOf(position) > -1) {
213             return this.getRandomFrog();
214         }
215         return position;
216     }
217 
218     //绘制青蛙
219     drawFrog(position) {
220         //计算x,y
221         var y = parseInt(position / this.cubeNumber + "");
222         var x = position - y * this.cubeNumber;
223         var ctx = this.canvas.getContext("2d");
224         ctx.fillStyle = this.frogColor;
225         ctx.fillRect(x * this.cubeWidth+0.5, y * this.cubeWidth+0.5, this.cubeWidth - 1, this.cubeWidth - 1);
226     }
227 
228     //声称青蛙
229     setFrog() {
230         var position = this.getRandomFrog();
231         //设置该区域为青蛙
232         this.boardArray[position] = this.frogNum;
233         //绘制青蛙
234         this.drawFrog(position);
235     }
236     //绑定键盘事件
237     bindKeyBoard() {
238         window.onkeydown = (e) => {
239             //如果和当前方向相反,无操作
240             if (e.keyCode+2!=this.snake.direction&&e.keyCode-2!=this.snake.direction) {
241                 //如果和当前方向相同
242                 if (e.keyCode == this.snake.direction) {
243                     if (this.moveInterval - 200 >= 200) {
244                         this.moveInterval -= 200;
245                         clearInterval(this.snakeMoveInterval);
246                         this.setSnakeMoveInterval();
247                     }
248                 } else {
249                     if (this.moveInterval + 200 <= 1000) {
250                         this.moveInterval += 200;
251                         clearInterval(this.snakeMoveInterval);
252                         this.setSnakeMoveInterval();
253                     }
254                 }
255                 this.snake.direction = e.keyCode;
256                 //检查蛇状态,吃掉青蛙
257                 this.checkSnake();
258                 this.drawSnake();
259             }
260         };
261     }
262 
263     //移动蛇
264     moveSnake() {
265         this.eraseSnake();
266         this.moveSnake();
267         this.checkSnake();
268         this.drawSnake();
269     }
270 
271     //设置贪吃蛇循环运动
272     setSnakeMoveInterval() {
273         clearInterval(this.snakeMoveInterval);
274         this.snakeMoveInterval = setInterval(() => {
275             this.eraseSnake();
276             this.snake.move();
277             this.checkSnake();
278             this.drawSnake();
279         },this.moveInterval);
280     }
281 
282     //开始游戏
283     start() {
284         this.initialUI();
285         this.drawBoard();
286         this.initialSnake();
287         this.drawSnake();
288         this.bindKeyBoard();
289         this.setSnakeMoveInterval();
290         this.setFrog();
291     }
292 }
293 
294 //window加载时启动游戏
295 window.onload = () => {
296     var game = new Game();
297     game.start();
298 }
299     
View Code

  下面是其编译后的JavaScript代码。

  1 //方向类,方向数值和键盘方向键一致
  2 var Direction;
  3 (function (Direction) {
  4     Direction[Direction["Up"] = 38] = "Up";
  5     Direction[Direction["Down"] = 40] = "Down";
  6     Direction[Direction["Right"] = 39] = "Right";
  7     Direction[Direction["Left"] = 37] = "Left";
  8 })(Direction || (Direction = {}));
  9 
 10 //贪吃蛇类
 11 var Snake = (function () {
 12     function Snake() {
 13         //蛇位置数组
 14         this.body = [];
 15     }
 16     //在移动蛇
 17     Snake.prototype.move = function () {
 18         var i = 0;
 19         for (; i < this.body.length - 1; i++) {
 20             this.body[i] = this.body[i + 1];
 21         }
 22 
 23         //根据方向计算蛇头位置
 24         var cubeNumber = new Game().cubeNumber;
 25         var y = parseInt(this.body[i] / cubeNumber + "");
 26         var x = this.body[i] - y * cubeNumber;
 27         switch (this.direction) {
 28             case 38 /* Up */:
 29                 this.body[i] = (y - 1) * cubeNumber + x;
 30                 break;
 31             case 40 /* Down */:
 32                 this.body[i] = (y + 1) * cubeNumber + x;
 33                 break;
 34             case 39 /* Right */:
 35                 this.body[i] = y * cubeNumber + x + 1;
 36                 break;
 37             case 37 /* Left */:
 38                 this.body[i] = y * cubeNumber + x - 1;
 39                 break;
 40         }
 41     };
 42     return Snake;
 43 })();
 44 
 45 var Game = (function () {
 46     function Game() {
 47         this.Width = 602;
 48         this.Height = 602;
 49         this.cubeWidth = 30;
 50         this.cubeNumber = 20;
 51         this.wallNum = -1;
 52         this.comNum = 0;
 53         this.snakeNum = 1;
 54         this.frogNum = 2;
 55         this.boardArray = [];
 56         this.wallColor = "#cccccc";
 57         this.snakeColor = "#000000";
 58         this.comColor = "#ffffff";
 59         this.frogColor = "#00cc33";
 60         this.moveInterval = 1000;
 61     }
 62     //初始化贪吃蛇界面(本贪吃蛇比较简单,只有一个canvas)
 63     Game.prototype.initialUI = function () {
 64         //创建canvas并设置格式
 65         this.canvas = document.createElement("canvas");
 66         this.canvas.height = this.Height;
 67         this.canvas.width = this.Width;
 68         this.canvas.style.margin = "30px auto auto auto";
 69 
 70         //this.canvas.style.border = "1px solid red";
 71         document.body.style.margin = "0px";
 72         document.body.style.textAlign = "center";
 73         document.body.appendChild(this.canvas);
 74     };
 75 
 76     //在(x,y)坐标处绘制一块墙
 77     Game.prototype.drawWall = function (x, y) {
 78         var ctx = this.canvas.getContext("2d");
 79         ctx.fillStyle = this.wallColor;
 80 
 81         //alert("(x,y)=>(" + (this.cubeWidth * x) + "," + (this.cubeWidth * y) + ")");
 82         //(x,y)各加0.5用来修正位置
 83         ctx.fillRect(x * this.cubeWidth + 0.5, y * this.cubeWidth + 0.5, this.cubeWidth - 1, this.cubeWidth - 1);
 84     };
 85 
 86     //初始化一条蛇(此处简化处理了)
 87     Game.prototype.initialSnake = function () {
 88         this.snake = new Snake();
 89         this.snake.direction = 39 /* Right */;
 90         for (var i = 0; i < 4; i++) {
 91             //从第二行开始位置设置一条向右运动的蛇
 92             this.snake.body.push(this.cubeNumber + 1 + i);
 93         }
 94     };
 95 
 96     //绘制蛇
 97     Game.prototype.drawSnake = function () {
 98         //遍历蛇身
 99         var ctx = this.canvas.getContext("2d");
100         ctx.fillStyle = this.snakeColor;
101         for (var i = 0; i < this.snake.body.length; i++) {
102             //计算坐标
103             var y = parseInt(this.snake.body[i] / this.cubeNumber + "");
104             var x = this.snake.body[i] - y * this.cubeNumber;
105             ctx.fillRect(x * this.cubeWidth + 0.5, y * this.cubeWidth + 0.5, this.cubeWidth - 1, this.cubeWidth - 1);
106         }
107     };
108 
109     //清除蛇
110     Game.prototype.eraseSnake = function () {
111         var ctx = this.canvas.getContext("2d");
112         ctx.fillStyle = this.comColor;
113         for (var i = 0; i < this.snake.body.length; i++) {
114             var y = parseInt(this.snake.body[i] / this.cubeNumber + "");
115             var x = this.snake.body[i] - y * this.cubeNumber;
116             ctx.fillRect(x * this.cubeWidth + 0.5, y * this.cubeWidth + 0.5, this.cubeWidth - 1, this.cubeWidth - 1);
117         }
118     };
119 
120     //检查蛇的位置状态
121     Game.prototype.checkSnake = function () {
122         var head = this.snake.body[this.snake.body.length - 1];
123 
124         //如果蛇头在墙上,则弹出蛇已经死亡的消息
125         if (this.boardArray[head] == this.wallNum) {
126             //停止蛇的移动
127             clearInterval(this.snakeMoveInterval);
128             alert("Your snake has gone !");
129         }
130 
131         for (var i = 0; i < this.snake.body.length - 2; i++) {
132             if (this.snake.body[i] == head) {
133                 //停止蛇的移动
134                 clearInterval(this.snakeMoveInterval);
135                 alert("Your snake has gone !");
136             }
137         }
138 
139         //如果设的下一个位置是青蛙,则吃掉青蛙
140         //计算当前位置
141         var y = parseInt("" + head / this.cubeNumber);
142         var x = head - y * this.cubeNumber;
143         var next = 0;
144 
145         switch (this.snake.direction) {
146             case 38 /* Up */:
147                 next = head - this.cubeNumber;
148                 break;
149             case 40 /* Down */:
150                 next = head + this.cubeNumber;
151                 break;
152             case 39 /* Right */:
153                 next = head + 1;
154                 break;
155             case 37 /* Left */:
156                 next = head - 1;
157                 break;
158         }
159 
160         //如果是青蛙,吃掉青蛙
161         if (this.boardArray[next] == this.frogNum) {
162             this.boardArray[next] = this.comNum;
163             this.snake.body.push(next);
164             this.setFrog();
165         }
166     };
167 
168     //绘制面板
169     Game.prototype.drawBoard = function () {
170         var ctx = this.canvas.getContext("2d");
171 
172         //画横线
173         ctx.beginPath();
174         ctx.translate(0.5, 0.5);
175         for (var y = 0; y <= this.cubeNumber; y++) {
176             ctx.moveTo(0, y * this.cubeWidth);
177             ctx.lineTo(this.cubeNumber * this.cubeWidth, y * this.cubeWidth);
178         }
179 
180         for (var x = 0; x <= this.cubeNumber; x++) {
181             ctx.moveTo(x * this.cubeWidth, 0);
182             ctx.lineTo(x * this.cubeWidth, this.cubeNumber * this.cubeWidth);
183         }
184         ctx.stroke();
185 
186         for (var y = 0; y < this.cubeNumber; y++) {
187             for (var x = 0; x < this.cubeNumber; x++) {
188                 //如果是四周,则设置值为墙的值
189                 if (x == 0 || y == 0 || x == this.cubeNumber - 1 || y == this.cubeNumber - 1) {
190                     this.boardArray.push(this.wallNum);
191                 } else {
192                     this.boardArray.push(this.comNum);
193                 }
194             }
195         }
196 
197         for (var i = 0; i < this.boardArray.length; i++) {
198             if (this.boardArray[i] == this.wallNum) {
199                 var y = parseInt(i / this.cubeNumber + "");
200                 var x = i - y * this.cubeNumber;
201                 this.drawWall(x, y);
202             }
203         }
204     };
205 
206     //随机设置一个位置为青蛙(保证青蛙不在墙上或蛇身上)
207     Game.prototype.getRandomFrog = function () {
208         var position = parseInt("" + Math.random() * this.boardArray.length);
209         if (this.boardArray[position] == this.wallNum) {
210             //递归
211             return this.getRandomFrog();
212         }
213 
214         //检查是否在蛇身上
215         if (this.snake.body.indexOf(position) > -1) {
216             return this.getRandomFrog();
217         }
218         return position;
219     };
220 
221     //绘制青蛙
222     Game.prototype.drawFrog = function (position) {
223         //计算x,y
224         var y = parseInt(position / this.cubeNumber + "");
225         var x = position - y * this.cubeNumber;
226         var ctx = this.canvas.getContext("2d");
227         ctx.fillStyle = this.frogColor;
228         ctx.fillRect(x * this.cubeWidth + 0.5, y * this.cubeWidth + 0.5, this.cubeWidth - 1, this.cubeWidth - 1);
229     };
230 
231     //声称青蛙
232     Game.prototype.setFrog = function () {
233         var position = this.getRandomFrog();
234 
235         //设置该区域为青蛙
236         this.boardArray[position] = this.frogNum;
237 
238         //绘制青蛙
239         this.drawFrog(position);
240     };
241 
242     //绑定键盘事件
243     Game.prototype.bindKeyBoard = function () {
244         var _this = this;
245         window.onkeydown = function (e) {
246             //如果和当前方向相反,无操作
247             if (e.keyCode + 2 != _this.snake.direction && e.keyCode - 2 != _this.snake.direction) {
248                 //如果和当前方向相同
249                 if (e.keyCode == _this.snake.direction) {
250                     if (_this.moveInterval - 200 >= 200) {
251                         _this.moveInterval -= 200;
252                         clearInterval(_this.snakeMoveInterval);
253                         _this.setSnakeMoveInterval();
254                     }
255                 } else {
256                     if (_this.moveInterval + 200 <= 1000) {
257                         _this.moveInterval += 200;
258                         clearInterval(_this.snakeMoveInterval);
259                         _this.setSnakeMoveInterval();
260                     }
261                 }
262                 _this.snake.direction = e.keyCode;
263 
264                 //检查蛇状态,吃掉青蛙
265                 _this.checkSnake();
266                 _this.drawSnake();
267             }
268         };
269     };
270 
271     //移动蛇
272     Game.prototype.moveSnake = function () {
273         this.eraseSnake();
274         this.moveSnake();
275         this.checkSnake();
276         this.drawSnake();
277     };
278 
279     //设置贪吃蛇循环运动
280     Game.prototype.setSnakeMoveInterval = function () {
281         var _this = this;
282         clearInterval(this.snakeMoveInterval);
283         this.snakeMoveInterval = setInterval(function () {
284             _this.eraseSnake();
285             _this.snake.move();
286             _this.checkSnake();
287             _this.drawSnake();
288         }, this.moveInterval);
289     };
290 
291     //开始游戏
292     Game.prototype.start = function () {
293         this.initialUI();
294         this.drawBoard();
295         this.initialSnake();
296         this.drawSnake();
297         this.bindKeyBoard();
298         this.setSnakeMoveInterval();
299         this.setFrog();
300     };
301     return Game;
302 })();
303 
304 //window加载时启动游戏
305 window.onload = function () {
306     var game = new Game();
307     game.start();
308 };
View Code

  

  效果图:

posted on 2014-01-04 13:57  天朝愚民  阅读(2897)  评论(0编辑  收藏  举报

导航