简单的网页游戏之贪吃蛇

上课无聊?来一把贪吃蛇游戏吧!

<!DOCTYPE html>
<HTML>
	<HEAD>
		<TITLE></TITLE>
		<style type="text/css">
			* {
				box-sizing: border-box;
			}

			html,
			body {
				background-color: #000;
				height: 100%;
			}

			body {
				background: #222;
				background: radial-gradient(#333, #111);
				background-position: center center;
				background-repeat: no-repeat;
				background-size: cover;
				color: #fff;
				font: 100%/1.5 sans-serif;
				overflow: hidden;
			}

			.score {
				color: rgba(255, 255, 255, 0.5);
				font-size: 16px;
				font-weight: bold;
				padding-top: 5px;
				text-align: center;
			}

			.stage {
				bottom: 0;
				left: 0;
				margin: auto;
				position: absolute;
				right: 0;
				top: 0;
				z-index: 2;
			}

			.tile {
				background: rgba(0, 0, 0, 0.15);
				position: absolute;
				transition-property: background, box-shadow, opacity, transform;
				transform: translateZ(0);
				transition-duration: 3000ms;
			}

			.tile:before {
				bottom: 0;
				content: "";
				height: 0;
				left: 0;
				margin: auto;
				opacity: 0;
				position: absolute;
				right: 0;
				top: 0;
				width: 0;
				transition: opacity 300ms;
			}

			.tile.path:before {
				opacity: 1;
			}

			.tile.up:before {
				border-bottom: 4px inset rgba(255, 255, 255, 0.15);
				border-left: 4px solid transparent;
				border-right: 4px solid transparent;
			}

			.tile.down:before {
				border-top: 4px inset rgba(255, 255, 255, 0.15);
				border-left: 4px solid transparent;
				border-right: 4px solid transparent;
			}

			.tile.left:before {
				border-right: 4px inset rgba(255, 255, 255, 0.15);
				border-top: 4px solid transparent;
				border-bottom: 4px solid transparent;
			}

			.tile.right:before {
				border-left: 4px inset rgba(255, 255, 255, 0.15);
				border-top: 4px solid transparent;
				border-bottom: 4px solid transparent;
			}

			@media (max-width: 900px),
			(max-height: 900px) {

				.tile.up:before,
				.tile.down:before,
				.tile.left:before,
				.tile.right:before {
					border-width: 3px;
				}
			}

			@media (max-width: 500px),
			(max-height: 500px) {

				.tile.up:before,
				.tile.down:before,
				.tile.left:before,
				.tile.right:before {
					border-width: 2px;
				}
			}

			.tile.pressed {
				background: rgba(0, 0, 0, 0.3);
				box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.6);
				transition-duration: 0ms;
			}
		</style>
	</head>
	<body>
		<div class="score">0</div>
		<div class="stage"></div>
		<script type="text/javascript">
			(function() {
				"use strict";
				var lastTime = 0;
				var vendors = ["webkit", "moz"];
				for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
					window.requestAnimationFrame = window[vendors[x] + "RequestAnimationFrame"];
					window.cancelAnimationFrame =
						window[vendors[x] + "CancelAnimationFrame"] ||
						window[vendors[x] + "CancelRequestAnimationFrame"];
				}
				if (!window.requestAnimationFrame) {
					window.requestAnimationFrame = function(callback, element) {
						var currTime = new Date().getTime();
						var timeToCall = Math.max(0, 16 - (currTime - lastTime));
						var id = window.setTimeout(function() {
							callback(currTime + timeToCall);
						}, timeToCall);
						lastTime = currTime + timeToCall;
						return id;
					};
				}
				if (!window.cancelAnimationFrame) {
					window.cancelAnimationFrame = function(id) {
						clearTimeout(id);
					};
				}
			})();
			(function() {
				"use strict";

				function hasClass(elem, className) {
					return new RegExp(" " + className + " ").test(" " + elem.className + " ");
				}

				function addClass(elem, className) {
					if (!hasClass(elem, className)) {
						elem.className += " " + className;
					}
				}

				function removeClass(elem, className) {
					var newClass = " " + elem.className.replace(/[\t\r\n]/g, " ") + " ";
					if (hasClass(elem, className)) {
						while (newClass.indexOf(" " + className + " ") >= 0) {
							newClass = newClass.replace(" " + className + " ", " ");
						}
						elem.className = newClass.replace(/^\s+|\s+$/g, "");
					}
				}

				function toggleClass(elem, className) {
					var newClass = " " + elem.className.replace(/[\t\r\n]/g, " ") + " ";
					if (hasClass(elem, className)) {
						while (newClass.indexOf(" " + className + " ") >= 0) {
							newClass = newClass.replace(" " + className + " ", " ");
						}
						elem.className = newClass.replace(/^\s+|\s+$/g, "");
					} else {
						elem.className += " " + className;
					}
				}
			})();
			g = {};

			(function() {
				"use strict";

				g.m = Math;
				g.mathProps =
					"E LN10 LN2 LOG2E LOG10E PI SQRT1_2 SQRT2 abs acos asin atan ceil cos exp floor log round sin sqrt tan atan2 pow max min"
					.split(
						" "
					);
				for (var i = 0; i < g.mathProps.length; i++) {
					g[g.mathProps[i]] = g.m[g.mathProps[i]];
				}
				g.m.TWO_PI = g.m.PI * 2;

				g.isset = function(prop) {
					return typeof prop != "undefined";
				};

				g.log = function() {
					if (g.isset(g.config) && g.config.debug && window.console) {
						console.log(Array.prototype.slice.call(arguments));
					}
				};
			})();

			(function() {
				"use strict";

				g.Group = function() {
					this.collection = [];
					this.length = 0;
				};

				g.Group.prototype.add = function(item) {
					this.collection.push(item);
					this.length++;
				};

				g.Group.prototype.remove = function(index) {
					if (index < this.length) {
						this.collection.splice(index, 1);
						this.length--;
					}
				};

				g.Group.prototype.empty = function() {
					this.collection.length = 0;
					this.length = 0;
				};

				g.Group.prototype.each = function(action, asc) {
					var asc = asc || 0,
						i;
					if (asc) {
						for (i = 0; i < this.length; i++) {
							this.collection[i][action](i);
						}
					} else {
						i = this.length;
						while (i--) {
							this.collection[i][action](i);
						}
					}
				};
			})();

			(function() {
				"use strict";

				g.util = {};

				g.util.rand = function(min, max) {
					return g.m.random() * (max - min) + min;
				};

				g.util.randInt = function(min, max) {
					return g.m.floor(g.m.random() * (max - min + 1)) + min;
				};
			})();

			(function() {
				"use strict";

				g.states = {};

				g.addState = function(state) {
					g.states[state.name] = state;
				};

				g.setState = function(name) {
					if (g.state) {
						g.states[g.state].exit();
					}
					g.state = name;
					g.states[g.state].init();
				};

				g.currentState = function() {
					return g.states[g.state];
				};
			})();

			(function() {
				"use strict";

				g.Time = function() {
					this.reset();
				};

				g.Time.prototype.reset = function() {
					this.now = Date.now();
					this.last = Date.now();
					this.delta = 60;
					this.ndelta = 1;
					this.elapsed = 0;
					this.nelapsed = 0;
					this.tick = 0;
				};

				g.Time.prototype.update = function() {
					this.now = Date.now();
					this.delta = this.now - this.last;
					this.ndelta = Math.min(Math.max(this.delta / (1000 / 60), 0.0001), 10);
					this.elapsed += this.delta;
					this.nelapsed += this.ndelta;
					this.last = this.now;
					this.tick++;
				};
			})();

			(function() {
				"use strict";

				g.Grid = function(cols, rows) {
					this.cols = cols;
					this.rows = rows;
					this.tiles = [];
					for (var x = 0; x < cols; x++) {
						this.tiles[x] = [];
						for (var y = 0; y < rows; y++) {
							this.tiles[x].push("empty");
						}
					}
				};

				g.Grid.prototype.get = function(x, y) {
					return this.tiles[x][y];
				};

				g.Grid.prototype.set = function(x, y, val) {
					this.tiles[x][y] = val;
				};
			})();

			(function() {
				"use strict";

				g.BoardTile = function(opt) {
					this.parentState = opt.parentState;
					this.parentGroup = opt.parentGroup;
					this.col = opt.col;
					this.row = opt.row;
					this.x = opt.x;
					this.y = opt.y;
					this.z = 0;
					this.w = opt.w;
					this.h = opt.h;
					this.elem = document.createElement("div");
					this.elem.style.position = "absolute";
					this.elem.className = "tile";
					this.parentState.stageElem.appendChild(this.elem);
					this.classes = {
						pressed: 0,
						path: 0,
						up: 0,
						down: 0,
						left: 0,
						right: 0
					};
					this.updateDimensions();
				};

				g.BoardTile.prototype.update = function() {
					for (var k in this.classes) {
						if (this.classes[k]) {
							this.classes[k]--;
						}
					}

					if (
						this.parentState.food.tile.col == this.col ||
						this.parentState.food.tile.row == this.row
					) {
						this.classes.path = 1;
						if (this.col < this.parentState.food.tile.col) {
							this.classes.right = 1;
						} else {
							this.classes.right = 0;
						}
						if (this.col > this.parentState.food.tile.col) {
							this.classes.left = 1;
						} else {
							this.classes.left = 0;
						}
						if (this.row > this.parentState.food.tile.row) {
							this.classes.up = 1;
						} else {
							this.classes.up = 0;
						}
						if (this.row < this.parentState.food.tile.row) {
							this.classes.down = 1;
						} else {
							this.classes.down = 0;
						}
					} else {
						this.classes.path = 0;
					}

					if (this.parentState.food.eaten) {
						this.classes.path = 0;
					}
				};

				g.BoardTile.prototype.updateDimensions = function() {
					this.x = this.col * this.parentState.tileWidth;
					this.y = this.row * this.parentState.tileHeight;
					this.w = this.parentState.tileWidth - this.parentState.spacing;
					this.h = this.parentState.tileHeight - this.parentState.spacing;
					this.elem.style.left = this.x + "px";
					this.elem.style.top = this.y + "px";
					this.elem.style.width = this.w + "px";
					this.elem.style.height = this.h + "px";
				};

				g.BoardTile.prototype.render = function() {
					var classString = "";
					for (var k in this.classes) {
						if (this.classes[k]) {
							classString += k + " ";
						}
					}
					this.elem.className = "tile " + classString;
				};
			})();

			(function() {
				"use strict";

				g.SnakeTile = function(opt) {
					this.parentState = opt.parentState;
					this.parentGroup = opt.parentGroup;
					this.col = opt.col;
					this.row = opt.row;
					this.x = opt.x;
					this.y = opt.y;
					this.w = opt.w;
					this.h = opt.h;
					this.color = null;
					this.scale = 1;
					this.rotation = 0;
					this.blur = 0;
					this.alpha = 1;
					this.borderRadius = 0;
					this.borderRadiusAmount = 0;
					this.elem = document.createElement("div");
					this.elem.style.position = "absolute";
					this.parentState.stageElem.appendChild(this.elem);
				};

				g.SnakeTile.prototype.update = function(i) {
					this.x = this.col * this.parentState.tileWidth;
					this.y = this.row * this.parentState.tileHeight;
					if (i == 0) {
						this.color = "#fff";
						this.blur =
							this.parentState.dimAvg * 0.03 +
							Math.sin(this.parentState.time.elapsed / 200) *
							this.parentState.dimAvg *
							0.015;
						if (this.parentState.snake.dir == "n") {
							this.borderRadius =
								this.borderRadiusAmount + "% " + this.borderRadiusAmount + "% 0 0";
						} else if (this.parentState.snake.dir == "s") {
							this.borderRadius =
								"0 0 " +
								this.borderRadiusAmount +
								"% " +
								this.borderRadiusAmount +
								"%";
						} else if (this.parentState.snake.dir == "e") {
							this.borderRadius =
								"0 " +
								this.borderRadiusAmount +
								"% " +
								this.borderRadiusAmount +
								"% 0";
						} else if (this.parentState.snake.dir == "w") {
							this.borderRadius =
								this.borderRadiusAmount + "% 0 0 " + this.borderRadiusAmount + "%";
						}
					} else {
						this.color = "#fff";
						this.blur = 0;
						this.borderRadius = "0";
					}
					this.alpha = 1 - i / this.parentState.snake.tiles.length * 0.6;
					this.rotation =
						this.parentState.snake.justAteTick /
						this.parentState.snake.justAteTickMax *
						90;
					this.scale =
						1 +
						this.parentState.snake.justAteTick /
						this.parentState.snake.justAteTickMax *
						1;
				};

				g.SnakeTile.prototype.updateDimensions = function() {
					this.w = this.parentState.tileWidth - this.parentState.spacing;
					this.h = this.parentState.tileHeight - this.parentState.spacing;
				};

				g.SnakeTile.prototype.render = function(i) {
					this.elem.style.left = this.x + "px";
					this.elem.style.top = this.y + "px";
					this.elem.style.width = this.w + "px";
					this.elem.style.height = this.h + "px";
					this.elem.style.backgroundColor = "rgba(255, 255, 255, " + this.alpha + ")";
					this.elem.style.boxShadow = "0 0 " + this.blur + "px #fff";
					this.elem.style.borderRadius = this.borderRadius;
				};
			})();

			(function() {
				"use strict";

				g.FoodTile = function(opt) {
					this.parentState = opt.parentState;
					this.parentGroup = opt.parentGroup;
					this.col = opt.col;
					this.row = opt.row;
					this.x = opt.x;
					this.y = opt.y;
					this.w = opt.w;
					this.h = opt.h;
					this.blur = 0;
					this.scale = 1;
					this.hue = 100;
					this.opacity = 0;
					this.elem = document.createElement("div");
					this.elem.style.position = "absolute";
					this.parentState.stageElem.appendChild(this.elem);
				};

				g.FoodTile.prototype.update = function() {
					this.x = this.col * this.parentState.tileWidth;
					this.y = this.row * this.parentState.tileHeight;
					this.blur =
						this.parentState.dimAvg * 0.03 +
						Math.sin(this.parentState.time.elapsed / 200) *
						this.parentState.dimAvg *
						0.015;
					this.scale = 0.8 + Math.sin(this.parentState.time.elapsed / 200) * 0.2;

					if (this.parentState.food.birthTick || this.parentState.food.deathTick) {
						if (this.parentState.food.birthTick) {
							this.opacity = 1 - this.parentState.food.birthTick / 1 * 1;
						} else {
							this.opacity = this.parentState.food.deathTick / 1 * 1;
						}
					} else {
						this.opacity = 1;
					}
				};

				g.FoodTile.prototype.updateDimensions = function() {
					this.w = this.parentState.tileWidth - this.parentState.spacing;
					this.h = this.parentState.tileHeight - this.parentState.spacing;
				};

				g.FoodTile.prototype.render = function() {
					this.elem.style.left = this.x + "px";
					this.elem.style.top = this.y + "px";
					this.elem.style.width = this.w + "px";
					this.elem.style.height = this.h + "px";
					this.elem.style["transform"] = "translateZ(0) scale(" + this.scale + ")";
					this.elem.style.backgroundColor = "hsla(" + this.hue + ", 100%, 60%, 1)";
					this.elem.style.boxShadow =
						"0 0 " + this.blur + "px hsla(" + this.hue + ", 100%, 60%, 1)";
					this.elem.style.opacity = this.opacity;
				};
			})();

			(function() {
				"use strict";

				g.Snake = function(opt) {
					this.parentState = opt.parentState;
					(this.dir = "e"), (this.currDir = this.dir);
					this.tiles = [];
					for (var i = 0; i < 5; i++) {
						this.tiles.push(
							new g.SnakeTile({
								parentState: this.parentState,
								parentGroup: this.tiles,
								col: 8 - i,
								row: 3,
								x: (8 - i) * opt.parentState.tileWidth,
								y: 3 * opt.parentState.tileHeight,
								w: opt.parentState.tileWidth - opt.parentState.spacing,
								h: opt.parentState.tileHeight - opt.parentState.spacing
							})
						);
					}
					this.last = 0;
					this.updateTick = 10;
					this.updateTickMax = this.updateTick;
					this.updateTickLimit = 3;
					this.updateTickChange = 0.2;
					this.deathFlag = 0;
					this.justAteTick = 0;
					this.justAteTickMax = 1;
					this.justAteTickChange = 0.05;

					var i = this.tiles.length;

					while (i--) {
						this.parentState.grid.set(this.tiles[i].col, this.tiles[i].row, "snake");
					}
				};

				g.Snake.prototype.updateDimensions = function() {
					var i = this.tiles.length;
					while (i--) {
						this.tiles[i].updateDimensions();
					}
				};

				g.Snake.prototype.update = function() {
					if (this.parentState.keys.up) {
						if (
							this.dir != "s" &&
							this.dir != "n" &&
							this.currDir != "s" &&
							this.currDir != "n"
						) {
							this.dir = "n";
						}
					} else if (this.parentState.keys.down) {
						if (
							this.dir != "n" &&
							this.dir != "s" &&
							this.currDir != "n" &&
							this.currDir != "s"
						) {
							this.dir = "s";
						}
					} else if (this.parentState.keys.right) {
						if (
							this.dir != "w" &&
							this.dir != "e" &&
							this.currDir != "w" &&
							this.currDir != "e"
						) {
							this.dir = "e";
						}
					} else if (this.parentState.keys.left) {
						if (
							this.dir != "e" &&
							this.dir != "w" &&
							this.currDir != "e" &&
							this.currDir != "w"
						) {
							this.dir = "w";
						}
					}

					this.parentState.keys.up = 0;
					this.parentState.keys.down = 0;
					this.parentState.keys.right = 0;
					this.parentState.keys.left = 0;

					this.updateTick += this.parentState.time.ndelta;
					if (this.updateTick >= this.updateTickMax) {
						this.updateTick = this.updateTick - this.updateTickMax;
						this.tiles.unshift(
							new g.SnakeTile({
								parentState: this.parentState,
								parentGroup: this.tiles,
								col: this.tiles[0].col,
								row: this.tiles[0].row,
								x: this.tiles[0].col * this.parentState.tileWidth,
								y: this.tiles[0].row * this.parentState.tileHeight,
								w: this.parentState.tileWidth - this.parentState.spacing,
								h: this.parentState.tileHeight - this.parentState.spacing
							})
						);
						this.last = this.tiles.pop();
						this.parentState.stageElem.removeChild(this.last.elem);

						this.parentState.boardTiles.collection[
							this.last.col + this.last.row * this.parentState.cols
						].classes.pressed = 2;
						var i = this.tiles.length;

						while (i--) {
							this.parentState.grid.set(
								this.tiles[i].col,
								this.tiles[i].row,
								"snake"
							);
						}
						this.parentState.grid.set(this.last.col, this.last.row, "empty");

						if (this.dir == "n") {
							this.currDir = "n";
							this.tiles[0].row -= 1;
						} else if (this.dir == "s") {
							this.currDir = "s";
							this.tiles[0].row += 1;
						} else if (this.dir == "w") {
							this.currDir = "w";
							this.tiles[0].col -= 1;
						} else if (this.dir == "e") {
							this.currDir = "e";
							this.tiles[0].col += 1;
						}

						this.wallFlag = false;
						if (this.tiles[0].col >= this.parentState.cols) {
							this.tiles[0].col = 0;
							this.wallFlag = true;
						}
						if (this.tiles[0].col < 0) {
							this.tiles[0].col = this.parentState.cols - 1;
							this.wallFlag = true;
						}
						if (this.tiles[0].row >= this.parentState.rows) {
							this.tiles[0].row = 0;
							this.wallFlag = true;
						}
						if (this.tiles[0].row < 0) {
							this.tiles[0].row = this.parentState.rows - 1;
							this.wallFlag = true;
						}

						if (
							this.parentState.grid.get(this.tiles[0].col, this.tiles[0].row) ==
							"snake"
						) {
							this.deathFlag = 1;
							clearTimeout(this.foodCreateTimeout);
						}

						if (
							this.parentState.grid.get(this.tiles[0].col, this.tiles[0].row) ==
							"food"
						) {
							this.tiles.push(
								new g.SnakeTile({
									parentState: this.parentState,
									parentGroup: this.tiles,
									col: this.last.col,
									row: this.last.row,
									x: this.last.col * this.parentState.tileWidth,
									y: this.last.row * this.parentState.tileHeight,
									w: this.parentState.tileWidth - this.parentState.spacing,
									h: this.parentState.tileHeight - this.parentState.spacing
								})
							);
							if (this.updateTickMax - this.updateTickChange > this.updateTickLimit) {
								this.updateTickMax -= this.updateTickChange;
							}
							this.parentState.score++;
							this.parentState.scoreElem.innerHTML = this.parentState.score;
							this.justAteTick = this.justAteTickMax;

							this.parentState.food.eaten = 1;
							this.parentState.stageElem.removeChild(this.parentState.food.tile.elem);

							var _this = this;

							this.foodCreateTimeout = setTimeout(function() {
								_this.parentState.food = new g.Food({
									parentState: _this.parentState
								});
							}, 300);
						}

						if (this.deathFlag) {
							g.setState("play");
						}
					}

					var i = this.tiles.length;
					while (i--) {
						this.tiles[i].update(i);
					}

					if (this.justAteTick > 0) {
						this.justAteTick -= this.justAteTickChange;
					} else if (this.justAteTick < 0) {
						this.justAteTick = 0;
					}
				};

				g.Snake.prototype.render = function() {
					var i = this.tiles.length;
					while (i--) {
						this.tiles[i].render(i);
					}
				};
			})();

			(function() {
				"use strict";

				g.Food = function(opt) {
					this.parentState = opt.parentState;
					this.tile = new g.FoodTile({
						parentState: this.parentState,
						col: 0,
						row: 0,
						x: 0,
						y: 0,
						w: opt.parentState.tileWidth - opt.parentState.spacing,
						h: opt.parentState.tileHeight - opt.parentState.spacing
					});
					this.reset();
					this.eaten = 0;
					this.birthTick = 1;
					this.deathTick = 0;
					this.birthTickChange = 0.025;
					this.deathTickChange = 0.05;
				};

				g.Food.prototype.reset = function() {
					var empty = [];
					for (var x = 0; x < this.parentState.cols; x++) {
						for (var y = 0; y < this.parentState.rows; y++) {
							var tile = this.parentState.grid.get(x, y);
							if (tile == "empty") {
								empty.push({
									x: x,
									y: y
								});
							}
						}
					}
					var newTile = empty[g.util.randInt(0, empty.length - 1)];
					this.tile.col = newTile.x;
					this.tile.row = newTile.y;
				};

				g.Food.prototype.updateDimensions = function() {
					this.tile.updateDimensions();
				};

				g.Food.prototype.update = function() {
					this.tile.update();

					if (this.birthTick > 0) {
						this.birthTick -= this.birthTickChange;
					} else if (this.birthTick < 0) {
						this.birthTick = 0;
					}

					this.parentState.grid.set(this.tile.col, this.tile.row, "food");
				};

				g.Food.prototype.render = function() {
					this.tile.render();
				};
			})();

			(function() {
				"use strict";

				function StatePlay() {
					this.name = "play";
				}

				StatePlay.prototype.init = function() {
					this.scoreElem = document.querySelector(".score");
					this.stageElem = document.querySelector(".stage");
					this.dimLong = 28;
					this.dimShort = 16;
					this.padding = 0.25;
					this.boardTiles = new g.Group();
					this.keys = {};
					this.foodCreateTimeout = null;
					this.score = 0;
					this.scoreElem.innerHTML = this.score;
					this.time = new g.Time();
					this.getDimensions();
					if (this.winWidth < this.winHeight) {
						this.rows = this.dimLong;
						this.cols = this.dimShort;
					} else {
						this.rows = this.dimShort;
						this.cols = this.dimLong;
					}
					this.spacing = 1;
					this.grid = new g.Grid(this.cols, this.rows);
					this.resize();
					this.createBoardTiles();
					this.bindEvents();
					this.snake = new g.Snake({
						parentState: this
					});
					this.food = new g.Food({
						parentState: this
					});
				};

				StatePlay.prototype.getDimensions = function() {
					this.winWidth = window.innerWidth;
					this.winHeight = window.innerHeight;
					this.activeWidth = this.winWidth - this.winWidth * this.padding;
					this.activeHeight = this.winHeight - this.winHeight * this.padding;
				};

				StatePlay.prototype.resize = function() {
					var _this = g.currentState();

					_this.getDimensions();

					_this.stageRatio = _this.rows / _this.cols;

					if (_this.activeWidth > _this.activeHeight / _this.stageRatio) {
						_this.stageHeight = _this.activeHeight;
						_this.stageElem.style.height = _this.stageHeight + "px";
						_this.stageWidth = Math.floor(_this.stageHeight / _this.stageRatio);
						_this.stageElem.style.width = _this.stageWidth + "px";
					} else {
						_this.stageWidth = _this.activeWidth;
						_this.stageElem.style.width = _this.stageWidth + "px";
						_this.stageHeight = Math.floor(_this.stageWidth * _this.stageRatio);
						_this.stageElem.style.height = _this.stageHeight + "px";
					}

					_this.tileWidth = ~~(_this.stageWidth / _this.cols);
					_this.tileHeight = ~~(_this.stageHeight / _this.rows);
					_this.dimAvg = (_this.activeWidth + _this.activeHeight) / 2;
					_this.spacing = Math.max(1, ~~(_this.dimAvg * 0.0025));

					_this.stageElem.style.marginTop = -_this.stageElem.offsetHeight / 2 + _this.headerHeight / 2 + "px";

					_this.boardTiles.each("updateDimensions");
					_this.snake !== undefined && _this.snake.updateDimensions();
					_this.food !== undefined && _this.food.updateDimensions();
				};

				StatePlay.prototype.createBoardTiles = function() {
					for (var y = 0; y < this.rows; y++) {
						for (var x = 0; x < this.cols; x++) {
							this.boardTiles.add(
								new g.BoardTile({
									parentState: this,
									parentGroup: this.boardTiles,
									col: x,
									row: y,
									x: x * this.tileWidth,
									y: y * this.tileHeight,
									w: this.tileWidth - this.spacing,
									h: this.tileHeight - this.spacing
								})
							);
						}
					}
				};

				StatePlay.prototype.upOn = function() {
					g.currentState().keys.up = 1;
				};
				StatePlay.prototype.downOn = function() {
					g.currentState().keys.down = 1;
				};
				StatePlay.prototype.rightOn = function() {
					g.currentState().keys.right = 1;
				};
				StatePlay.prototype.leftOn = function() {
					g.currentState().keys.left = 1;
				};
				StatePlay.prototype.upOff = function() {
					g.currentState().keys.up = 0;
				};
				StatePlay.prototype.downOff = function() {
					g.currentState().keys.down = 0;
				};
				StatePlay.prototype.rightOff = function() {
					g.currentState().keys.right = 0;
				};
				StatePlay.prototype.leftOff = function() {
					g.currentState().keys.left = 0;
				};

				StatePlay.prototype.keydown = function(e) {
					e.preventDefault();
					var e = e.keyCode ? e.keyCode : e.which,
						_this = g.currentState();
					if (e === 38 || e === 87) {
						_this.upOn();
					}
					if (e === 39 || e === 68) {
						_this.rightOn();
					}
					if (e === 40 || e === 83) {
						_this.downOn();
					}
					if (e === 37 || e === 65) {
						_this.leftOn();
					}
				};

				StatePlay.prototype.bindEvents = function() {
					var _this = g.currentState();
					window.addEventListener("keydown", _this.keydown, false);
					window.addEventListener("resize", _this.resize, false);
				};

				StatePlay.prototype.step = function() {
					this.boardTiles.each("update");
					this.boardTiles.each("render");
					this.snake.update();
					this.snake.render();
					this.food.update();
					this.food.render();
					this.time.update();
				};

				StatePlay.prototype.exit = function() {
					window.removeEventListener("keydown", this.keydown, false);
					window.removeEventListener("resize", this.resize, false);
					this.stageElem.innerHTML = "";
					this.grid.tiles = null;
					this.time = null;
				};

				g.addState(new StatePlay());
			})();

			(function() {
				"use strict";

				g.config = {
					title: "Snakely",
					debug: window.location.hash == "#debug" ? 1 : 0,
					state: "play"
				};

				g.setState(g.config.state);

				g.time = new g.Time();

				g.step = function() {
					requestAnimationFrame(g.step);
					g.states[g.state].step();
					g.time.update();
				};

				window.addEventListener("load", g.step, false);
			})();
		</script>>
	</body>>
</html>

HTML文件点开就可以玩哦

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小孙同学1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值