At the start of making it I had a lot of ideas how to make this Pac-Man main but after realizing that I won't be able to make it in two weeks after all I settled with making a normal Pac-Man.
First, I decided to make a map but because I didn't know how to existing sprites and I struggled for somewhere a week but I made a map from div and its :after and :before elements, added some normal pacman sprites, got a free license for font and it was looking fine:
Then I needed to make Pac-Man(where I learned to use sprites after all), implement moving logic like not walking into the walls or going through tunnels, most info was in normal variables like speed characters moved in but later I understood that it will be a mess if ghosts also had their own variables for properties so I made an object with all characters and their properties when I started implementing ghosts.
After that to make Pac-Man move like in real game, I made a function for him when he would get new relative position (later changed to translate for better performance), direction based on user input ,animation of eating and function responsible for changing his position from one place to another.
Pac-Man sudden change from one game block to another was too fast though and new animation would start before pac-man changed his position so I decided to use async and await, but even with tha, class was not fast enough to give a starting translate and because transition needs starting value to play, there was no transition. What I decided was making an invisible pac-man element on every element player can go to and only toggle the visibility.
I choosed this one because he was starting the same way as Pac-Man and I didn't have a plan yet how would I take the ghosts out of their spawn. Firstly I made different functions responsible for blinky movement but then I saw how many similarities all characters have so I just made most functions for all the characters with a small differences in behaviour between ghosts and point eater.
After that I started to make animation stop, game win, game over, eating points and many other game-end stuff but as code has started to grow I started to have big problems with understanding what did what, I made some comments for the weirdest things, cleaned code few times already and tried to apply DRY and I was hanging by somehow.
I Made different kind of animations and started making collisions checking. It was pretty bad, because characters were :after elements if they didn't detect themselves before colliding they would bug out, later I realized that ghosts have to pass through themselves freely so I had to ditch out the whole :after element idea and just made a 5 elements in each accessible block for characters.
At this point I was happy even when I still had a lot of work to do but I saw that my game was a bit buggy, not much if you don't pay any closer look but I wanted to make it work well. After a lot of searching I was reminded that games in js should be done in canvas, so I said my game is good enough and went forward.
Later I started to have trouble with frightened and retreating mode but I managed to make it for red, sadly it was time to make other ghosts now and all those exclusive ghost functions were made especially for him and were a big mess, it took a long time before I made everything work for others and even more time until I fixed all the bugs.
Then I had to do the eating animation and I didn't have any idea how to do this whole stop when eating ghost, what I finally came up with was taking a performance.now() check before every animation and after stopping all the animations I calculated how much time they had left to complete each of their animation, resumed them and everything was working fine.
And now I had to do things I should do from beginning. I had to make lives and highscore which would be definitely a lot easier to implement and plan when I didn't have 800 lines of code.
After that I decided to make sounds, I failed to make them repeat well so I just downloaded audacity, learned it quickly and made them into a loop so soundtracks will change before they have a chance to end. The main soundtrack, the only audio file that could play for more than a minute had a buffer set though.
I repaired some bugs that showed up for other browsers and then I I decided to make a version for mobile devices, it was awfully late for it considering that best practice says you should start with it and because of my lack of planning I had to make a sprite file out of the main elements cause border wouldn't render properly after scalling it down. In the end my avoidance to use existing sprites for a map resulted in making my own sprites after all but with more effort needed to change already complex code:
Then once again my lack of planning showed itself because I had to make a white version of map when player was winning but I already deleted styling made from :after and :before elements left with only photos of them. So I played a lot with Gimp to make it. Because of that I spend pretty good amount of time learning image editing instead of programming.
After that it was done, I was happy with what I did and the animation was still smooth enough so you could play without issues. I felt that this journey has come to an end.
But it didn't.
Everything on local host was working well but after posting it on Github fps decline was clearly visible, I looked for an answer but couldn't find anything so finally I asked a question on Stack Overflow but because I am not good in asking on that site I had to rewrite it and currently I am still waiting for a response.
In short I found out that after hosting, one line that removed a class from character which caused him to move recalculated bigger half of the map. And because I couldn't think of any way to repair this bug I decided to admit defeat and post it, hopefully I will find some solution soon.
(Here's the question if you want to help me or to know more details)
Amazingly, everything works perfectly fine on CodePen, you can find this version on top.
I learned a lot of things and few mistakes I will try to avoid in future are:
- Make constantly moving games in canvas or some engine,
- Always have a general plan of whole project,
- Take your time to make your code maintainable instead of just applying some quick fix and moving on or it will haunt you later.