実戦——対象に向かって+原型を実現した食いしん坊蛇
62914 ワード
対象+プロトタイプに向かって食いしん坊を実現
前のあの食いしん坊蛇https://blog.csdn.net/F_Felix/article/details/89676816)対象向けにも使われていますが、ゲーム自体が同じ対象となるように、JavaScriptのプロトタイプを使っているのと同じように、この食いしん坊蛇を分析してみます.
考え方の分析
1、全部でいくつの相手がいますか?ここには4つのオブジェクトがあります.それぞれSnake、Food、Game、mapですが、簡単な点のためにmapオブジェクトを省略しました.前の編の2、各オブジェクトを直接使うなら、どのような属性と方法がありますか? Foodオブジェクト:幅の高さ、色、位置の属性およびレンダリング方法(width、height、bgColor、x、yおよびrender) Snakeオブジェクト:幅、方向、頭の色、体の色、体の属性及びレンダリング及び移動方法(width、height、direction、headColor、bodyColor、body、render、move) Gameオブジェクト:地図、蛇、食べ物の属性と初期化、初期化ゲーム、スタートゲーム、一時停止ゲーム、リセットゲーム、終了ゲーム、操作蛇のオブジェクト(map、snake、food、init、start、pause、control、reet) 3、どのように前の基礎の上で最適化を行いますか?は、方法をプロトタイプに定義し、構造関数 に属性を定義する.沙箱を使ってコードをくるみ、大域汚染を避ける(説明:https://blog.csdn.net/F_Felix/article/details/90111118) それから多くなく説明しました.コードの中にコメントがあります.直接コードをつけます.
ページコード
前のあの食いしん坊蛇https://blog.csdn.net/F_Felix/article/details/89676816)対象向けにも使われていますが、ゲーム自体が同じ対象となるように、JavaScriptのプロトタイプを使っているのと同じように、この食いしん坊蛇を分析してみます.
考え方の分析
1、全部でいくつの相手がいますか?ここには4つのオブジェクトがあります.それぞれSnake、Food、Game、mapですが、簡単な点のためにmapオブジェクトを省略しました.前の編の2、各オブジェクトを直接使うなら、どのような属性と方法がありますか?
ページコード
<style>
* {
margin: 0;
padding: 0;
}
.map {
width: 800px;
height: 500px;
background-color: #000;
margin: 0 auto;
position: relative;
}
p {
text-align: center;
line-height: 30px;
}
.btn {
margin: 0 auto;
text-align: center;
}
style>
<body>
<div class="btn">
<button class="begin"> button>
<button class="pause"> button>
<button class="reset"> button>
div>
<p>
<strong> :strong>Enter--> Space--> Esc--->
←↑→↓
p>
<p> 10 , 50, 200p>
<div class="map">div>
<script src="food.js">script>
<script src="snake.js">script>
<script src="game.js">script>
<script>
var map = document.querySelector('.map')
var btn1 = document.querySelector('.begin')
var btn2 = document.querySelector('.pause')
var btn3 = document.querySelector('.reset')
var g = new Game({
map: map
})
g.init()
btn1.onclick = function() {
g.start()
}
btn2.onclick = function() {
g.pause()
}
btn3.onclick = function() {
g.reset()
}
// js ,
document.onkeydown = function(e) {
switch (e.keyCode) {
case 13:
btn1.focus()
break
case 32:
btn2.focus()
break
case 27:
btn3.focus()
break
}
}
script>
body>
Foodオブジェクト// 4----
;(function(window) {
/**
*
* @param {object} options
* : 、 、 、
* :
*/
function Food(options) {
options = options || {}
this.width = options.width || 20
this.height = options.height || 20
this.bgColor = options.bgColor || 'cyan'
this.x = 0
this.y = 0
}
Food.prototype.render = function(target) {
// 1, ,
this.node && target.removeChild(this.node)
// , map
var div = document.createElement('div')
this.node = div
target.appendChild(div)
div.style.width = this.width + 'px'
div.style.height = this.height + 'px'
div.style.backgroundColor = this.bgColor
div.style.position = 'absolute'
this.x = ((Math.random() * target.offsetWidth) / this.width) | 0
this.y = ((Math.random() * target.offsetHeight) / this.height) | 0
div.style.left = this.x * this.width + 'px'
div.style.top = this.y * this.height + 'px'
div.style.borderRadius = '50%'
}
window.Food = Food
})(window)
Snakeオブジェクト;(function(window) {
/**
*
* @param {*} options ( )
* : , , ,
* : 、
*/
function Snake(options) {
options = options || {}
this.width = options.width || 20
this.height = options.height || 20
this.direction = options.direction || 'right'
this.headColor = options.headColor || 'skyblue'
this.bodyColor = options.bodyColor || 'yellowgreen'
this.body = [{ x: 2, y: 0 }, { x: 1, y: 0 }, { x: 0, y: 0 }]
}
// map
Snake.prototype.render = function(target) {
// 2
var spans = document.querySelectorAll('span')
for (var i = 0; i < spans.length; i++) {
target.removeChild(spans[i])
}
for (var i = 0; i < this.body.length; i++) {
var span = document.createElement('span')
target.appendChild(span)
span.style.width = this.width + 'px'
span.style.height = this.height + 'px'
span.style.backgroundColor = i === 0 ? this.headColor : this.bodyColor
span.style.position = 'absolute'
span.style.left = this.body[i].x * this.width + 'px'
span.style.top = this.body[i].y * this.height + 'px'
span.style.borderRadius = '50%'
}
}
//
Snake.prototype.move = function(target, food) {
/*
:
,
*/
var head = {
x: this.body[0].x,
y: this.body[0].y
}
switch (this.direction) {
case 'right':
head.x++
break
case 'left':
head.x--
break
case 'up':
head.y--
break
case 'down':
head.y++
break
}
this.body.unshift(head)
// ,
if (head.x == food.x && head.y == food.y) {
// , food ---> 1
food.render(target)
} else {
this.body.pop()
}
// 4 ,
if (
head.x < 0 ||
head.y < 0 ||
head.x >= target.offsetWidth / this.width ||
head.y >= target.offsetHeight / this.height
) {
return
}
// 2 , ,
this.render(target)
}
window.Snake = Snake
})(window)
ゲームオブジェクト// 4 --
;(function(window) {
/**
*
* @param {*} options
* : 、 、 、
* : 、 、 、 、 、 ( )
*/
function Game(options) {
options = options || {}
this.map = options.map
this.snake = options.snake || new Snake()
this.food = options.food || new Food()
this.duration = 200 //
this.limit = 50 // 50ms
this.level = 10 //
}
// 3
var dirFlag = true // ---> ,
var gameFlag = true // --->
var tId // id
var these // start this, ,
var prevLength = 3 // 3
//
Game.prototype.init = function() {
this.snake.render(this.map)
this.food.render(this.map)
// start
this.control()
}
//
Game.prototype.start = function() {
if (gameFlag) {
gameFlag = false
// this this ,
// var that = this;
// this.timeId = setInterval(function () {
// // : this this , window
// that.snake.move(that.map, that.food);
// //
// that.gameOver();
// //
// setTimeout(() => {
// dirFlag = true;
// }, 100);
// }, this.duration);
these = this
// tId = setInterval('execute(these)', this.duration)
tId = setInterval(() => {
execute(these)
}, this.duration)
}
}
// ,
function execute(these) {
// : this this , window
these.snake.move(these.map, these.food)
//
these.gameOver()
clearInterval(tId)
if (
these.snake.body.length - prevLength >= these.level &&
these.duration >= these.limit
) {
prevLength = these.snake.body.length
these.duration -= 10
console.log(these.duration)
}
// var that = tt;
// , ,
if (!gameFlag) {
tId = setInterval(() => {
execute(these)
}, these.duration)
}
//
setTimeout(() => {
dirFlag = true
}, 100)
}
//
Game.prototype.gameOver = function() {
var head = this.snake.body[0]
// 1、 --->
if (
head.x < 0 ||
head.y < 0 ||
head.x >= this.map.offsetWidth / this.snake.width ||
head.y >= this.map.offsetHeight / this.snake.height
) {
alert('Game Over!')
this.pause()
gameFlag = true
}
// 2、 --->
for (var i = 4; i < this.snake.body.length; i++) {
if (head.x == this.snake.body[i].x && head.y == this.snake.body[i].y) {
alert('Game Over!')
this.pause()
gameFlag = true
}
}
}
//
Game.prototype.pause = function() {
// clearInterval(this.timeId);
clearInterval(tId)
gameFlag = true
dirFlag = true
}
// 、 、
Game.prototype.control = function() {
var that = this
document.addEventListener('keydown', function(e) {
if (dirFlag) {
dirFlag = false
switch (e.keyCode) {
case 37:
if (that.snake.direction != 'right') {
that.snake.direction = 'left'
}
break
case 38:
if (that.snake.direction != 'down') {
that.snake.direction = 'up'
}
break
case 39:
if (that.snake.direction != 'left') {
that.snake.direction = 'right'
}
break
case 40:
if (that.snake.direction != 'up') {
that.snake.direction = 'down'
}
break
case 32:
that.pause()
break
case 13:
that.start()
break
case 27:
that.reset()
break
}
}
})
}
//
Game.prototype.reset = function() {
this.snake.body = [{ x: 2, y: 0 }, { x: 1, y: 0 }, { x: 0, y: 0 }]
this.snake.direction = 'right'
this.init()
// clearInterval(this.timeId);
clearInterval(tId)
gameFlag = true
dirFlag = true
}
window.Game = Game
})(window)
ゲーム中の方法について簡単に説明してください.1、 these = this?(start )
: ,this window , this Game , this these, these Game 。( these = this , )
, , ' ' bind , this Game this
tId = setInterval(function(){
execute(this)
}.bind(this),this.duration)
2、 execute ?
: , function this.duration , , , ,
3、 ?
: , , , over, : , , ( ) , , 。 , , , , , , 。
4、 ?
: , , , 。