DEV Community

Cover image for Made an .io game in 10 days✈️
Abhishek
Abhishek

Posted on

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!!

Top comments (9)

Collapse
 
codergautam profile image
Coder Gautam

Super cool game! Also curious how you got H5 access (I just got ghosted by them). If you're interested we can collaborate on a project I'm making called GamePromote for game cross promotion and future Advertising SDK.

Collapse
 
anitaolsen profile image
Anita Olsen • Edited

Congratulations on making an .io game in 10 days! Most impressive! I even tried it out. I lasted only a few seconds the first time as I got shot down and I walked into a galaxy or what those colourful things are, and the second time, I did not know what to do (or where/who to shoot) and then a space ship appeared and took me down before I managed to take it down, haha! Maybe there should be a list of enemies or something so you know what to watch out for? For all I know, that space ship could have been friendly.

Collapse
 
lilshake profile image
Abhishek

haha I really should have explained the rules....
So like most io games every entity (in this game Jets) are all competing, and you can move around with your mouse. The closer your mouse pointer is to your plane the slower it moves.
A left click makes your plane shoot. And the glowing stuff is like food which also gives smaller boosts to your score.
The speed of the game is a lot actually, and it might actually be a bit too fast paced, maybe I should reduce the overall speed.
Thank you for playing!

Collapse
 
slobodan4nista profile image
Slobi

I like the parallax effect going on, did not expected it to work on phone but it does.
Maybe differential touch would be a good controller option.
Great work!

Collapse
 
lilshake profile image
Abhishek

Thank you!! So the layers are tiled infinitely and that along with the parallax makes it work on any screen ig.
On phones and touchscreen devices I'm planning to add a virtual joystick, so the degree to which the joystick is pulled basically defines how much to move and or shoot

Collapse
 
thecheapaudiophile profile image
Griff Polk

All the normal names for the ships and then “if you want to look like a fool”

Collapse
 
lilshake profile image
Abhishek

lolol yes

Collapse
 
taqui_786 profile image
TAQUI ⭐

Awsome Bro 🔥

Collapse
 
lilshake profile image
Abhishek

Thanks bro