mirror of
				https://github.com/flynx/Slang.git
				synced 2025-11-03 21:10:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			290 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			290 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!DOCTYPE html>
 | 
						|
<html>
 | 
						|
<style>
 | 
						|
 | 
						|
.snake.field {
 | 
						|
	width: 500px;
 | 
						|
	height: 500px;
 | 
						|
	border: solid 1px silver;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
</style>
 | 
						|
 | 
						|
<script>
 | 
						|
 | 
						|
var Snake = {
 | 
						|
	config: {
 | 
						|
		apple_color: 'red',
 | 
						|
		wall_color: 'gray',
 | 
						|
		interval: 200,
 | 
						|
	},
 | 
						|
 | 
						|
	_field: null,
 | 
						|
	_cells: null,
 | 
						|
	players: null,
 | 
						|
	field_size: null,
 | 
						|
 | 
						|
	// XXX BUG: going down into bottom left corner breaks the snake...
 | 
						|
	//		...check other corner cases!
 | 
						|
	//			...looks like the only corner case...
 | 
						|
	_tick: function(){
 | 
						|
		var that = this
 | 
						|
 | 
						|
		var l = this._cells.length
 | 
						|
		var w = this.field_size.width
 | 
						|
		var h = this.field_size.height
 | 
						|
 | 
						|
		var tick = this.__tick = (this.__tick + 1 || 0)
 | 
						|
		var directions = 'neswn'
 | 
						|
 | 
						|
		this._cells.forEach(function(cell, i){
 | 
						|
			var color = cell.style.backgroundColor
 | 
						|
 | 
						|
			// skip cells we touched...
 | 
						|
			if(cell.tick == tick){
 | 
						|
				return
 | 
						|
			}
 | 
						|
 | 
						|
			// snake...
 | 
						|
			if(cell.age != null){
 | 
						|
				// handle cell age...
 | 
						|
				if(cell.age == 0){
 | 
						|
					delete cell.age
 | 
						|
					cell.style.backgroundColor = ''
 | 
						|
 | 
						|
				} else {
 | 
						|
					cell.age -= 1
 | 
						|
				}
 | 
						|
 | 
						|
				// head...
 | 
						|
				var direction = cell.direction
 | 
						|
				var next = 
 | 
						|
					direction == 'n' ?
 | 
						|
						(i < w ? l - w + i : i - w)
 | 
						|
					: direction == 's' ?
 | 
						|
						(i > (l-w) ? i - (l-w) : i + w)
 | 
						|
					: direction == 'e' ?
 | 
						|
						((i+1)%w == 0 ? i - (w-1) : i + 1)
 | 
						|
					: direction == 'w' ?
 | 
						|
						(i%w == 0 ? i + (w-1) : i - 1)
 | 
						|
					: null 
 | 
						|
 | 
						|
				if(next != null){
 | 
						|
					next = that._cells[next]
 | 
						|
 | 
						|
					// turn...
 | 
						|
					var turn = that.players[color] || ''
 | 
						|
					if(turn != ''){
 | 
						|
						var j = turn == 'left' ? directions.indexOf(direction) - 1
 | 
						|
							: directions.indexOf(direction) + 1
 | 
						|
						j = j < 0 ? 3 : j
 | 
						|
						direction = directions[j]
 | 
						|
						that.players[color] = ''
 | 
						|
					}
 | 
						|
 | 
						|
					var age = cell.age
 | 
						|
					var move = false
 | 
						|
					// special case: other snake's head -- kill both...
 | 
						|
					if(next.direction){
 | 
						|
						next.style.backgroundColor = ''
 | 
						|
						// NOTE: we are not deleteing .direction here as 
 | 
						|
						//		we can have upto 4 snakes colliding...
 | 
						|
						next.direction = ''
 | 
						|
						delete next.age
 | 
						|
 | 
						|
					// apples...
 | 
						|
					} else if(next.style.backgroundColor == that.config.apple_color){
 | 
						|
						age += 1
 | 
						|
						move = true
 | 
						|
 | 
						|
					// empty...
 | 
						|
					// NOTE: anything but an apple will kill the snake...
 | 
						|
					} else if(next.style.backgroundColor == ''){
 | 
						|
						move = true
 | 
						|
					}
 | 
						|
 | 
						|
					if(move){
 | 
						|
						next.tick = tick
 | 
						|
						next.style.backgroundColor = color
 | 
						|
						next.age = age + 1
 | 
						|
						next.direction = direction
 | 
						|
					}
 | 
						|
 | 
						|
					delete cell.direction
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			cell.tick = tick
 | 
						|
		})
 | 
						|
	},
 | 
						|
 | 
						|
	setup: function(field){
 | 
						|
		field = field || this._field
 | 
						|
		field = this._field = typeof(field) == typeof('str') ? document.querySelector(field)
 | 
						|
			: field
 | 
						|
		this._cells = [].slice.call(field.querySelectorAll('td'))
 | 
						|
		this.field_size = {
 | 
						|
			width: field.querySelector('tr').querySelectorAll('td').length,
 | 
						|
			height: field.querySelectorAll('tr').length,
 | 
						|
		}
 | 
						|
		this.players = {}
 | 
						|
		return this
 | 
						|
	},
 | 
						|
 | 
						|
	// constructors...
 | 
						|
	snake: function(color, x, y, direction, age){
 | 
						|
		var head = this._cells[x + y * this.field_size.width]
 | 
						|
 | 
						|
		head.style.backgroundColor = color
 | 
						|
		head.direction = direction
 | 
						|
		head.age = (age || 5) - 1
 | 
						|
 | 
						|
		this.players[color] = ''
 | 
						|
 | 
						|
		return this
 | 
						|
	},
 | 
						|
	apple: function(x, y){
 | 
						|
		this._cells[x + y * this.field_size.width]
 | 
						|
			.style.backgroundColor = this.config.apple_color
 | 
						|
		return this
 | 
						|
	},
 | 
						|
	wall: function(x, y, direction, length){
 | 
						|
		length = length || 1
 | 
						|
		while(length > 0){
 | 
						|
			this._cells[x + y * this.field_size.width]
 | 
						|
				.style.backgroundColor = this.config.wall_color
 | 
						|
 | 
						|
			x += direction == 'e' ? 1
 | 
						|
				: direction == 'w' ? -1
 | 
						|
				: 0
 | 
						|
			x = x < 0 ? this.field_size.width + x
 | 
						|
				: x % this.field_size.width
 | 
						|
			y += direction == 'n' ? -1
 | 
						|
				: direction == 's' ? 1
 | 
						|
				: 0
 | 
						|
			y = y < 0 ? this.field_size.height + y
 | 
						|
				: y % this.field_size.height
 | 
						|
 | 
						|
			length -= 1
 | 
						|
		}
 | 
						|
		return this
 | 
						|
	},
 | 
						|
 | 
						|
	// actions...
 | 
						|
	start: function(){
 | 
						|
		this.__timer = this.__timer 
 | 
						|
			|| setInterval(this._tick.bind(this), this.config.interval || 200)
 | 
						|
		return this
 | 
						|
	},
 | 
						|
	stop: function(){
 | 
						|
		clearInterval(this.__timer)
 | 
						|
		delete this.__timer
 | 
						|
		delete this.__tick
 | 
						|
		return this
 | 
						|
	},
 | 
						|
	left: function(color){ 
 | 
						|
		this.players[color || Object.keys(this.players)[0]] = 'left' 
 | 
						|
		return this
 | 
						|
	},
 | 
						|
	right: function(color){
 | 
						|
		this.players[color || Object.keys(this.players)[0]] = 'right' 
 | 
						|
		return this
 | 
						|
	},
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
function test(game){
 | 
						|
	return Snake
 | 
						|
		.setup(game || '.snake')
 | 
						|
 | 
						|
		// XXX BUG: this will break as soon as it reaches the corner...
 | 
						|
		.snake('blue', 0, 0, 's', 5)
 | 
						|
 | 
						|
		// hit an apple...
 | 
						|
		.snake('green', 5, 3, 's', 5)
 | 
						|
		.apple(5, 5)
 | 
						|
 | 
						|
		// hit a wall...
 | 
						|
		.snake('silver', 14, 3, 'w', 5)
 | 
						|
		.wall(2, 14, 's', 7)
 | 
						|
 | 
						|
		.start()
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// XXX keyboard controller...
 | 
						|
//		- press two buttons in under N milliseconds to launch a snake
 | 
						|
//		- first button pressed is left, second is right
 | 
						|
// XXX should the cfg be global or local to Snake???
 | 
						|
//		...at this point global seems simpler...
 | 
						|
var KEY_CONFIG = {
 | 
						|
}
 | 
						|
function kbHandler(event){
 | 
						|
	// XXX
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
function setup(){
 | 
						|
	Snake('.snake')
 | 
						|
		// setup base level...
 | 
						|
		// XXX
 | 
						|
		.wall(2, 14, 's', 7)
 | 
						|
 | 
						|
		.start()
 | 
						|
 | 
						|
	// XXX setup kb handler...
 | 
						|
	// XXX
 | 
						|
}
 | 
						|
 | 
						|
</script>
 | 
						|
 | 
						|
<body onload="setup()">
 | 
						|
 | 
						|
<table class="snake field" cellspacing="0">
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
	<tr> <td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td>
 | 
						|
		<td></td><td></td><td></td><td></td> <td></td><td></td><td></td><td></td> </tr>
 | 
						|
</table>
 | 
						|
 | 
						|
<p>
 | 
						|
XXX basic instructions...
 | 
						|
</p>
 | 
						|
 | 
						|
</body>
 | 
						|
</html>
 | 
						|
<!-- vim:set ts=4 sw=4 spell : -->
 |