0

(Heads up I literally started programming like 1 week ago)

So I'm trying to use node.js and socket.io to make a simple multiplayer snake game. I also wanted to use my custom domain (https://trononline.tech (it has a snake game, but not the one I want)), but I cant do that without this console error: https://ibb.co/RhpHK5H

It's really annoying and no matter what I try it doesn't seem to change.

My code:

//server.js
const io = require('socket.io')();
const { initGame, gameLoop, getUpdatedVelocity} = require('./game');
const { FRAME_RATE } = require('./constants');
const{ makeid } = require('./utils')

const state = {};
const clientRooms = {};

io.on('connection', client => {
    const state = initGame;

    client.on('keydown', handleKeydown);
    client.on('newGame', handleNewGame);
    client.on('joinGame', handleJoinGame);

    function handleJoinGame(gameCode) {
        const room = io.sockets.adapter.rooms[gameCode];

        let allUsers;
         if (room) {
             allUsers = room.sockets;
         }
         let numClients = 0;
         if (allUsers) {
             numClients = Object.keys(allUsers).length;
         }
         if (numClients === 0) {
             client.emit('unknownGame');
             return;
         } else if (numClients > 1) {
             client.emit('tooManyPlayers');
             return;
         }
         clientRooms[client.id] = gameCode;

         client.join(gameCode);
         client.number = 2;
         client.emit('init', 2);

         startGameInterval(gameCode);
    }

    function handleNewGame() {
        let roomName = makeid(5);
        clientRooms[client.id] = roomName;
        client.emit('gameCode', roomName);

        state[roomName] = initGame();

        client.join(roomName)
        client.number = 1;
        client.emit('init', 1);
    }

    function handleKeydown(keyCode) {
        const roomName = clientRooms[client.id];

        if (!roomName) {
            return;
        }

        try {
            keyCode = parseInt(keyCode);
        } catch(e) {
            console.error(e);
            return;
        }
        const vel = getUpdatedVelocity(keyCode);
            if (vel) {
                state[roomName].players[client.number - 1].vel = vel;
            }
    }

    startGameInterval(client, state);
});

function startGameInterval (roomName) {
   const intervalId = setInterval(() => {
      const winner = gameLoop(state[roomName]);

      if(!winner) {
         emitGameState('roomName', state[roomName]);
      } else {
         emitGameOver(roomName, winner);
         state[roomName] = null;
         clearInterval(intervalId);
      }

   }, 1000 / FRAME_RATE);
}
function emitGameState(roomName, state) {
    io.sockets.in(roomName)
        .emit('gameState', JSON.stringify(state));
}

function emitGameOver(roomName, winner) {
    io.sockets.in(roomName)
        .emit('gameOver', JSON.stringify({ winner }))
}

//index.js

const FOOD_COLOUR = '#FF0000';

const socket = io("https://trononline.tech/snake");


socket.on('init', handleInit);
socket.on('gameState', handleGameState);
socket.on('gameOver', handleGameOver);
socket.on ('gameCode', handleGameCode);
socket.on('unknownGame', handleUnknownGame);
socket.on('tooManyPlayers', handleTooManyPlayers);

const gameScreen = document.getElementById('gameScreen');
const initialScreen = document.getElementById('initialScreen');
const newGameButton = document.getElementById('newGameButton');
const joinGameButton = document.getElementById('joinGameButton');
const gameCodeInput = document.getElementById('gameCodeInput');
const gameCodeDisplay = document.getElementById('gameCodeDisplay')

newGameButton.addEventListener('click', newGame);
joinGameButton.addEventListener('click', joinGame);


function newGame() {
    socket.emit('newGame');
    init();
}

function joinGame() {
    const code = gameCodeInput.value;
    socket.emit('joinGame', code);
    init();

}

let canvas, ctx;
let playerNumber
let gameActive = false;

function init() {
    initialScreen.style.display = "none";
    gameScreen.style.display = "block";

    canvas = document.getElementById('canvas');
    ctx = canvas.getContext('2d')

    canvas.width = canvas.height = 600;

    ctx.fillStyle = BG_COLOUR;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    document.addEventListener('keydown', keydown);
    gameActive = true;
}
function keydown (e) {
    socket.emit('keydown', e.keyCode);
}
function paintGame(state) {
    ctx.fillStyle = BG_COLOUR;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    const food = state.food;
    const gridSize = state.gridSize;
    const size = canvas.width / gridSize;

    ctx.fillStyle = FOOD_COLOUR;
    ctx.fillRect(food.x * size, food.y * size, size, size);

    paintPlayer(state.players[0], size, SNAKE1_COLOUR);
    paintPlayer(state.players[1], size, SNAKE2_COLOUR);
}

    function paintPlayer(playerState, size, colour) {

        const snake = playerState.snake;

        ctx.fillStyle = colour;
        for (let cell of snake) {
            ctx.fillRect(cell.x * size, cell.y * size, size, size);
        }
    }
function handleInit (number) {
    playerNumber = number;
}

function handleGameState(gameState) {
    if (!gameActive) {
        return;
    }
    gameState = JSON.parse(gameState);
    requestAnimationFrame(() => paintGame(gameState));
}
function handleGameOver(data) {
    if (!gameActive) {
        return;
    }

    data = JSON.parse(data);

    if (data.winner === playerNumber) {
        alert("You win! :^)");
    } else {
        alert("You lose. :^(")
    }
    gameActive = false;
}
function handleGameCode(gameCode) {
    gameCodeDisplay.textContent = gameCode;
}
function handleUnknownGame() {
    reset();
    alert("Unknown game code")
}

function handleTooManyPlayers() {
reset();
alert("This game is already in progress");
}
function reset() {
    playerNumber = null;
    gameCodeInput.value = "";
    initialScreen.style.display = "block";
    gameScreen.style.display = "none";
}
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>MultiPlayer Snake</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

    <style>
        #gameScreen {
            display: none;
        }
    </style>
</head>
<body>
<section class="vh-100">
    <div class="container h-100">

        <div id="initialScreen" class="h-100">
            <div class="d-flex flex-column align-items-center justify-content-center h-100">
                <h1>Multiplayer Snake</h1>
                <button
                        type="submit"
                        class="btn btn-success"
                        id="newGameButton"
                >
                    Create New Game
                </button>
                <div>OR</div>
                <div class="form-group">
                    <label for="gameCodeInput"></label><input type="text" placeholder="Enter Game Code" id="gameCodeInput"/>
                </div>
                <button
                        type="submit"
                        class="btn btn-success"
                        id="joinGameButton"
                >
                    Join Game
                </button>
            </div>
        </div>

        <div id="gameScreen" class="h-100">
            <div class="d-flex flex-column align-items-center justify-content-center h-100">

                <h1>Your game code is: <span id="gameCodeDisplay"></span></h1>

                <canvas id="canvas"></canvas>
            </div>
        </div>

    </div>
</section>

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
<script src="index.js"></script>
</body>
</html>

To be honest I don't know what I've tried yet because they were mostly just minor tweaks that resulted in nothing.

Any help is greatly appreciated!

1 Answers1

0

You are making HTTP requests to your domain name trononline.tech from localhost. Since these names do not match, this counts as a cross-origin HTTP request. By default, this is not permitted to protect your website but you can enable it manually. See this MDN doc about CORS headers and this NPM module.

See this answer from apsiller for more information.

boranseckin
  • 335
  • 2
  • 12
  • For the NPM module, where do I use it? On my custom domain, or in a file in the code of the game? And which file would I do it in? – SupremeButter May 17 '21 at 01:09
  • You should use the module in your backend server for the game. If you are not already using it, I suggest looking into [expressjs](https://expressjs.com/). – boranseckin May 17 '21 at 06:19