清华大佬耗费三个月吐血整理的几百G的资源,免费分享!....>>>
<!doctype html> <html lang="zh"> <head> <title>纯HTML和CSS生成的贪食蛇游戏</title> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> /*General*/ * { box-sizing: border-box; font-family: 'microsoft yahei',Arial,sans-serif; } 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*/ .score { color: rgba(255, 255, 255, 0.5); font-size: 16px; font-weight: bold; padding-top: 5px; text-align: center; } /*Stage*/ .stage { bottom: 0; left: 0; margin: auto; position: absolute; right: 0; top: 0; z-index: 2; } /*Tiles*/ .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>分数:<span class="score">0</span></div> <div class="stage"></div> <script src="prefixfree.min.js"></script> <script src="modernizr.min.js"></script> <script> /*Polyfill*/ (function(){ 'use strict'; /*Request Animation Frame*/ 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 ); } } })(); /*DOM Manipulation*/ (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; } }; })(); /*Core*/ g = {}; (function(){ 'use strict'; /*Math*/ 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; /*Miscellaneous*/ 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 ) ); } }; })(); /*Group*/ (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 ); } } }; })(); /*Utilities*/ (function(){ 'use strict'; g.util = {}; /*Random*/ 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; }; }()); /*State*/ (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 ]; }; }()); /*Time*/ (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++; }; })(); /*Grid Entity*/ (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; }; })(); /*Board Tile Entity*/ (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; }; })(); /*Snake Tile Entity*/ (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; }; })(); /*Food Tile Entity*/ (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[ Modernizr.prefixed( '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; }; })(); /*Snake Entity*/ (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; // sync data grid of the play state 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 ) { // reset the update timer to 0, or whatever leftover there is this.updateTick = ( this.updateTick - this.updateTickMax ); // rotate snake block array 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; // sync data grid of the play state 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' ); // move the snake's head 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; } // wrap walls 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; } // check death by eating self if( this.parentState.grid.get( this.tiles[ 0 ].col, this.tiles[ 0 ].row ) == 'snake' ) { this.deathFlag = 1; clearTimeout( this.foodCreateTimeout ); } // check eating of food 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); } // check death by eating self if( this.deathFlag ) { g.setState( 'play' ); } } // update individual snake tiles 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() { // render individual snake tiles var i = this.tiles.length; while( i-- ) { this.tiles[ i ].render( i ); } }; })(); /*Food Entity*/ (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() { // update food tile this.tile.update(); if( this.birthTick > 0 ) { this.birthTick -= this.birthTickChange; } else if( this.birthTick < 0 ) { this.birthTick = 0; } // sync data grid of the play state this.parentState.grid.set( this.tile.col, this.tile.row, 'food' ); }; g.Food.prototype.render = function() { this.tile.render(); }; })(); /*================================================ Play State ================================================*/ (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() ); })(); /*================================================ Game ================================================*/ (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>