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!!
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
- Drawing planes and Moving the Camera there
- Drawing bullets
- 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
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.
Food ie Selenium
Some metal... these are like the slither io orbs. The gamemaker particle effects make it look a lot like that.
Levelling system
The levelling system uses a formula.... This formula will need to be updated as the game gets better but here it is
The Game Loop in Nodejs
Here,
- All the players are propelled forward according to their speed and direction
- 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.
- If players are close to the food, it is destroyed and added to their score.
- 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);
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;
}
}
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
- Improve the game - Adding more SFX and VFX to make it look better, and improve the levelling up and evolution
- Develop a following for constant feedback. iogames.forum is the best place imo and then there are other io game sites.
- 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
- 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)
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.
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.
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!
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!
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
All the normal names for the ships and then “if you want to look like a fool”
lolol yes
Awsome Bro 🔥
Thanks bro