Made an .io game in 10 days✈️

lilshake

Abhishek

Posted on October 31, 2023

Made an .io game in 10 days✈️

Hello Everyone!
Let's talk gamedev, better yet fast addictive .io games. And how I made
StellarClash.io✈️ in 10 days.

This is a real .io game!! You can open 2 tabs on your browser and see 2 planes!!

Image description

Here is the source GitHub🐈

Basic Structure of an .io Game

Frontend - Gamemaker

You have to choose a frontend which is compatible with the HTML5 Canvas. You can directly use the canvas API if you like vanilla JS code but I used Gamemaker and it's really easy!
Because the frontend stuff is mostly just

  1. Drawing planes and Moving the Camera there
  2. Drawing bullets
  3. Showing what is happening on the server

Backend Nodejs Server

This is where all the game logic actually works.
And there is always websocket communication between client and server.

Players

Every player is treated like a point particle and is spawned at a relatively low density area of the game. All players are saved to a players array

Image description

Image description

Bullets

Shooting is important and based on your level you shoot a specific number of bullets, bullets of specific damage. And on the client side the damage of the bullet appears as its size, so you have an idea how much you'll be hurt.

Image description

Food ie Selenium

Some metal... these are like the slither io orbs. The gamemaker particle effects make it look a lot like that.

Image description

Levelling system

The levelling system uses a formula.... This formula will need to be updated as the game gets better but here it is

Image description

The Game Loop in Nodejs

Here,

  1. All the players are propelled forward according to their speed and direction

Image description

  1. All the bullets are propelled forward according to their speed and direction. If a bullet is hitting another player, the bullet is destroyed and health and kills of victim and killer are updated.

Image description

  1. If players are close to the food, it is destroyed and added to their score.
  2. Other behaviors like bots ...

Bot Creation

So bots are created when there are less players and they are made to behave very similar to normal players.

function createBots() {
  //go through the players and count how many are bots
  var botCount = 0;
  realPlayerCount = 0;
  for (var i in players) {
    var player = players[i];
    if (player.bot) {
      botCount++;
    } else {
      if (player.health > 0) {
        realPlayerCount++;
      }
    }
  }

  if (botCount < MAX_BOTS && realPlayerCount < MAX_BOTS) {
    console.log("creating a new bot");
    var spawnPoint = bestSpawnPoint(players, spawnPoints, "public");
    //for the name of the bot, 30% chance use the name from the list, 70% chance use empty string
    var botName = "";
    if (Math.random() < 0.3) {
      botName = botNames[currentBotName++];
      if (currentBotName >= botNames.length) {
        currentBotName = 0;
      }
    }

    var player = {
      clientId: clientId++,
      x: spawnPoint.x,
      y: spawnPoint.y,
      A: 0,
      N: 0,
      speed: 10,
      health: 100,
      maxHealth: 100,
      kills: Math.floor(Math.random() * 4),
      roomId: "public", ///BOTS WILL ONLY EXIST in public room
      username: botName,
      ws: null,
      bot: {
        recoil: 0,
        lifetime: 0,
      },
      skin: Math.floor(Math.random() * 7), //0-6
      lastHitTime: 0,
      recoil: 0,
    };
    player.shootingCharacteristics = getShootingCharacteristics(player.kills);

    player.speed = player.shootingCharacteristics.thrustSpeed;
    player.maxHealth = player.shootingCharacteristics.maxHealth;

    players[player.clientId] = player;

    //tell other players we created this guy
    var sendThis = {
      eventName: "create_player",
      clientId: player.clientId,
      roomId: player.roomId,
      x: player.x,
      y: player.y,
      username: player.username,
      skin: player.skin,
    };

    for (var j in players) {
      var otherPlayer = players[j];

      //check if same room
      if (otherPlayer.roomId != player.roomId) {
        continue;
      }

      if (otherPlayer.clientId != player.clientId) {
        //if ws is not null
        if (otherPlayer.ws) {
          otherPlayer.ws.send(JSON.stringify(sendThis));
        }
      }
    }
  }
}
setInterval(createBots, 1000);

Enter fullscreen mode Exit fullscreen mode

Bot Behavior

Inside the game Loop, bots are made to follow the closest player to them and once they are close enough start shooting. Note that there is some randomness allowed here to make it feel real.

if (player.bot) {
      player.bot.lifetime++;
      //recoil
      if (player.bot.recoil > 0) {
        player.bot.recoil--;
      }
      //bot logic
      //try to chase the player closest to this bot and once you are close enough, shoot

      var closestPlayer = null;
      var closestDistance = Infinity;

      for (var j in players) {
        var otherPlayer = players[j];
        //if roomId is different, skip this player
        if (otherPlayer.roomId != player.roomId) {
          continue;
        }

        //if health is 0, skip this player
        if (otherPlayer.health <= 0) {
          continue;
        }

        if (otherPlayer.clientId != player.clientId) {
          var d = distance(player.x, player.y, otherPlayer.x, otherPlayer.y);
          if (d < closestDistance) {
            closestDistance = d;
            closestPlayer = otherPlayer;
          }
        }
      }

      if (closestPlayer) {
        //chase this player
        var dx = closestPlayer.x - player.x;
        var dy = closestPlayer.y - player.y;

        //if the player is close enough, shoot
        if (closestDistance < 100 + 5 * player.kills) {
          if (player.bot.recoil <= 0) {
            //rotate the bot to face the player
            player.A = Math.atan2(-dy, dx) * (180 / Math.PI);

            ///repeat x times

            for (var k = 0; k < player.shootingCharacteristics.spread; k++) {
              var bullet = {
                x: player.x,
                y: player.y,
                A: player.A + Math.random() * 10 - 5,
                speed: player.shootingCharacteristics.bulletSpeed,
                damage: player.shootingCharacteristics.damage,
                firedBy: player.clientId,
                roomId: player.roomId,
                lifetime: 120,
                username: player.username,
              };
              bullets[bulletId++] = bullet;
            }

            //recoil
            player.bot.recoil = player.shootingCharacteristics.recoilTime;
            player.recoil = player.shootingCharacteristics.recoilTime;
          }
        } else {
          //just make the bot move in the direction of the player 5 pixels
          var fakeN = 0.2 + Math.abs(Math.sin(player.kills)) / 2;
          player.x += (dx / closestDistance) * player.speed * fakeN;
          player.y += (dy / closestDistance) * player.speed * fakeN;

          //rotate the bot to face the player
          var newA =
            Math.atan2(-dy, dx) * (180 / Math.PI) + 5 * Math.random() - 2.5;
          //lerp player.A to newA
          player.A = (player.A + newA) / 2;
        }
        //check if player is out of bounds
        var correctedPosition = outOfBounds(player.x, player.y);
        player.x = correctedPosition.x;
        player.y = correctedPosition.y;
        continue;
      }
    }
Enter fullscreen mode Exit fullscreen mode

Deployment and public facing.

The nodejs websocket server is deployed on heroku for just 7$ a month!!! That is my game server, only 7$🤑🤑🤑💵💵

It is hosted in US so players like me from India can face some lag. But because of extreme lerping, it's smooth lag which kind of does not feel as bad.

The actual game is hosted with Firebase hosting. I bought the domain on Namecheap for like 42$ and then deployed using the firebase CLI.

Future Plans

The next step would be to

  1. Improve the game - Adding more SFX and VFX to make it look better, and improve the levelling up and evolution
  2. Develop a following for constant feedback. iogames.forum is the best place imo and then there are other io game sites.
  3. Iterate 1 and 2 so that players are funnelled to my twitter and iogames.forum where they get updates on the games and can interact with me and that will make the game better
  4. Ads by Google - I was magically approved as a google H5 Games ad associate but I don't have the basic adsense approval on my site yet😶... so I have to figure some stuff out but hopefully I'll be able to earn a little from this!

Thank you for reading this post! Follow me on
Twitter🐦 for more updates!!

💖 💪 🙅 🚩
lilshake
Abhishek

Posted on October 31, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Made an .io game in 10 days✈️
gamedev Made an .io game in 10 days✈️

October 31, 2023