In Killer in Purple you play as William Afton, having to murder kids in order to get points which can buy you upgrades, new characters and new areas.
Killer in Purple is one of the most popular of my games, and still quite popular to this day, even with Killer in Purple 2.
Release Date: July 2nd 2020
Versions: - Alpha 1
- v0.1.2
- v0.2
- v0.3
- v1.0
- v1.0.1
- v1.1
- v1.2
- v2.0
- v2.0.1
- v2.0.2
- v2.0.3
- v2.0.4
- v3.0
- v3.0.1
- v3.0.2
- v3.0.3
- v3.0.4
- v3.0.5 (latest)
32-bit Versions: - v1.0
- v1.0.1
- v1.1
- v1.2
- v2.0
- v2.0.1
- v2.0.2
- v2.0.3
- v2.0.4 (latest)
PC VR: - v3.0
- v3.0.1
- v3.0.2
- v3.0.3
- v3.0.4
- v3.0.5 (latest)
Killer in Purple was first made as a joke, but eventually got extremely popular. Due to it first being a joke game, the code for this game slowly got more and more out of hands with every single update. v2.0.4 was the last update where I used this old unoptimized code. When I started working on a VR port I decided to recode over 80% of the game, with more optimized and manageable code.
This was probably one of the biggest overhauls to my games I had done to date, but a necessary one. Below here, I want to show some code from v2.0.4, and how the code looks now, in v3.0.5 with the remastered code.
Bonnies suit is used within the Backroom of the pizzeria. By clicking on it with a kid in your hand, you gain extra points. However, each suit was a duplicate of the other, meaning every single one had the same code, besides an integer that I changed manually to increase the points the player got for the suit.
This of course is horribly coded. As the game was also coded with duplicate players, instead of having 1 main one with child classes. Meaning if I added 1 new character, I had to go trough 100's of blueprints to add cast nodes so that it would work. The suits were a big issue with this as there are a lof of suits, and it took hours just to change it to work with 1 new character.
For this change I am just showing Bonnie's suit, but keep in mind, every suit had the same code, just duplicated, meaning if I change 1, it wont change the others.
v2.0.4
Other then just the casting, the score was saved as a string, and in order to add something to the existing score, I used a loop which would increment the score +1 every time it is called, which is very unoptimized as you can just increment it by +x with x being an integer I can set.
v3.0
As you can see, the main improvement here is making 1 base class. The base class just has an integer, which gets added onto the current score, which is now saved as an integer, and not a string. Also the loop that adds to the score is gone, to increase CPU performance.
Every suit is a child class of this main suit class, meaning if there is a bug with the suit, it only takes 1 minute to fix, instead of 30 minutes.
The camera has a massive overhaul with v3.0, cause the main issue that happened with the camera was that it would check EVERYTHING in the scene for Overlaps, meaning it caused loads of triggers to the event when it overlapped, causing loads of CPU usage.
Besides that of course, the casting to the player can be seen again, which will happen loads with code from v2.0.4.
v2.0.4
v3.0
To fix the issue with the CPU bottleneck, I made a separate collision channel in the Project Settings, so that cameras would only check for the Player Collision and for the Children Collision, this was perfect as it would never check useless things like walls, parents and other props.
Also the casting to all the players is gone due to the object oriented Player, instead I only have to cast to the base class (William_BP). When the player enters the camera view, it will continue checking over and over if they are holding the knife, and once they leave the camera view, it will stop.
The Elevator was less bad with v2.0.4, but still, it was definitely not perfect. One of the bigger issues was this time loop in the image below, where it would check every 0.05 seconds if the player was pressing F while in the elevator, but this is not optimal, as when the player is not even close to the elevator, this code will still run in the background.
v2.0.4
v3.0
The solution to this problem is simple, we just want to check if the player interacts with the elevator, a keypress with F is definitely possible, but this is 1 of the only places in the game using F as an interaction key. So I switched the system out with Interaction by Left Mouse button. This solves all the issues the Elevator had with being active when the player is not around.
The music is once again a good example of why Object Oriented code exists. Firstly the issue is of course, like lots of other scripts, that I cast to each player, which, even in this situation is not needed, as I could just compare it to the Player Character / Pawn. However I decided to use casts here, probably from old leftover code from over the years.
Outside of that, all the music changes are hard coded into the Level BP, and are not really easily controlable.
v2.0.4
v3.0
To solve the music issue, it's quite simple, since I do not want bloated code for this, all I have to do is remove the code, and just simply leave only the audio. With a simple Audio visualizer I coded, I was able to only put sound in the level. This works extremely well, and even has smooth transitions between levels.
Saving / Loading is done extremely badly. Sure, the game does save things sorta clean (altho it could be much better as it is all done in the Level BP), the loading is the main issue. As I load EVERYTHING with 1 giant function, which is not clean at all, and takes huge amounts of space. Besides that, I load in variables at the start, but then at runtime I also use the Load function to load variables from the save file, which costs a lot of performance.
v2.0.4
v3.0
The entire Load function is now replaced with this small load function, that returns the Save Object instead of all the data in it, meaning I can re-use it. Also the game doesn't load at runtime anymore. It now loads once from the save file, and stores it in the Game Instance. Once the player beats this play-session, their score is then updated in the Game Instance.
Once the player quits the entire game in the mainmenu, the Game Instance data is then saved in the Save File.
However there is a slight issue still with this system. Currently the data is still split up, so the Save function is still massive just like the old system. To reduce this size, it would be better to use a Struct and save that. That way you don't have to update the save function every time you add a variable to the save.
The biggest issue with Killer in Purple v2.0.4 and older builds was that, as it was made as a joke, it was not coded in a way to have a lot of characters. The game expanded so much, that too many duplicate players were created, causing many blueprints (as seen above) to have to cast to every player character.
That is not the only issue. As when I was coding the game, and I had to fix bugs with the player, I had to fix it for all characters, and the chances were big that I forgot to code it in for 1 or 2 characters.
v2.0.4
v3.0
Now as you can see, the code of v3.0 is MUCH bigger than v2.0.4, but that is only cause I added more stuff like VR Support, and I also implemented some code into the Player that was in random places it shouldn't be before.
But overall, now all the code for all the players is in 1 class (William_BP), and all the players that are not William, are just subclasses of him, with the same code. This means I can always just cast only to William_BP.
For a comparison, when adding Burntrap to the game, it took me 2 days to implement him fully with all the other Blueprints, and I still forgot things, which had to be patched later.
The new system costs me a maximum of 1 hour to implement a new character, this mostly due to the ability, model and sounds, but code wise it is quite easy.