123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- /*
- * Part of Snek vs Snacc webapp.
- * Released under AGPLv3. Copyright (C) NetherEran 2020
- * */
- var field_width = 38
- var field_height = 18
- var pixel_width = 20
- var wpixels = field_width * pixel_width
- var hpixels = field_height * pixel_width
- function isInsideMap(point) {
- return point.x >= 0 &&
- point.x < field_width &&
- point.y >= 0 &&
- point.y < field_height
- }
- var canvas = document.getElementById("game_field")
- var context = canvas.getContext("2d")
- function Point(x, y) {
- this.x = x
- this.y = y
- this.add = function(pt) {
- return new Point(this.x + pt.x, this.y + pt.y)
- }
- this.equals = function(pt) {
- return (this.x == pt.x && this.y == pt.y)
- }
- this.distance = function(pt) {
- return Math.sqrt((this.x - pt.x) ** 2 + (this.y - pt.y) ** 2)
- }
- }
- var player
- var snacc
- var points = 0
- var game_going = false
- var eatSnacc
- var setLost
- function Player(x, y, length) {
- this.positions = new Array()
- this.length = length
- for (var i = 0; i < length; i++) {
- this.positions[i] = new Point(x + i, y)
- }
- this.head_ptr = this.length - 1
- this.next_direction = new Point(1, 0)
- this.direction = this.next_direction
- this.move = function() {
- let oldhead = this.positions[this.head_ptr]
- this.head_ptr = (this.head_ptr + 1) % this.length
- this.direction = this.next_direction
- let newhead = oldhead.add(this.direction)
-
- if(newhead.equals(snacc.position)) {
- eatSnacc()
- }
- if (!isInsideMap(newhead)) {
- setLost()
- }
- for (var i = 0; i < this.length; i++) {
- if (i == this.head_ptr) {
- continue
- }
- if (this.positions[i].equals(newhead)) {
- setLost()
- }
- }
-
- this.positions[this.head_ptr] = newhead
- }
- }
- document.addEventListener('keydown', function(event) {
- if (!player) {
- return
- }
- switch(event.keyCode) {
- case 37: //LEFT
- case 65:
- if (player.direction.x != 1) {
- player.next_direction = new Point(-1, 0)
- }
- break
- case 38: //UP
- case 87:
- if (player.direction.y != 1) {
- player.next_direction = new Point(0, -1)
- }
- break
- case 39: //RIGHT
- case 68:
- if (player.direction.x != -1) {
- player.next_direction = new Point(1, 0)
- }
- break
- case 40: //DOWN
- case 83:
- if (player.direction.y != -1) {
- player.next_direction = new Point(0, 1)
- }
- break
- default:
- break
- }
- });
- function Snacc(x, y, tier, direction) {
- this.position = new Point(x, y)
- this.tier = tier
- this.direction = direction
- this.move_tick = 0
- this.move = function() {
- //bounce
- if ((this.position.x + 1 == field_width && this.direction.x > 0) ||
- (this.position.x == 0 && this.direction.x < 0)) {
- this.direction.x = -this.direction.x
- }
- if ((this.position.y + 1 == field_height && this.direction.y > 0) ||
- (this.position.y == 0 && this.direction.y < 0)) {
- this.direction.y = -this.direction.y
- }
- //move
- this.position = this.position.add(this.direction)
-
- //check for collision with player
- for (var i = 0; i < player.length; i++) {
- if (player.positions[i].equals(this.position)) {
- if (i == player.head_ptr) {
- eatSnacc()
- } else {
- setLost()
- }
- }
- }
- if (this.direction == 2) {
- //alert()
- }
- }
- this.tick = function() {
- this.move_tick += this.tier ** 2
- if (this.move_tick > 17) {
- this.move()
- this.move_tick = 0
- }
- }
- }
- function addSnacc(max_value) {
- let tier = Math.floor(Math.random() * max_value) + 1
- let direction = Math.floor(Math.random() * 4)
- switch(direction) {
- case 0:
- direction = new Point(1, 1)
- break
- case 1:
- direction = new Point(-1, 1)
- break
- case 2:
- direction = new Point(-1, -1)
- break
- case 3:
- direction = new Point(1, -1)
- break
- }
-
- //find a point on the field that's far enough from the player to
- //not kill them right away
- let playerhead = player.positions[player.head_ptr]
- let spawnpoint = new Point(0, 0)
- do {
- spawnpoint.x = Math.floor(Math.random() * field_width)
- spawnpoint.y = Math.floor(Math.random() * field_height)
- } while (spawnpoint.distance(playerhead) < 13 + tier)
-
- snacc = new Snacc(spawnpoint.x, spawnpoint.y, tier, direction)
- }
- eatSnacc = function() {
- points += snacc.tier ** 2
- let maxval = Math.log(points) * 2 + 1
- addSnacc(maxval > 4 ? 4 : maxval)
- }
- setLost = function() {
- game_going = false
- }
- function drawPixel(point) {
- var posx = point.x * pixel_width
- var posy = point.y * pixel_width
- context.fillRect(posx, posy, pixel_width, pixel_width)
- }
- function getSnaccColor(tier) {
- switch(tier) {
- case 1:
- return "magenta"
- case 2:
- return "red"
- case 3:
- return "blue"
- case 4:
- return "yellow"
- }
- }
- //Graphics stuff
- function redrawField() {
- context.clearRect(0, 0, canvas.width, canvas.height)
-
- let snacc_color = getSnaccColor(snacc.tier)
- context.fillStyle = snacc_color
- context.strokeStyle = snacc_color
- drawPixel(snacc.position)
-
-
- context.fillStyle = "cyan"
- context.strokeStyle = "cyan"
- for (var i = 0; i < player.length; i++) {
- drawPixel(player.positions[i])
- }
- }
- function drawGameOverScreen(points) {
-
- context.clearRect(0, 0, canvas.width, canvas.height)
- context.fillStyle = "lightgrey"
- context.strokeStyle = "lightgrey"
- context.font = "15pt a"
- context.fillText("Game Over", 320, 200)
- context.fillText(points + " Points", 320, 230)
- }
- //Game loop stuff
- var now, dt, last = timestamp();
- function timestamp() {
- return window.performance && window.performance.now ? window.performance.now() : new Date().getTime();
- }
- var player_tick = 0
- var snacc_tick = 0
- function tick() {
- now = timestamp()
- dtime = (now - last) / 1000 //in seconds
- last = now
-
- let redraw = false
-
- player_tick += dtime
- if (player_tick >= 0.15) {
- player.move()
- redraw = true
- player_tick -= 0.15
- }
- snacc_tick += dtime
- if (snacc_tick >= 0.05) {
- snacc.tick()
- redraw = true
- snacc_tick -= 0.05
- }
-
- if (game_going) {
- if (redraw) {
- redrawField()
- }
- requestAnimationFrame(tick);
- } else {
- drawGameOverScreen(points)
- }
- }
- function start() {
- //replace start button with restart button
- var startbtn = document.getElementById("start_button")
- startbtn.innerHTML = "RESTART"
-
- //start game
- player = new Player(Math.floor(field_width / 2), Math.floor(field_height / 2), 6)
- addSnacc(1)
- points = 0
- player_tick = 0
- snacc_tick = 0
- now = timestamp()
- last = now
- game_going = true
- redrawField()
- requestAnimationFrame(tick);
- }
|