A bit of how this game was made (FNAF in Godot)


Intro

So this is just a basic "tutorial" on how I made this game, and how you can make a FNAF-like game in Godot.

I first just wanna mention that the sole reason I started working on this was Tech Rules' great video on the FNAF AI, which I assume you've seen already if you're reading this. If you haven't I would highly recommend watching it here.

I won't be discussing the title screen and other things here, just the main game itself.

Something else that I have to mention is that for this project, I made the whole game in one big scene. In my opinion this is actually really bad! You end up with a giant scene that has way too much stuff in it, and in my case, a script with 750 lines (that sucks!!). I was pretty inexperienced when I made this though, so my #1 tip for beginner Godot developers is please, split stuff up into separate scenes if you can.

For FNAF-likes, I would definitely recommend at least making separate scenes for the room and the camera view, and an extra scene for when the power goes out. You can use a global scene to control all the game variables, this can be done in "AutoLoad" in the project settings. But anyways, let's just get into what I did.

Walker AI

So each enemy has an AI level, which is assigned like this:


The "level" array gets assigned the correct value depending on the night. It's taken from the "lvls" array if it's night 1 to 5, or it gets forced to a specific value if it's a custom night.

First let's talk about "walking" enemies, that walk through rooms until they get to your doors.  I have another array to control their locations:

These enemies all use timers that activate a "movement opportunity". You can use the timeout signal on a timer to achieve this.

So that's the function for a basic walker. Let's dissect it.

This was done simply so that I could easily copy-paste functions and just have to change the value of i (the index). Whenever you see "locations[i]" or just "l", that's referring to the location of this specific enemy on the map.

This if statement is how the level affects the AI. It's basically how it works in FNAF, where the AI level is really just determining the chance that they get to move.

The second part of the if statement is specific to my game. The way I did it, when the location is 0 that indicates that they're at your door. For my game, when an enemy like this is at your door, they actually get a second chance to successfully move. This makes it more likely to either get into your office, or leave if the door is closed. You don't have to include this for your game.

So what's going on here? Well, "if l!=0" means if they aren't at your door. So, a normal movement.

(this is the cheat-sheet map I used for the game)

This one in specific is somewhat random. If the location isn't 11 or 13, then they pick a random location from 8, 9, 11, or 12.

If it is 11, then they always move to 13. And if it's 13, then they try to go to your door. atdoors[1] represents who's at the right door currently, so if it's empty, then they're free to go there.

The line at the bottom is pretty important. changecam is the function that updates the camera and enemy sprites, and this is the relevant part of it:


Basically if the camera is at an enemy's location, then show their sprite and update the texture to the correct one. All walking enemies have different sprites depending on what room they're in. And if they aren't at the camera's room, then hide them.

So here's what this line is saying:

If the camera is up, and the camera location is equal to this enemy's location, and the enemy moved (either to or from this room), then update the camera view.


Now here's the second part of the movement. 

This when the enemy IS at your door. door[1] represents if the right door is closed. So if it is closed, then reset the location to either 8 or 9. If the camera is currently at that same location, then update the camera view. Finally, play a footstep sound effect.

But if the door is open, then go in the room. The game checks for this, so the moment the inroom variable isn't empty, a timer starts.  At this point you get jumpscared if you either put down the camera or the timer runs out. And that's it for this enemy!

There are other walking enemies that pick an adjacent room instead of choosing randomly, but the rest is exactly the same.

For that, I just made an array that holds all the possible values for rooms.


We subtract 8 from the location to get the index for the p array. So for example, when this enemy is in room 8, that checks index 0 of the array, which is [9,10]. So they go to either room 9 or 10. 

Other AI


This guy is my equivalent of Foxy. It has the same level check, but the cam also has to be invisible and he can't be locked. (The lock is just a timer that starts whenever you put the camera down, and has "One Shot" set to true so that it doesn't loop forever. It's very short)

 "zain" is the variable that determines his stage. Each time it goes up, it also updates his sprite, and when it hits 3 that means he's going to attack soon. At this point the run animation is queued up, and a timer starts with a specific time that gets faster with a higher level.

What happens now is either the timer runs out, or you check cam 4 which will play the run animation and shorten the timer significantly.

This is in the changecam function, and it occurs when you check cam 4 and his stage is 3.

When the timer runs out:


"down" is the variable that represents if the power is out, since he's not supposed to kill you in that case.

If the left door is open, then play his jumpscare. Otherwise remove a bit of power, play a footstep sound, and reset him.

All done

Thanks for reading. If there's anything more specific that you'd like to know, tell me and I'll try to help.

Get Five Nights At Cogcon

Comments

Log in with itch.io to leave a comment.

SHould I make the nights seprate scenes? I'm also making a fnaf fan game with godot.

*Should

If the nights have major differences in setting and gameplay then sure (something like Sister Location comes to mind). But if it's more like my fangame (which is just like FNAF 1) where pretty much the only difference between nights is the "levels" of the enemies, then probably not.

thanks, oh, one more thing. When the main game loads it takes a while, how do I fix that?

uh honestly I dunno. Could be a number of reasons, maybe you've got a lot of stuff in the scene, or maybe a hardware thing. In my experience it takes a lot to get Godot to lag badly

if you make all the nights in one scene, how do you make to the player only play one night if he finish the night before? also, how do you make to keep on track the night that the player is in?

Assuming that the only difference between nights is the difficulty of the enemies, all you have to do is change a variable containing those difficulties. You can use a global variable to keep track of which night it is, I explain how to do that in the intro of this post.

very interesting...