Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!doctype html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title><Stream Snake Game></title>
- <style></style>
- <script src="/socket.io/socket.io.js"></script>
- <script src="http://<%= host %>:<%= port %>/js/source.js"></script>
- </head>
- <body>
- </body>
- <script>
- "use strict";
- // classes
- function vec2(x, y) {
- this.x = x;
- this.y = y;
- }
- function element(position, color) {
- this.position = position;
- this.color = color;
- }
- function player(user, entity) {
- this.user = user;
- this.head = entity;
- this.velocity = new vec2(0, 0);
- this.links = [];
- this.targetId = -1;
- this.speed = 1.0;
- this.trailSpeed = 1.0;
- this.interval = null;
- }
- function collectable(id, entity) {
- this.id = id;
- this.position = entity.position;
- this.color = entity.color;
- }
- function engine(tileSize, pickupAmount, canvasPadding) {
- this.tileSize = tileSize;
- this.padding = canvasPadding;
- this.pickupAmount = pickupAmount;
- this.font = {
- size: 22,
- color: 'pink'
- };
- // Set in on load
- this.gridSize = new vec2(0, 0);
- this.canvas = null;
- this.context = null;
- this.interval = -1;
- // set in on load
- this.snakes = [];
- this.pickups = [];
- // player stats
- this.minCollisionLinks = 4;
- this.maxBotTail = 7;
- this.speedBoost = 1.0;
- this.highPlayer = null;
- //this.highestEver = null;
- }
- // init vars
- const debug = {
- info: {},
- position: new vec2(10, 100),
- index: 0,
- spacing: 17,
- font: {
- size: 16,
- color: 'white'
- }
- }
- const game = new engine(new vec2(20, 20), 5, 20);
- const colors = ["lime", "yellow", "purple", "cyan", "orange", "red"]; //game.context.fillStyle = "lime";
- // game methods
- function addPlayer(data) {
- const user = data.user;
- const username = data.user.username;
- const color = data.user.color === null ? colors[Math.floor(Math.random() * colors.length)] : data.user.color;
- const hasPlayer = game.snakes.hasOwnProperty(username);
- if(hasPlayer === false) {
- const snake = new player(user, new element(randomGridPosition(), color));
- addTail(snake);
- game.snakes[username] = snake;
- }
- }
- function addTail(snake) {
- // add to tail
- snake.links = [];
- for(let i = 0; i < game.minCollisionLinks; i++) {
- snake.links.push(new element(new vec2(snake.head.position.x, snake.head.position.y), snake.head.color));
- }
- }
- function targetPickup(data) {
- const targetId = parseInt(data.command, 10);
- if(isNaN(targetId)) return;
- const username = data.user.username;
- if(game.snakes.hasOwnProperty(username)) {
- const snake = game.snakes[username];
- snake.targetId = targetId;
- }
- }
- function createAndSetupGameObjects() {
- // create initial players
- for (let index = 0; index < 1; index++) {
- addPlayer({user: {username: 'bot', color: 'red'}});
- game.snakes['bot'].targetId = Math.floor(Math.random() * (game.pickupAmount - 1));
- //game.snakes['bot'].speed = 3;
- //game.snakes['bot'].trailSpeed = 3;
- setIdleTimeout(game.snakes['bot']);
- }
- //game.highPlayer = game.snakes['bot'];
- // create initial collectables
- for (let index = 0; index < game.pickupAmount; index++) {
- game.pickups.push(new collectable(index, new element(randomGridPosition(), colors[index % colors.length])));
- }
- }
- function resetPlayer(snake) {
- snake.head.position = randomGridPosition();
- snake.targetId = -1;
- snake.velocity.x = 0;
- snake.velocity.y = 0;
- addTail(snake);
- }
- function setIdleTimeout(snake) {
- if(snake.interval !== null) {
- clearInterval(snake.interval);
- }
- snake.interval = setTimeout(function() {
- if (game.snakes.hasOwnProperty(snake.user.username)) {
- delete game.snakes[snake.user.username];
- }
- }, 60 * 1000 * 5);
- }
- function debugInfo() {
- //debug.info.players = game.snakes;
- /*debug.info.canvasWidth = game.canvas.width;
- debug.info.canvasHeight = game.canvas.height;
- debug.info.game.snakes = game.snakes;
- debug.info.rndGX = Math.floor(Math.random() * game.gridSize.x);*/
- }
- function update(deltaTime) {
- for (let key in game.snakes) {
- if (!game.snakes.hasOwnProperty(key)) continue;
- const snake = game.snakes[key];
- if(snake.targetId !== -1 && snake.targetId < game.pickups.length) {
- let target = game.pickups[snake.targetId];
- if(Math.floor(snake.head.position.x) < Math.floor(target.position.x)) {
- moveRight(snake);
- } else if(Math.floor(snake.head.position.x) > Math.floor(target.position.x)) {
- moveLeft(snake);
- } else if(Math.floor(snake.head.position.y) < Math.floor(target.position.y)) {
- moveDown(snake);
- } else if(Math.floor(snake.head.position.y) > Math.floor(target.position.y)) {
- moveUp(snake);
- }
- }
- // update snake position
- snake.head.position.x += snake.velocity.x * snake.speed * deltaTime;
- snake.head.position.y += snake.velocity.y * snake.speed * deltaTime;
- // wrap snake position for high level game.snakes
- if(snake.head.position.x < 0) {
- //snake.head.position.x = game.gridSize.x - 1;
- resetPlayer(snake);
- }
- if(snake.head.position.x > game.gridSize.x - 1) {
- //snake.head.position.x = 0;
- resetPlayer(snake);
- }
- if(snake.head.position.y < 0) {
- //snake.head.position.y = game.gridSize.y - 1;
- resetPlayer(snake);
- }
- if(snake.head.position.y > game.gridSize.y - 1) {
- //snake.head.position.y = 0;
- resetPlayer(snake);
- }
- // update snake links
- for(let i = 0; i < snake.links.length; i++) {
- const link = snake.links[i];
- let targetPos = new vec2(0, 0);
- if(i == 0) {
- targetPos = snake.head.position;
- }
- else {
- targetPos = snake.links[i - 1].position;
- }
- const dir = new vec2(targetPos.x - link.position.x, targetPos.y - link.position.y);
- const moveDir = new vec2(Math.min(1, dir.x), Math.min(1, dir.y));
- link.position.x += moveDir.x * snake.trailSpeed * deltaTime;
- link.position.y += moveDir.y * snake.trailSpeed * deltaTime;
- }
- // check game.pickups collision
- for (let j = 0; j < game.pickups.length; j++) {
- const pickup = game.pickups[j];
- if(checkCollision(snake.head.position, pickup.position, new vec2(1, 1))) {
- snake.targetId = -1;
- pickup.position = randomGridPosition();
- // add to tail
- snake.links.unshift(new element(new vec2(snake.head.position.x, snake.head.position.y), pickup.color));
- if(key === 'bot') {
- game.snakes['bot'].targetId = Math.floor(Math.random() * (game.pickups.length - 1));
- if(snake.links.length > game.maxBotTail) {
- while(snake.links.length > game.minCollisionLinks) {
- snake.links.pop();
- }
- }
- }
- if(game.highPlayer === null || snake.links.length > game.highPlayer.links.length) {
- game.highPlayer = new player(snake.user, snake.head);
- game.highPlayer.links = [];
- for (let i = 0; i < snake.links.length; i++) {
- let link = snake.links[i];
- game.highPlayer.links.push(link);
- }
- sendHighPlayerToServer(game.highPlayer);
- }
- }
- }
- }
- // update game.pickups
- for (let index = 0; index < game.pickups.length; index++) {
- const pickup = game.pickups[index];
- pickup.id = index;
- }
- }
- function render() {
- // clear background
- game.context.fillStyle = "black";
- game.context.fillRect(0, 0, game.canvas.width, game.canvas.height);
- // render game.snakes
- for (let key in game.snakes) {
- if (!game.snakes.hasOwnProperty(key)) continue;
- const snake = game.snakes[key];
- game.context.fillStyle = snake.head.color;
- game.context.fillRect(snake.head.position.x * game.tileSize.x, snake.head.position.y * game.tileSize.y, game.tileSize.x - 2, game.tileSize.y - 2);
- for(let i = 0; i < snake.links.length; i++) {
- const link = snake.links[i];
- game.context.fillStyle = link.color;
- game.context.fillRect(link.position.x * game.tileSize.x, link.position.y * game.tileSize.y, game.tileSize.x - 2, game.tileSize.y - 2);
- }
- const userText = "t" + snake.targetId + " s" + snake.speed + " b" + (snake.links.length - game.minCollisionLinks) + ":" + snake.user.username;
- const textWidth = game.context.measureText(userText).width; /// width in pixels
- textWithBackground(userText, 'pink', snake.head.position.x * game.tileSize.x, snake.head.position.y * game.tileSize.y - 10, "rgba(0, 0, 255, 0.3)");
- }
- // render game.pickups
- for (let index = 0; index < game.pickups.length; index++) {
- const pickup = game.pickups[index];
- game.context.fillStyle = pickup.color;
- game.context.fillRect(pickup.position.x * game.tileSize.x, pickup.position.y * game.tileSize.y, game.tileSize.x - 2, game.tileSize.y - 2);
- const textPosX = pickup.position.x * game.tileSize.x + game.tileSize.x - 4;
- let textPosY = pickup.position.y * game.tileSize.y - 10;
- if(textPosY < game.canvas.height * 0.5) {
- textPosY += game.tileSize.y * 2.0 + 4;
- }
- textWithBackground(pickup.id, 'pink', textPosX, textPosY, "rgba(0, 0, 255, 0.3)");
- }
- // render high score
- if(game.highPlayer !== null) {
- const highText = "HIGH TAIL " + game.highPlayer.user.username + " with " + game.highPlayer.links.length + " tail segments";
- const textWidth = game.context.measureText(highText).width; /// width in pixels
- textWithBackground(highText, 'pink', game.canvas.width - textWidth - 10, 20, "rgba(0, 0, 255, 0.3)");
- }
- // render debug text
- game.context.font = `${debug.font.size}px Arial`;
- game.context.fillStyle = debug.font.color;
- debug.index = 0;
- showDebugInfo('', debug.info);
- }
- function textWithBackground(text, color, x, y, bgColor) {
- game.context.font = `${game.font.size}px Arial`;
- const textWidth = game.context.measureText(text).width; /// width in pixels
- const textHeight = 20;
- game.context.fillStyle = bgColor;
- game.context.fillRect(x - 10 - 4, y - 15 - 4, textWidth + 6, textHeight + 2);
- game.context.fillStyle = color;
- game.context.fillText(text, x - 10, y);
- }
- function showDebugInfo(name, obj) {
- Object.keys(obj).forEach((key) => {
- if(typeof obj[key] === 'object') {
- showDebugInfo(name + "." + key, obj[key]);
- }
- else {
- game.context.fillText(name + "." + key + " > " + obj[key], debug.position.x, debug.position.y + ((debug.index++) * debug.spacing));
- }
- });
- }
- function checkCollision(position1, position2, size) {
- return (position1.x > position2.x - size.x && position1.x < position2.x + size.x) &&
- (position1.y > position2.y - size.y && position1.y < position2.y + size.y);
- }
- function randomGridPosition() {
- const x = Math.floor(Math.random() * game.canvas.width / game.tileSize.x);
- const y = Math.floor(Math.random() * game.canvas.height / game.tileSize.y);
- return new vec2(x, y);
- }
- function resizeCanvasAndGrid() {
- if(game.canvas !== null) {
- // Set canvas size
- game.canvas.width = window.innerWidth - game.padding;
- game.canvas.height = window.innerHeight - game.padding;
- //Set grid size
- game.gridSize.x = game.canvas.width / game.tileSize.x;
- game.gridSize.y = game.canvas.height / game.tileSize.y;
- }
- }
- function processCommandData(data) {
- if(data.user.username === 'callowcreation') {
- data.user.username = 'bot';
- }
- let username = data.user.username;
- if(data.command === 'join') { // not a player yet, may want to join
- addPlayer(data);
- } else if(data.command === 'boost') {
- if(game.snakes.hasOwnProperty(username)) {
- const snake = game.snakes[username];
- if(snake.links.length > game.minCollisionLinks) {
- snake.speed += game.speedBoost;
- snake.trailSpeed = snake.speed;
- snake.links.pop();
- setTimeout(function() {
- if(snake.speed > 0) {
- snake.speed -= game.speedBoost;
- snake.trailSpeed = snake.speed;
- }
- }, 5000);
- }
- }
- } else {
- const targetId = parseInt(data.command, 10);
- if(isNaN(targetId) === false) { // might be a target
- targetPickup(data);
- }
- }
- if(game.snakes.hasOwnProperty(username)) {
- const snake = game.snakes[username];
- setIdleTimeout(snake);
- }
- }
- function moveUp(snake) {
- snake.velocity.x = 0;
- snake.velocity.y = -1;
- }
- function moveDown(snake) {
- snake.velocity.x = 0;
- snake.velocity.y = 1;
- }
- function moveLeft(snake) {
- snake.velocity.x = -1;
- snake.velocity.y = 0;
- }
- function moveRight(snake) {
- snake.velocity.x = 1;
- snake.velocity.y = 0;
- }
- // Cross-browser support for requestAnimationFrame
- const w = window;
- const requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;
- // for delta time
- let then = Date.now();
- // The main game loop
- const main = function () {
- const now = Date.now();
- const delta = now - then;
- update(delta / 1000);
- debugInfo();
- render();
- then = now;
- // Request to do this again ASAP
- requestAnimationFrame(main);
- };
- // window set up
- window.onresize = function(event) {
- resizeCanvasAndGrid();
- };
- window.onload=function() {
- // Create canvas
- game.canvas = document.createElement("canvas");
- // Get drawing buffer
- game.context = game.canvas.getContext("2d");
- // Add canvas to dom
- document.body.appendChild(game.canvas);
- resizeCanvasAndGrid();
- // Setup Game Objects
- createAndSetupGameObjects();
- // Server listeners
- socket.on('snake-control', processCommandData);
- // Start game loop
- main();
- }
- function sendHighPlayerToServer(highPlayer) {
- socket.emit('high-player', { data: highPlayer });
- }
- </script>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement