Deer Clicker: Behind The Scenes
3/3/2025
You may have noticed that recently I released a very small game to the site called Deer Clicker. Web games have always been something on my mind, since creating the site, as part of my growing general interest in web...stuff. I've been a big fan of Newgrounds since I was a kid, so weird, free, cool games are definitely part of that great old internet feeling for me. I thought I would share some fun little tidbits about how exactly I got this started, and some stuff I learned along the way.
Note: This is NOT a tutorial for JavaScript or Phaser, or good coding. You have been warned.
The first thing I investigated was what to make a game with. Having already known I wanted to make some kind of idle/clicker game, I thought Godot was cool, but maybe a little overkill. I had flipped-flopped a bit on whether it might be a good thing in the long run, though. Godot, as far as I know, is known to be powerful and quite capable for both 2D and 3D projects (even for web!), and who knows what I might want to make later? With that in mind, I probably will check out Godot more thoroughly when I'm ready.
I ended up finding Phaser, which seemed to fit neatly for a lot of my personal goals. Those being...
- 1. Web first.
- 2. JavaScript
- 3. No extra software or installs.
Naturally, I had an inclination to publish whatever game Deer Clicker would become on my own website. I personally have "make Newgrounds game" as a bucket-list item, but for getting started, I knew where my game was going. Phaser's focus on being fast for web browsers seemed to be exactly what I was looking for. I also saw Kaplay, which seems to be pretty similar and also well liked. The website shows a lot of cool features. I found out about Kaplay after getting started with Phaser, so I haven't gotten to try it, but there're plenty of web game frameworks and tools. I just went with Phaser this time (and probably will again, now that I've gotten some experience with it).
Learning more about JavaScript is something that's been on my plate for a good while, especially after using it for certain things on this site. That was a headache at that time, but who doesn't want to learn a little more about programming? Phaser being a JavaScript framework seemed like it would teach me more about JS.
Phaser is just a file you include in your project, though there is a Phaser Editor (there's a free trial, otherwise paid); I liked the idea of keeping to what I'm used to. That is, VSCode of course! I'm very, very used to VSCode and testing in my web browser, so I was already all set to go here.

Keep in mind for a game like Deer Clicker, it would be totally feasible to not have a game engine or framework. Hell, it might have taught me more about JS to do it that way. Games like Cookie Clicker Classic or the crazy DodecaDragons are made with regular ol' JavaScript and HTML/CSS, at least as far as I know. Still, I wanted Deer Clicker to have a little bit more presentation to it, and what's the harm in picking up a tool for potential future projects?
If you're just starting out, you may not have any goals or identifiable points to help lead you in a direction. You may not even have a game in mind that you want to make. If that's the case, you probably are best off with something that does have some kind of graphic interface, or a plethora of YouTube tutorials at the very least.
Alright, with all of that decided, step two was following this tutorial on the Phaser website to get an idea of what exactly is going on. I'll mention this on the off chance that you're like me and that it may help you get through the beginning stage of the project. I am the type of person that likes to start swapping out tutorial graphics and screwing with it as soon as possible, even if I don't know all of what is possible, yet. I did follow this tutorial, but also had a window in to start loading what would become Deer Clicker's graphics. I'm also the kind of person that needs to see something game-like for me to get excited. I probably could have coded a number-go-up button on one of the site pages, but where's the fun in that? If you have those kinds of compulsions, just listen to them. Fighting them makes it tougher, I think.
Everything went well for me in that tutorial section, and soon I had little animated deer on a background. I recall calling it quits for the night. The rest was up to me...
One thing I know I should have done (and never did) was actually write down and design Deer Clicker. I basically made it up on the spot, which I suppose worked out fine, since the intent was to follow the Cookie Clicker model. Still, I definitely could have made the earliest part of development smoother. How much was supposed to be idle, and how much was supposed to be click? I ended up making all the buttons in the game as bespoke graphics, which was not a great idea considering I was making up the numbers as I went along. We'll talk about that later.
Despite my lack of design, I knew there would be a few "building blocks" that I could create, those pieces of code would be able to be reused frequently and make the game as it is. A number has to go up when the player clicks on something. A number has to go up every x amount of time. The number has to go down when they "buy" something. The player needs to see the cost of the Deer and how many they have. I think each of these building blocks gave me some headaches.
Getting things to display on screen in Phaser is pretty easy. Interactivity started to be an issue. The numbers were issues. Let's go over a few problems I faced as a total novice to this...
How To Make Number Go Up?
This was probably the biggest one. Naturally, numbers going up and down is the entire game. The first order of business was to make the number go up by one when you click on a deer. Hm, okay. Well, it seemed easy enough to create a variable. From what I understand, if you create a variable inside a function, then it can't be messed with outside of it. So, it needs to be a global variable (declared somewhere where "everything can see it"). Makes enough sense to me.
let DeerCount = 0;
Next was the deer. Thankfully for me, you can easily set a sprite or image as "interactive" when you load it in. You can then "listen" for events and do whatever. So, that ended up looking something like this when I first wrote it...
fakedeer.on(pointerdown), (){DeerCount + 1}
That makes sense to you, human, doesn't it? 'fakedeer' is the code name for one of the regular brown deer you start with. So, 'pointerdown' is click, and then it executes a function (that starts with the squiggly brackets) written inside it. That's simple enough, but this wasn't working for a few reasons. I'm sure JS fans know why, but humor me...
First off, there was nothing in the code at first that told the game to update the display of the deer counter. Oops. Thankfully for me, Phaser includes a function built in that continually updates things, made for things like scores and health values, etc. My first solution was to write the update into this (pointerdown) function. (){DeerCount + 1; DeerDisplay.setText(DeerCount)}
, forcing it to re-check and redisplay the value...right?
That also didn't work! But why not?
Here's something it took me an depressingly long time to discover: There's a specific way in JS to modify a variable and return the result to the variable. Let's review. DeerCount + 1
doesn't do anything by itself. All I did was create an arbitrary number that doesn't get used anywhere, by anything. I later discovered DeerCount ++
, this, in JS, increments a number by one, which was perfect for an incremental game! There was also DeerCount += 1
, that extra equals sign returns the equation answer to the left variable, as in, it actually updates it. This was a huge headache early on, but this very basic 'number go up' ability was eventually worked out. The ++
method was for the deer, and that +=
method was used for deer that added more per click.
...So that's what I went through to get a number to go up.
Coding A Store

With that worked out (for this example. In reality, a lot of this was happening back and forth), I knew the purchase buttons would have the largest amount of things involved. When a player clicks on one of the buttons to purchase a deer, all the following have to happen...
- The price of the deer has to be subtracted from the DeerCount.
- The price needs to go up according to...something.
- The number of that specific deer the player bought has to go up.
- All the text needs to be updated on the screen.
- The deer needs to show up on the screen.
- The next tier of deer needs to become purchasable.
- The effect of x deer per second needs to start happening for each of that Deer the player has.
- And none of that needs to happen if the player's DeerCount (their money) doesn't match the price.
- Also, hovering over the button should show some extra information somehow.
You would be correct in imagining that these made up the biggest hurdles. Of course, once all that got solved, that would pretty much be the game! We'll take a look at the code that does all of that later, and see how it matches with the list.
The first snag I had was with having the price go up. Obviously, it couldn't go up by a fixed number. I didn't check with any precision, but I was decently certain that the prices in Cookie Clicker are multiplied by 1.1 for each buy. But wait a minute...that doesn't make round numbers! Uh oh...thankfully, JavaScript has a method to round numbers to the nearest integer. Math.round()
ended up being a lifesaver, but how does it work? I wasn't sure at first, because I read 30 StackOverflow posts halfway through instead of reading one or two closely. I wondered if there was a way to consistently apply Math.round
to the variable itself, which I'm pretty sure is possible and I just wrote it wrong the first few times.
earthdeerprice = Math.round(earthdeerprice)
, I think something like that would have worked just fine, and would have saved on lines of code (but who's counting?). What I ended up doing instead was simply rounding the number as part of the function that happens when the button is clicked. It looks just like the above.
earthdeerprice *= 1.1;
earthdeerprice = Math.round(earthdeerprice);
Simple enough.
You're probably familiar with if else
statements, or at least the idea of some kind of code that runs under a condition. It's pretty important to not have stuff running all the time. I was pretty stumped for a while on how to get if DeerCount >= xDeerPrice
to do nothing if the player didn't have enough Deer. I tried a couple of things that didn't really make much sense (involving null
and void0
), which sorta worked. For a while, the else
statement was something like else void0
. In the end though, it turned out that if
statements do not require an else
statement to run if the condition is false. It just won't do it. That's perfect. Although, looking back, it would have been possible to have some kind of negative feedback as the else
, like having the store text box shake or flash red or something. But this works just fine!
Graphics
The store buttons themselves (that is, the little white rectangles on the right side of the screen) have their own issues, but I made my choices and stuck with it. I knew it wasn't ideal when I starting making the store graphics, but allow me to explain. According to Phaser documentation, the text rendering what's done in the browser is done by remaking itself whenever it's updated. This apparently can have a performance impact if there are a lot of text elements. I'm not sure how many is "a lot" in this case, but I decided to make bespoke graphics for the signage. That is, they are PNG files at a fixed resolution that sit in the game asset folder. I used Aseprite for that, and sometimes Paint.net for touchups. Also, it was the quickest way for me to get something to mess with on screen.
The drawback here of course, is that I must remake the graphic myself every time I adjust what purchasing the Deer does. This is an issue that's compounded by the fact that I was pretty much just making up those numbers and I didn't map out a game design for Deer Clicker. So, it's very slapdash, but I think it came out okay.
By the way, the primary deer counter and the white text above each store button are generated by the game code. You can include variables in text strings. You can see that in the image at the top, but it looks like this.
transgendeerdisplay = this.add
.text(621, 290, `Owned: ${transgendeercount} Cost:${transgendeerprice}`
Because these price/count displays are done by the game code, I can include them in the update function, and they'll stay up to date when changed.
The tooltips ended up actually being simple, but we'll talk about why (I think) they bug out a bit later. Originally, they just statically appeared next to the store button, but I was very adamant about having some kind of animation associated with it. They are exactly like the other store buttons, just PNGs! On a pointerover
event, the tooltip appears, and on pointerout
, the tooltip is hidden again. This is one element that I was able to get working pretty much right away. Phaser has tweening capabilities, meaning it's not so hard to get graphics sliding around.
Alright, so, we've got the price being subtracted from the cost correctly, and the price increasing at 1.1 each time. The graphics for the store buttons have a fun animated tootlip. Now, they need to actually do the thing where the DeerCount goes up by x every second, as advertised in the store button.
This freaked me out at first, but this is where Phaser came in handy. Phaser has a feature called Timeline. This is something you can add events and execute functions in. So, in our block of code for the store button, I write in that something should be added to the timeline. There is a bug with this too, but this mostly worked as intended. This is hard to explain in words, so...
Let's finally go through that whole code block! We'll use the one for the Lemonlime Deer.
lemonlimebutton.on("pointerdown", () => {
if (deercount >= lemonlimeprice) {
console.log("You Clicked On Me");
lemonlimepurchase();
lemonlimeprice *= 1.1;
lemonlimeprice = Math.round(lemonlimeprice);
lemonlimedeer.setVisible(true);
timeline.add({ in: 1000, once: false, repeat: -1, run: deercountAdd });
timeline.add({
in: 1000,
once: false,
repeat: -1,
run: lemonlimecountAdd,
});
transgendeerbutton.setVisible(true);
transgendeerdisplay.setVisible(true);
}
});
I bet you were able to read that just fine! Let's review...
lemonlimebutton.on("pointerdown", () => {
if (deercount >= lemonlimeprice) {
console.log("You Clicked On Me");
lemonlimepurchase();
lemonlimeprice *= 1.1; lemonlimeprice = Math.round(lemonlimeprice);
lemonlimedeer.setVisible(true);
timeline.add({ in: 1000, once: false, repeat: -1, run: deercountAdd }); timeline.add({ in: 1000, once: false, repeat: -1, run: lemonlimecountAdd, });
transgendeerbutton.setVisible(true); transgendeerdisplay.setVisible(true);
This is what starts us off. When this graphic is clicked on...and you can see, the function part starts with the squiggly { bracket.
There's our condition.
This is just something that lets me know that the 'pointerdown' listener is working.
This calls another function in the game code. This wasn't strictly necessary, and probably inflated the code. There are some reasons to do this though, like if the lemonlimepurchase
code was called in multiple places, I'd only have to edit it in one. This function also checks to make sure the money matches the price, and increments the number of the deer the player just purchased goes up. Once I understood that I was already writing a function for when the button is clicked, I probably would have done it there.
You remember this one, and how it's a bit redundant. But that's okay.
This turns on the deer graphic, in this case the green and yellow deer. All the graphics are loaded, but they're set as not visible, and effectively don't exist. You can't click on the deer before the graphic is drawn. I'm glad I didn't have to figure out that functionality.
Here's the code for the timeline. As you can see, it actually adds two things to the timeline. Yeah, you actually get some bonus deer because I didn't take that out of the code that I kept reusing. in: 1000
refers to milliseconds, so, every second it runs deercountAdd
, another function. I'm not sure if it's possible to write the function to be executed on the timeline within the timeline code, but I think this way is pretty clean. repeat: -1
means that this event will continuously run on a loop. Lastly, lemonlimecountAdd
is the function that adds a number to the deercount, in this case 150.
This sets the store buttons (and the counter) as visible. Just like the clickable deer, they basically don't exist when set as invisible. .setVisible
is a property of pretty much any game object in Phaser, as I understand it.
Bugs

There are a few bugs in Deer Clicker, or at least otherwise strange behaviors I don't totally understand.
When you click on a deer, a little animation plays where the deer grows and shrinks again. It happens fast, and I really like it as feedback for the player. However, if you click too fast, the deer stays enlarged, and at some point will no longer animate. I'm not entirely sure what causes this, but I think that if the animation isn't completed, but is called again by a second click, it doesn't like that too much. I'm not sure how many people even noticed! But I noticed. Still, I saw no clear remedy for this, and decided to let it go. It still plays the happy sound, so that works for me.
The tooltip can start to glitch out if your mouse is hovering over the edge of the tooltip while it's also on top of the store button. It doesn't like when a pointerover
graphic has something drawn over it, because now it's pointerout
, causing the flickering as it rapidly flips back and forth between being over
the button and not. I think this was fixable (and a reason to have a static, not animated tooltip). Phaser will load graphics in the order you preload them in, basically putting each one on their own kind of layer.
In my code, you can see that the tooltips are loaded in after the store button, this effectively makes them "on top" of them. Had I reversed this order, I think the animation glitch wouldn't happen. It may have been a little more complex than that.
Now, about the behavior of the timeline that you just learned about...
You may have noticed (at least one person did and told me!) that the Deer Count doesn't seem to actually update every second. It sort of happens in bursts. Why is that?
I have a hunch that each time something is added to the timeline, it basically exists on it's own second, or perhaps its own timeline. This would explain why everything doesn't seem to update at once. Cookie Clicker Classic maybe exhibits this behavior as well? It's hard to tell just by watching. I believe there are ways to have everything on the "same second" in Phaser, there are a lot of controls for the concept of time that I didn't mess with.
And there you have it! That's about 90% of what powers Deer Clicker. Writing about this got out of hand, so I'm going to cut off explaining anything else, for now. If you have a question about the game, I'm more than happy to answer on Bluesky, or I suppose you could send some email to playingps2@hotmail.com!
The response to Deer Clicker on Bluesky was really amazing. I can't thank everyone who played and shared it enough, and doing some simple game development myself was an amazing and exciting experience! I'm still working and messing with Phaser and seeing what I can do. I have a lot to learn. A lot, but it's remained enjoyable. Hopefully, you'll see another little game by me in the future.
If you read this entire thing, you are a superfan! Thank you again, everyone.
- Jane