You are on page 1of 20

BITS at Night ✈

Goal Type

Status Done ✨
Tags

Due

Date

Language

Prelude
Horror - Top Down Game?
Dev flow
1. Basic topdown movement system
Random cheap map with walls and a player
Collision Control Sytem
Camera
Result
2.Menu to enter game
Result
3. Updating Coordinates on Node
Setting Up node js server
Setting up GMS2
Ask server to create a player
Updating player info
Sending updates to the server
Result - Server Updating this
4. Make other players appear and disappear
Sending position updates from node
Receiving the updates on GMS
Bug report :
Result
5. Lighting System
Jobo Lighting System
GMS Official Simple Tutorial Lighting System
Result of Lighting and multiplayer
6. Guns Concept
Generating a Bullet
Event to send this to server.
Server Handling this (Part 1 - telling other players someone got shot)
How GMS makes it look like a player shot a bullet
7. Authoritative Bullets
shootBullet Function
Using this to kill the player who got shot
Results
8. Health
Adding Health Effects
Cool progressive Result After Adding Healthbars, Blinkness
9. Ghosts
Differences in Ghosts and Normal Players
Adding a body attribute
Adding Logic
Turning P into G after death

BITS at Night✈ 1
Changes to oPlayer, oEnemy
Ghosts are like air, they cant be shot
Ghosts Sprite
Final Result After Ghosts Integration 💜💜
9. Killing Ghosts
The Math of it…
Making the Function in js
ghostHealthReducer Function
Result…
10. Ghosts Attacking Players
Ghost Scare Check Function
The Jumpscare from Node
Handling the Jumpscare in GMS2
Result
11. Jumpscares and Freaky Music
Freaky Theme Music
Transition to Jumpscares Music
Real Jumpscare Music and Jumpscare
Adding Gunshot sounds
12. BITS Map and Walls Config
Wall Placement
13. Random Spawn System , Streetlights
Spawn System in Node.js
Respawn ghosts !!! Very imp
Cute streetlights
Streetlight Placement
14. Major UI fixes
Kill Count
Adding to Kills
Done with testing, it works 🙂
Ghosts and Players count
Death UI saying you died and all
Messages UI
Server sent messages
How GMS handles this
Result
Fullscreen Death Alert
In the ghost health reducer function
How GMS Handles this
Designing the Player Stats screen after you have fully died
15. Leaderboard and Minimap
Leaderboard
Minimap
16. Hosting and Playability
Bullets

20 August

Prelude
Horror - Top Down Game?
Okay so I was thinking of bits at night, a horror multiplayer game based on illumination.

So firstly its topdown shooter multiplayer kind. Easy to make that part with node.

For the map I really dont know design so its way out of my league to design that so google earth + some editing can make you
a nice map.

BITS at Night✈ 2
Then we need a lot of darkness but the user can toggle a torch light and move around a little.

So there are other players and monsters. The most interesting game mode would be battle royale. For now keep it simple 1
room. Players can kill each other and monsters are bots that attack people.

Dev flow
1. Basic top down movement system

2. Menu to Enter game

3. Updating coordinates on node (try server authority)

4. Make other players appear and disappear.

5. map with walls - can be done later anytime

6. Illumination and torch and whatnot

7. Monsters AI - Randomly spawning and attacking you

8. Jumpscares

9. Battle royale system (restrictions on joining and alive count)

Okay this looks fine. I think I can start. Ill make a desktop folder and repo

1. Basic topdown movement system


Random cheap map with walls and a player
Draw some walls and make a circular player object with like a gun or a torch

Okay important point in coding….. don’t get suck on anything but the current goal. Thats all that matters.

I think this is fine.

So I integrated the Walls collision system but its not exactly fine. The guy is getting stuck in walls. So Im trying to have like a
system that brings the player back to where he came from.

Collision Control Sytem

BITS at Night✈ 3
I have an array of old coordinates values. So whenever a player is wall stuck itll take the player back I guess?

Or wait, if a wall is close , push the guy away from the wall

var move = keyboard_check(ord("W")) - keyboard_check(ord("S"))


speed = 5*move

if(point_distance(x,y, mouse_x , mouse_y) > 30){


direction = point_direction(x,y, mouse_x , mouse_y);

if(position_meeting(x + lengthdir_x(speed , direction),y + lengthdir_y(speed , direction),oWall)){


//colliding with a wall - no freedom in image angle , only in direction
speed =0

}else{
//not colliding with a wall
image_angle = direction;

Finally something that works!. It was getting annoying. And I think the most important thing would be camera now

Camera
This is just boilerplate so I dont think its so important to log about it much

Just a slow interpolated camera

I changed up the values and the movement is looking really nice now 🙂
Result

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/df4e91ba-e974-4132-8907-01d1e35e71a8/screen_rec.mp4

2.Menu to enter game


I will make a new room. Basic room. Just takes in your name and then sends you to the multiplayer stuff.

So I added some font and made some buttons and text and a field for your name and all

//oMenu Create
global.username = "";
keyboard_string=""

//oMenu Draw GUI


var bh = camera_get_view_height(view_current)
var bw = camera_get_view_width(view_current)
var scale = .4*bw/1300; //if we want to scale up the font
var mx = device_mouse_x_to_gui(0)
var my = device_mouse_y_to_gui(0)

draw_set_color(c_white)
draw_set_font(fPressStart2P)
draw_set_halign(fa_center);
draw_set_valign(fa_center);
draw_text_transformed(bw*0.5 , bh*0.25 , "BITS at Night" , scale, scale ,0 )

BITS at Night✈ 4
draw_text_transformed(bw*0.5 , bh*0.5 , "Enter a username" , 0.5*scale, 0.5*scale ,0 );

//Enter button
draw_set_color(c_green)
draw_roundrect(bw*0.4 , bh*(0.65-0.04) , bw*0.6 ,bh*(0.65+0.04) ,false )
draw_set_color(c_white)
draw_text_transformed(bw*0.5 , bh*0.66 , "PLAY" , scale, scale ,0 )
if(mouse_check_button_pressed(mb_left)){

var c1 = mx < bw*0.6


var c2 = mx > bw*0.4
var c3 = my > bh*(0.65-0.04)
var c4 = my < bh*(0.65+0.04)
if(c1 and c2 and c3 and c4){
room_goto(rGame)
}
}

//Textbox for name


draw_set_color(c_white)
draw_roundrect(bw*0.4 , bh*(0.4-0.04) , bw*0.6 ,bh*(0.4+0.04) ,false )
draw_set_color(c_black)
if( string_length(keyboard_string) > 10){
keyboard_string = string_delete(keyboard_string ,10 , 1 )
}

draw_text_transformed(bw*0.5 , bh*0.4 , keyboard_string , 0.5*scale, 0.5*scale ,0 )

Result
Ok this is cute

BITS at Night✈ 5
3. Updating Coordinates on Node
Setting Up node js server
So in the main repo Im making a folder called server for the node project

Then the boilerplate websocket server stuff

Setting up GMS2
Async networking boilerplate

Next lets set up the event based communication stuff.

Ask server to create a player


So in the oMenu after the guy clicks on PLAY I am going to tell the server to “create_me”

//DEAD PLAYERS CAN BE GHOSTS — ok so my mom cracked a joke on the walls movement bugs and it let me to a very
cool mechanic
Battle royale + horror : dead players become ghosts and can haunt and kill existing players. Dead ghosts are just
spectators.

BITS at Night✈ 6
So the main part is the players array that holds all the players. So we will have all our player properties here. x , y , name , id
and everything.

Some more properties that we will add later is torchLight switched on?

We are also telling the new guy and everyone already existing on the server that here is someone new

Updating player info


I want to do this using the server so we have good authority but because we have walls I cant trust …

So basically the client would send the latest coordinates

I created a global to hold if the torchlight is on or not

BITS at Night✈ 7
I added an angle and torch attribute here in node player info too

Sending updates to the server

Result - Server Updating this

BITS at Night✈ 8
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/35ddc11e-f23e-4ab6-a6cd-fb0fa9f4c4f9/coordinates_updati
ng.mp4

So I was running this on chrome it was lame fps. Edge was fine. I guess its something to do with the …Okay I disabled webGL it
works fine.

4. Make other players appear and disappear


Sending position updates from node

I need to tell every player about every player. So I will make a new function for that that repeats every 16 ms or so.

This function grabs a players info, puts it in a dictionary , and sends that dictionary over to everyone

function stateUpdate() {
for (let i in players) {
var sendThis = {
eventName: "state_update", //grabbing this player's info
id: players[i].id,
x: players[i].x,
y: players[i].y,
A: players[i].A,
T: players[i].T,
}

for (let j in players) {


players[j].socket.send(JSON.stringify(sendThis)); //sending it to every other player
}
}

setTimeout(stateUpdate, 1000 / 30);


}

Receiving the updates on GMS


Now we need to update these player coordinates and angle to their respective oEnemy instances

BITS at Night✈ 9
Bug report :
When webgl is set to disabled then the fps is good but after 3 oEnemies the game doesnt update their positions

When webgl is set to required then the fps is low asf but oENemies are getting updated. Here is auto detect

When webgl is set to auto detect then the fps is bad in chrome but players are updating. In edge however everything is
working perfectly.

Maybe its that hardware acceleration that I switched off in chrome? Lets try switching it on and playing.

Yes I was right…… I guess the movement could be more smooth though. Lets amp up the interpolation.

Nope its worse. I set it to half half and lets increase nodejs state update frequency

Wow, its just so damn smooth. I fixed it. I changed it up from 50ms to 16ms

Result

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/597ee731-a41b-45b0-94a7-5eaa5b78a5ff/coordinates_upd
ating.mp4

The lighting system seems cool… Ill do that tomorrow. Dont fucking think about it now. Your progress for today was pretty good.

23 August

5. Lighting System
So what I’m going for is dynamic lighting. Now I guess I have to understand surfaces and whatnot for that.

Okay I followed the tutorial and pretty much understood. We are drawing the lights(non shadow) as a polygon

Actually lights first then polygon. for shadow

BITS at Night✈ 10
First the light sprite is drawn in oLigthing. Then the walls
///see shaun spalding jobo thing
24 August
Okay I need to see the shaun spalding jobo video. If my systems dont work I will use that extension.
Ok so my systems dont work and I’m going to use that extension 👏👏👏
Even this could have worked

https://gamemaker.io/en/blog/coffee-break-tutorial-simple-lighting-gml

Jobo Lighting System


Okay I pretty much understood shaun spaldings tutorial.

Okay this system is trash on html5 and websockets primarily use h5 so I cant, fuck it

GMS Official Simple Tutorial Lighting System


So I followed that tutorial and it wasnt so bad really. This is the end result and this is just the beginning.

BITS at Night✈ 11
So in the oLighting object you can make different lights work for different objects and its really cool.

I can also add streetlights and all

Result of Lighting and multiplayer

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/385b432f-6c1a-401d-8223-fda2ea74bf49/multiplayer_with_l
ights.mp4

6. Guns Concept
So for the shooting dynamic, itll be part server authority so thats good right? Ill draw some simple bullet sprite and add some
speed

BITS at Night✈ 12
Generating a Bullet

The result looks a bit like this

Event to send this to server.


We need to tell the server we shot a bullet.

BITS at Night✈ 13
Server Handling this (Part 1 - telling other players someone got shot)

How GMS makes it look like a player shot a bullet

case "bullet_shot":

with(oEnemy){

BITS at Night✈ 14
if(clientId == real(realData[?"shooter"]) ){
//creating a bullet
var bullet = instance_create_layer(x +lengthdir_x(13 ,direction -85) ,y+lengthdir_y(13 ,direction-85) ,"Instances",oBullet);
bullet.speed = 10;
bullet.direction = image_angle;
bullet.image_angle = bullet.direction;
reloading = 20;

//recoil animation
x -= lengthdir_x(10 , direction)
y -= lengthdir_y(10 , direction)

}
}
break;

7. Authoritative Bullets
Right now the bullets dont really do anything. We need code that traces the path of the bullets and checks if it is hitting someone.
This also needs to be done by a centralised authority , so the node server.

shootBullet Function

function shootBullet(shootersId) {

var frame = 0

var init_x = 0;
var init_y = 0;
var angle = 0;

for (let i in players) {


if (players[i].id == shootersId) {
init_x = players[i].x;
init_y = players[i].y;
angle = players[i].A;
}
}

//trace the trajectory of the bullet


while (frame < 400) {
var current_x = init_x + Math.sin(3.1415 / 180 * angle);
var current_y = init_y - Math.sin(3.1415 / 180 * angle);

//we have the current coordinates of the bullet. Now check if it is colliding with someone
for (let i in players) {
var distance = Math.sqrt((current_x - players[i].x) ** 2 + (current_y - players[i].y) ** 2);

if (distance < 16) {


if (players[i].id != shootersId) { //make sure friendly fire doesnt exist
return players[i].id; //id of the guy who got shot
}

}
}
}

return -1; ///-1 means the bullet hasnt hit anyone yet
}

Here we are tracing each step of the bullet in the direction in which it was fired and checking if it is hitting any player

It returns the id of the player we hit, or -1 if we hit no one

We do this by using perpendicular distance from the line in which the bullet was shot.

BITS at Night✈ 15
Using this to kill the player who got shot

By kill I mean destroy websocket.

So we are basically destroying that player for everyone else.

oh fuck i forgot to close the while loop in the shootBullet func

BITS at Night✈ 16
……also for x its cos not sin…lot of silly errors there.

Results
Yess the player we shoot is dying! This is extremely cool but I do think we could add a health variable. 1 shot to kill a player seems
too lame

8. Health
Just like any other property like x , y , angle , now we will also use Health, denoted by H in nodejs

And when a player is hit by a bullet, I am reducing the health by 30.

I also drew healthbars for everyone so this is easier to see.

25 August

Adding Health Effects


So when like you are getting shot adrenaline pumps up and you can see a little more than normal.

So the lighting is controlled in oLighting, thats where I will make changes

BITS at Night✈ 17
So darkness always resets itself. Once health changes, let me change darkness to 0.7 or something.

In the oPlayer Step

Also the shader blink thing.

Cool progressive Result After Adding Healthbars, Blinkness

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/05d7c5a5-4000-4456-8e2c-0aed0ef789a3/blinky_health.mp
4

9. Ghosts
Differences in Ghosts and Normal Players
1. Ghosts can see in the dark

2. Ghosts have no healthbar or health concept. They are gone if light falls on them for like 300ms. Maybe they do need health of
some sort, but no healthbar shown

3. Ghosts can go through walls

4. Ghosts can jumpscare players and kill them.

Adding a body attribute


Like body of the player. “P” , “G” , “D”

BITS at Night✈ 18
So player or ghost or dead(like out of the game)

Adding Logic
Turning P into G after death

Changes to oPlayer, oEnemy


As a ghost, dont show healthbar or walls….

Ghosts are like air, they cant be shot


Changes to the bullet tracing code. Shoot only if person is a P

BITS at Night✈ 19
Ghosts Sprite
This is what I created in aseprite. Yeah I know top views suck for this….

Final Result After Ghosts Integration 💜💜


https://s3-us-west-2.amazonaws.com/secure.notion-static.com/78fa7c8f-9ab1-4b8c-8158-344cae7ea429/ghosts_integratio
n.mp4

BITS at Night✈ 20

You might also like