Reactor Defence (a game for CoronaDefold game jam)


Release build, yes. 14 draw calls - mainly, that’s because I don’t use layers for GUI. Build with no GUI and no turrets, but still lags (but actually this build is little bit smoother).

I’ve deleted all the extensions - still lags. Deleted all the game objects 1. except the turrets 2. Except the mobs - still lags. So, maybe something’s wrong with the way I use images and atlases?

I don’t use tiles. I have 7 atlases:

  1. Background and light
  2. HP bar
  3. Mob1
  4. Mob2
  5. Reactor
  6. Turrets
  7. Laser

Now I realise that this is too much but may this cause lags in Chrome? I didn’t test it with fewer atlases yet. So, should I rebuild my image structure or this amount of atlases can’t cause lags and everything’s fine?


You want to aim for as few atlases as possible while maintaining an atlas size below 4096x4096 pixels. There’s a discussion on atlas sizes in another post. You might want to consider using 2048x2048 atlases but it depends on your target group of users. I’d say 4096x4096 is good since it is handled by almost all existing hardware today.


Okay, now I have only one atlas for all images and also one tilemap for background with one huge tile (is this ok? Or one should use tiles as tiny as possible?). I’ve deleted GUI for testing (background also). Now I have only 3 draw calls. Now Chrome lags at first but then (make window of Chrome not fullscreen and then again fullscreen helps) - everything seems fine.

Build without GUI and background.

Here are results with extensions and all the code I’ve wrote:

But build with GUI and background still lags. I need to optimize my GUI.


Adding the gui should result in two more drawcalls (one for the button bg and one for the text) if you have created your gui properly. You need to use GUI layers to reduce the number of draw calls. This is mentioned in more detail in the post I linked previously.


Yes, thanks. I’ve used this approach and now I have 6-9 draw calls. But Chrome still lags. Latest build.

One more thing, when I “Build HTML5” from editor - absolutely no lags in Chrome. Absolutely. But if I build with Bundle lags will appear. And yes, I am absolutely sure about release checkbox.

Hate Chrome. :smiley:


As it often happens the solution was simple - just one checkbox. Variable Dt :man_facepalming:


But variable Dt is causing some funny bugs. For example, now one of the mobs just teleported 4 floors down. Wut? :smiley:

I have this code for moving mobs:

	local p = go.get_position()
	-- apply the speed
	p.x = p.x + self.speed * dt * self.direction
	if p.x >= 204 or p.x <= 39 then		
		p.y = p.y - 56
		self.direction = self.direction*-1
		if self.direction == -1 then
			sprite.set_hflip("#mob1", true)
			sprite.set_hflip("#hp", true)
			sprite.set_hflip("#mob2", true)
			sprite.set_hflip("#mob1", false)
			sprite.set_hflip("#hp", false)
			sprite.set_hflip("#mob2", false)

As I can understand, because of the variable Dt is on, if statement of the script is executed several times in a row, not only once. How to avoid this?

One more interesting thing. Because of Variable Dt Chrome version is much more challenging to play now. Any suggestions? :slight_smile:


But will not the p.x check in the first if case evaluate to true multiple times?


Now I have this code in update, so I think the best way will be to add collision object and run this if statement in on message.


Yes, sounds look a good plan.


I’ve made level progression, everything is smooth now in Chrome. But because of Variable Dt(?) Firefox version is really easy to win, but Chrome is not.

Mob’s hp increments in time, something like every 1 seconds add 100 more hps to initial hp (when factory spawns mob). But because of Variable Dt these 2 seconds are not actually 2 seconds as I may guess. The same thing happens with britzl’s timer and with other approach of making timer (like in some tutorial with spawning stars to collect).

Or there is some kinda problem with damage dealing which now works like that: if mob receives collision message from laser, than mob takes damage.

Or math.random behaves differently in Chrome and Firefox? Hm…

Any suggestions how to make Chrome and Firefox versions be the same difficulty?

Intro menu slightly redone:



You could use os.time() or socket.gettime() to read system time and decouple it from dt. Although dt should be the correct way to solve this problem I think. Or you could use my timer module.


I’ve checked HP incrementing and os.time(), socket.gettime(). It seems that problem is in damage dealing, not in hp incrementing.

Here is the brief example:


As you may see, in Chrome version mob has passed the whole second floor, but in Firefox not (you also may notice how much hp he has: initial hps for Chrome - 575, for Firefox - 657). It seems that Сhrome processes messages slower and this causing lower hp damage. ~0-1 ms for Firefox, ~2+ ms in Chrome.

I have the following code for damage dealing:

--laser script
function on_message(self, message_id, message, sender)
    if message_id == hash("collision_response") then, "do_damage", {damage = self.damage * self.damage })
--mob script
function on_message(self, message_id, message, sender)
    if message_id == hash("do_damage") then
        self.hp = self.hp - message.damage

If I understand all this thing right, I need to add a timer here? To kinda slow down Firefox to not receive messages too fast. What’s the best way to implement this? I need to send only one message at a time not the bunch of messages.

P.S. Also, the problem is not in the Chrome itself. It’s in the performance of the device and browser. Lower performance = slower message passing = lower hp damage. I’ve added timer to sending messages but this doesn’t work well. It seems that “collision_response” behaves very differently. With timer there can be such a situation that mobs will not be damaged at all for some amount of time. Don’t know what to do with all of this - I just can’t balance the game, because browsers and performance may vary. Really annoying.


Yeah, that’s most likely low FPS issue. You need variable_dt option and rely solely on time markers: count seconds and not messages. Inflict damage each second or half a second.

On slow machines you get fewer frames, fewer messages, hence smaller damage per second.


I would give each laser a collision object set to “trigger”. Match the collision masks and layers so it reacts to the enemies of course, then do the following (untested code).

-- Laser script
function on_message(self, message_id, message, sender)
    if message_id == hash("trigger_response")
        if message.enter then
  , "start_damage", {damage = self.damage})
  , "end_damage")

-- Enemy script
function on_message(self, message_id, message, sender)
    if message_id == hash("start_damage") then
        self.damage = message.damage
    elseif message_id == hash("end_damage") then
        self.damage = nil

function update(self, dt)
    if self.damage then = - self.damage * dt
        if <= 0 then
            -- enemy death code here

You’ll need a bit more than this to cover everything. Upgrades for example. You’ll need to keep a table of all the enemies the laser is hitting—add them to the list on trigger enter and remove them on trigger exit. When the laser is upgraded (damage increased), resend the “start_damage” message with the updated damage to every target enemy. That means you’ll need to keep that list updated when enemies are killed, but I think you’ll get the “trigger_response” exit message when the enemy is deleted, so it may just work.


Thanks, I’ll check this approach maybe , but now I found how to build the game with release mode actually working. It was not working because of some Native Extensions. More info here.

So, now I can make build running smoothly in Chrome and Firefox.


At last I’ve fixed all the weird performance and balancing stuff. :slight_smile: Thanks to everyone who helped me on this forum. Guys, you’re awesome! Final build on itch. Enjoy!


You say final build, but maybe the buttons should say “Build / Build + ON” when there is no initial turret? Keep working on the project outside of the jam?


Sure. I mean final version for the jam. :slight_smile: Hope to polish it a little bit in future and lunch on Google Play.


Now it’s tougher! Good.


Community page has been updated.

whDefRouter (ex. Defold UI Routing Library)