style update...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2022-07-10 11:36:11 +03:00
parent fbc68b9393
commit b43adbce0d

190
simplesnake/simplesnake.js Executable file → Normal file
View File

@ -79,11 +79,9 @@ function makeEvent(handler_attr){
var args = [].slice.call(arguments) var args = [].slice.call(arguments)
this[handler_attr] this[handler_attr]
&& this[handler_attr] && this[handler_attr]
.forEach(function(handler){ handler.apply(that, args) }) .forEach(function(handler){
} handler.apply(that, args) }) }
return this return this } }
}
}
var Snake = { var Snake = {
config: { config: {
@ -108,8 +106,7 @@ var Snake = {
return { return {
x: i%w, x: i%w,
y: Math.floor(i/w), y: Math.floor(i/w),
} } },
},
get random_direction(){ get random_direction(){
return ('nesw')[Math.floor(Math.random() * 4)] }, return ('nesw')[Math.floor(Math.random() * 4)] },
@ -126,15 +123,15 @@ var Snake = {
var h = this.field_size.height var h = this.field_size.height
var y = point.y % h var y = point.y % h
y = y < 0 ? (y + h) : y y = y < 0 ? (y + h) : y
return { x: x, y: y } return { x, y } },
},
// system... // system...
setup: function(field, size, interval){ setup: function(field, size, interval){
this.config.field_size = size || this.config.field_size this.config.field_size = size || this.config.field_size
this.config.interval = interval || this.config.interval this.config.interval = interval || this.config.interval
field = field || this._field field = field || this._field
field = this._field = typeof(field) == typeof('str') ? document.querySelector(field) field = this._field = typeof(field) == typeof('str') ?
document.querySelector(field)
: field : field
this._make_field() this._make_field()
this._cells = [].slice.call(field.querySelectorAll('td')) this._cells = [].slice.call(field.querySelectorAll('td'))
@ -145,8 +142,7 @@ var Snake = {
this.players = {} this.players = {}
return this return this
.appleEaten(null) .appleEaten(null)
.snakeKilled(null) .snakeKilled(null) },
},
_make_field: function(w){ _make_field: function(w){
var l = [] var l = []
l.length = w || this.config.field_size l.length = w || this.config.field_size
@ -156,8 +152,7 @@ var Snake = {
l.map(function(){ l.map(function(){
return ` <tr> ${ l.join('') } </tr>` return ` <tr> ${ l.join('') } </tr>`
}).join('\n') }).join('\n')
}\n</table>` }\n</table>` },
},
_tick: function(){ _tick: function(){
var that = this var that = this
var l = this._cells.length var l = this._cells.length
@ -171,8 +166,7 @@ var Snake = {
// skip cells we touched on this tick... // skip cells we touched on this tick...
if(cell.tick == tick){ if(cell.tick == tick){
return return }
}
// snake... // snake...
if(cell.age != null){ if(cell.age != null){
@ -183,8 +177,7 @@ var Snake = {
cell.style.backgroundColor = '' cell.style.backgroundColor = ''
} else { } else {
cell.age -= 1 cell.age -= 1 }
}
// snake head -> move... // snake head -> move...
var direction = cell.direction var direction = cell.direction
@ -192,22 +185,30 @@ var Snake = {
// turn... // turn...
if(that.players[color] != ''){ if(that.players[color] != ''){
var turn = that.players[color] || '' var turn = that.players[color] || ''
var j = turn == 'left' ? directions.indexOf(direction) - 1 var j = turn == 'left' ?
directions.indexOf(direction) - 1
: directions.indexOf(direction) + 1 : directions.indexOf(direction) + 1
j = j < 0 ? 3 : j j = j < 0 ? 3 : j
direction = directions[j] direction = directions[j]
that.players[color] = '' that.players[color] = '' }
}
// get next cell index... // get next cell index...
var next = var next =
direction == 'n' ? direction == 'n' ?
(i < w ? l - w + i : i - w) (i < w ?
l - w + i
: i - w)
: direction == 's' ? : direction == 's' ?
(i > (l-w-1) ? i - (l-w) : i + w) (i > (l-w-1) ?
i - (l-w)
: i + w)
: direction == 'e' ? : direction == 'e' ?
((i+1)%w == 0 ? i - (w-1) : i + 1) ((i+1)%w == 0 ?
: (i%w == 0 ? i + (w-1) : i - 1) i - (w-1)
: i + 1)
: (i%w == 0 ?
i + (w-1)
: i - 1)
next = that._cells[next] next = that._cells[next]
var age = cell.age var age = cell.age
@ -238,8 +239,7 @@ var Snake = {
// other -> kill... // other -> kill...
} else { } else {
that.snakeKilled(color, age+2) that.snakeKilled(color, age+2) }
}
// do the move... // do the move...
if(move){ if(move){
@ -247,16 +247,11 @@ var Snake = {
next.style.backgroundColor = color next.style.backgroundColor = color
next.classList.add('snake') next.classList.add('snake')
next.age = age + 1 next.age = age + 1
next.direction = direction next.direction = direction }
}
delete cell.direction delete cell.direction } }
} cell.tick = tick })
} this.tick(tick) },
cell.tick = tick
})
this.tick(tick)
},
// constructors... // constructors...
snake: function(color, age, point, direction){ snake: function(color, age, point, direction){
@ -265,53 +260,57 @@ var Snake = {
var head = this._cells[point.x + point.y * this.field_size.width] var head = this._cells[point.x + point.y * this.field_size.width]
head.style.backgroundColor = color head.style.backgroundColor = color
head.classList.add('snake') head.classList.add('snake')
head.direction = direction || this.random_direction head.direction = direction
|| this.random_direction
head.age = (age || 5) - 1 head.age = (age || 5) - 1
this.players[color] = '' this.players[color] = ''
return this return this
.snakeBorn(color) .snakeBorn(color) },
},
apple: function(point){ apple: function(point){
point = this.normalize_point(point || this.random_point) point = this.normalize_point(point || this.random_point)
var c = this._cells[point.x + point.y * this.field_size.width] var c = this._cells[point.x + point.y * this.field_size.width]
c.classList.add('apple') c.classList.add('apple')
c.style.backgroundColor = '' c.style.backgroundColor = ''
return this return this },
},
wall: function(point, direction, length){ wall: function(point, direction, length){
direction = direction || this.random_direction direction = direction
|| this.random_direction
point = this.normalize_point(point || this.random_point) point = this.normalize_point(point || this.random_point)
var x = point.x var x = point.x
var y = point.y var y = point.y
length = length || Math.random() * this.field_size.width length = length
|| Math.random() * this.field_size.width
while(length > 0){ while(length > 0){
var c = this._cells[x + y * this.field_size.width] var c = this._cells[x + y * this.field_size.width]
c.classList.add('wall') c.classList.add('wall')
c.style.backgroundColor = '' c.style.backgroundColor = ''
x += direction == 'e' ? 1 x += direction == 'e' ?
: direction == 'w' ? -1 1
: direction == 'w' ?
-1
: 0 : 0
x = x < 0 ? this.field_size.width + x x = x < 0 ?
this.field_size.width + x
: x % this.field_size.width : x % this.field_size.width
y += direction == 'n' ? -1 y += direction == 'n' ?
: direction == 's' ? 1 -1
: direction == 's' ?
1
: 0 : 0
y = y < 0 ? this.field_size.height + y y = y < 0 ?
this.field_size.height + y
: y % this.field_size.height : y % this.field_size.height
length -= 1 length -= 1 }
}
return this return this },
},
level: function(level){ level: function(level){
var that = this var that = this
level.forEach(function(wall){ level.forEach(function(wall){
that.wall.apply(that, wall) }) that.wall.apply(that, wall) })
return this return this },
},
// events... // events...
snakeKilled: makeEvent('__killHandlers'), snakeKilled: makeEvent('__killHandlers'),
@ -324,32 +323,35 @@ var Snake = {
// actions... // actions...
start: function(t){ start: function(t){
this.__timer = this.__timer this.__timer = this.__timer
|| setInterval(this._tick.bind(this), t || this.config.interval || 200) || setInterval(
this._tick.bind(this),
t
|| this.config.interval
|| 200)
// reset player control actions... // reset player control actions...
var that = this var that = this
Object.keys(this.players) Object.keys(this.players)
.forEach(function(k){ that.players[k] = '' }) .forEach(function(k){
that.players[k] = '' })
return this return this
.tick() .tick()
.gameStarted() .gameStarted() },
},
stop: function(){ stop: function(){
clearInterval(this.__timer) clearInterval(this.__timer)
delete this.__timer delete this.__timer
delete this.__tick delete this.__tick
return this return this
.gameStopped() .gameStopped() },
},
pause: function(){ pause: function(){
return this.__timer ? this.stop() : this.start() }, return this.__timer ?
this.stop()
: this.start() },
left: function(color){ left: function(color){
this.players[color || Object.keys(this.players)[0]] = 'left' this.players[color || Object.keys(this.players)[0]] = 'left'
return this return this },
},
right: function(color){ right: function(color){
this.players[color || Object.keys(this.players)[0]] = 'right' this.players[color || Object.keys(this.players)[0]] = 'right'
return this return this },
},
} }
@ -388,19 +390,23 @@ function makeTapHandler(snake){
// prevent clicks and touches from triggering the same action // prevent clicks and touches from triggering the same action
// twice -- only handle the first one within timeout... // twice -- only handle the first one within timeout...
// NOTE: this should not affect events of the same type... // NOTE: this should not affect events of the same type...
if(__DEBOUNCE && event.type != __DEBOUNCE){ return } if(__DEBOUNCE && event.type != __DEBOUNCE){
return }
__DEBOUNCE = event.type __DEBOUNCE = event.type
setTimeout(function(){ __DEBOUNCE = false }, __DEBOUNCE_TIMEOUT) setTimeout(function(){ __DEBOUNCE = false }, __DEBOUNCE_TIMEOUT)
clearHints() clearHints()
// top of screen (1/8)... // top of screen (1/8)...
;(event.clientY || event.changedTouches[0].pageY) <= (window.innerHeight / 8) ? ;(event.clientY
|| event.changedTouches[0].pageY) <= (window.innerHeight / 8) ?
setup() setup()
// bottom of screen 1/8... // bottom of screen 1/8...
: (event.clientY || event.changedTouches[0].pageY) >= (window.innerHeight / 8)*7 ? : (event.clientY
|| event.changedTouches[0].pageY) >= (window.innerHeight / 8)*7 ?
Snake.pause() Snake.pause()
// left/right of screen... // left/right of screen...
: (event.clientX || event.changedTouches[0].pageX) <= (window.innerWidth / 2) ? : (event.clientX
|| event.changedTouches[0].pageX) <= (window.innerWidth / 2) ?
Snake.left() Snake.left()
: Snake.right() }} : Snake.right() }}
@ -425,8 +431,7 @@ function digitizeBackground(snake, walls){
`rgb(${220 - v*2}, ${220 - v*2}, ${220 - v*2})`) `rgb(${220 - v*2}, ${220 - v*2}, ${220 - v*2})`)
// skip the rest... // skip the rest...
: null }) : null })
return snake return snake }
}
//--------------------------------------------------------------------- //---------------------------------------------------------------------
@ -455,12 +460,12 @@ function setup(snake, timer, size){
get random(){ get random(){
var l = Object.keys(this) var l = Object.keys(this)
.filter(function(e){ return e != 'random' }) .filter(function(e){
return e != 'random' })
do { do {
var level = this[l[ Math.round(Math.random()*l.length) ]] var level = this[l[ Math.round(Math.random()*l.length) ]]
} while(!(level instanceof Array)) } while(!(level instanceof Array))
return level return level },
},
} }
function showScore(color, age){ function showScore(color, age){
@ -473,14 +478,17 @@ function setup(snake, timer, size){
: snake.__top_score : snake.__top_score
snake._field.setAttribute('score', score.score) snake._field.setAttribute('score', score.score)
snake._field.setAttribute('snake', score.color) snake._field.setAttribute('snake', score.color)
snake._field.setAttribute('state', ( snake._field.setAttribute('state',
score.score == age && score.color == color) ? '(current)' : '') (score.score == age
} && score.color == color) ?
'(current)'
: '') }
// setup event handlers (only once)... // setup event handlers (only once)...
if(!__HANDLER_SET){ if(!__HANDLER_SET){
document.querySelectorAll('.version') document.querySelectorAll('.version')
.forEach(function(e){ e.innerHTML = VERSION }) .forEach(function(e){
e.innerHTML = VERSION })
// control handlers... // control handlers...
document.addEventListener('keydown', makeKeyboardHandler(snake)) document.addEventListener('keydown', makeKeyboardHandler(snake))
@ -497,14 +505,12 @@ function setup(snake, timer, size){
appCache.swapCache() appCache.swapCache()
confirm('New version ready, reload?') confirm('New version ready, reload?')
&& location.reload() && location.reload() } })
} setInterval(
}) function(){ appCache.update() },
setInterval(function(){ appCache.update() }, __CACHE_UPDATE_CHECK) __CACHE_UPDATE_CHECK) }
}
__HANDLER_SET = true __HANDLER_SET = true }
}
// setup the game... // setup the game...
return snake return snake
@ -513,8 +519,7 @@ function setup(snake, timer, size){
.call(digitizeBackground, snake) .call(digitizeBackground, snake)
.call(function(){ .call(function(){
this.__snake_apples = [] this.__snake_apples = []
return this return this })
})
// load level... // load level...
.level(Level.random) .level(Level.random)
@ -523,8 +528,7 @@ function setup(snake, timer, size){
// reconstruct eaten apples... // reconstruct eaten apples...
.appleEaten(function(color, age){ .appleEaten(function(color, age){
this.apple() this.apple()
showScore(color, age) showScore(color, age) })
})
// one apple per snake... // one apple per snake...
.snakeBorn(function(color){ .snakeBorn(function(color){
this.__snake_apples.indexOf(color) < 0 this.__snake_apples.indexOf(color) < 0
@ -537,8 +541,7 @@ function setup(snake, timer, size){
this this
.pause() .pause()
.snake(color, 3) .snake(color, 3)
showScore(color, 3) showScore(color, 3) })
})
// indicate game state... // indicate game state...
.gameStarted(function(){ .gameStarted(function(){
this._field.classList.remove('paused') }) this._field.classList.remove('paused') })
@ -547,8 +550,7 @@ function setup(snake, timer, size){
// game eleemnts... // game eleemnts...
.apple() .apple()
.snake('blue', 3) .snake('blue', 3) }
}