Reactor Defence (a game for CoronaDefold game jam)

  1. …I am afraid, it will be hard to implement buttons with GUI, but we’ll see.

Were you able to use the make_button function, or did you figure this out after testing gui yourself? I’m curious because I hope the make_button function didn’t give you trouble :wink: .



GUI with your code is next thing I want to implement :slight_smile: Hope to finish it next few days. :wink:



I do not fully understand your code. Can you help a little bit please?

  1. So, first I’ve made GUI.go with GUI.gui and attached GUI.gui_script to it. All files are in /main/GUI. Added GUI.go to main.collection. Am I right that I don’t need to change anything in this file? (Except of hash(“lClick”) to hash(“LMB”))


local buttons = 0
local listButtons = {}
local listBoxes = {}
local listOwners = {}
local thisBtn = {}

function on_message(self, message_id, message, sender)
	if message_id == hash("Make_button") then
		print("ORDERED BUTTON .............................")

function on_input(self, action_id, action)
	if action_id == hash("LMB") then
		for i=1,buttons,1 do
			if listBoxes[i] ~= nil and listBoxes[i] ~= Deleted then
				local size = gui.get_size(listBoxes[i])
				thisPos = gui.get_position(listBoxes[i])
				cX = thisPos.x - (size.x / 2)
				cX_ = thisPos.x + (size.x / 2)
				cY = thisPos.y - (size.y / 2)
				cY_ = thisPos.y + (size.y / 2)
				if action.x >= cX and action.x <= cX_ then
					if action.y >= cY and action.y <= cY_ then
						listButtons[i] = nil
						listBoxes[i] = nil
						thisBtn[1] = i[i], "Button_press", thisBtn)
						print("CLICKED: " .. tostring(listOwners[i]) .. "/Button: " .. i)

function make_button(owner,text,chars,font,pos,bound) -- Owner, Text, (Size of each character in pixels), pos, size of button in vmath.vector3() format.
	print(tostring(owner) .. " ORDERED BUTTON")
	buttons = buttons + 1
	if bound == nil then
		bound = vmath.vector3(0,0,0)
		bound.x = chars * (string.len(text) + 10)
		bound.y = 4 * chars
	buttonBox = gui.new_box_node(pos,bound)
	button = gui.new_text_node(pos,text)
	listBoxes[buttons] = buttonBox
	listButtons[buttons] = button
	listOwners[buttons] = owner
	local tab = {buttons}, "Made_button", tab)
	print("MADE BUTTON: " .. buttons)
  1. Created on_button_message.lua in /main/GUI


function on_button_message(message_id, message, btnHash, thisBtnNums)
	if message_id == hash("Made_button") then
		btnHash = btnHash + 1
		thisBtnNums[btnHash] = message[1]
		return "made"
	elseif message_id == hash("Button_press") then
		return "press"
  1. My turret.script is attached to every turret.go in main.collection. Script has id = behavior_TurretReactor. For example url of second turret is /turret2#behavior_TurretReactor

I’ve added to turret.script the following:

require "/main/GUI/on_button_message"

Little question here. Should not I specify path here something like:

require "main.GUI.on_button_message"

Or both are right?


local btnHash = 0
local thisBtnNums = {}
function on_message(self, message_id, message, sender)
	if on_button_message(message_id,message,btnHash,thisBtnNums) == "made" then
	elseif on_button_message(message_id,message,btnHash,thisBtnNums) == "press" then
		if message[1] == thisBtnNums[1] then -- This would correlate to the order of the created buttons. Upgrade is thisBtnNums[1], On/Off is [2], Special is [3]
			self.state = self.state + 1
        elseif message[1] == thisBtnNums[2] then
           -- .... Etc.
function update(self, dt)
	if message_id == hash("upgrade") == true and once == false then
        once = true
        list = {"Upgrade", GETfont_size(font), font,vmath.vector3(100,300,0), nil}"GUI#GUI", "Make_button", list) -- [] = wherever your UI script is with the Make_button() function.
        list = {"On/Off", GETfont_size(font), font,vmath.vector3(100,200,0), nil}"[]", "Make_button", list)
        list = {"Special", GETfont_size(font), font,vmath.vector3(100,100,0), nil}"[]", "Make_button", list)

So, what I need to fix to make all this stuff working? Tried some approaches, but it seems that I miss something. Thanks!

UPD. Also, it would be really helpful to have some minimum working prototype from you :slight_smile: Like britzl’s extensions. Your code can be really useful for others in future, but without working example it’s a bit hard to implement it (if one’s knowledge of Lua is limited).


  1. Yes, you’re correct. Unless you wanted to change some things like the color, add graphics, change the default size… etc.

  2. If you have any other UI modules, this could be bundled in the script with them. I have a UIModules.script with several different functions that make calculations, fit text to certain boundaries and insert line breaks, etc. So I put it along with them because it was related to UI. But this is absolutely fine–I just mentioned all that for organization’s sake.

  3. Alright, you’d have to wire this differently then. What I mean is you’d have to detect which turret was pressed and use that to change each individual turret’s values. I touched a little bit on this inside the GameObject.script, which is listed below.

This just gets the file path. I haven’t tried using periods to file search, but it may be a substitute for “/”. The first slash tells it to start at Game.project, then continue to main file, then the GUI file, and then the on_button_message script. Put the script wherever you want, but make sure you change the file path to the correct one.

I tried doing as you asked, but I couldn’t figure out how to make a repository. I MacGyvered it although, and made it as close as I could.

I posted the files, editing some things that I realized wouldn’t work for you. The main.collection file is an example showing how the collection should be laid out.

Another thing I realized is that I haven’t tested it for reproducing buttons. It will make them once, but then they cannot be recalled correctly. Sorry about this, I really should have spent more time and made sure it was finished before posting it as an example.



The easiest way to create repository is to use

I took your code and made base (not working) project with it: You can download it and run in your Defold editor.

Can you fix it to have basic working functional? i.e. create default buttons near objects with click on them. It would be super-duper cool! At the end we can update repo so everyone can use it in their projects. Thanks!

P.S. I am really appreciate of your help already! Thank you!



Found Dirty Larry extension. Works fine and also it’s kinda easy to customize it. However, I have some issue with it (described here)



Updated version with working buttons (now you can turn turrets on/off) :slight_smile: Everything works like it should but my code… god… that’s ****ing mess. Google Chrome doesn’t like it and lags as hell, but Firefox seems to work m… well. So yes, use Firefox.

Also, WIP version added to community pages

1 Like


The performance difference could be that you are running in debug mode. I chrome, the glCheckError in the engine slows it down quite a bit. Bundle a release version an try that instead!

1 Like

Release mode doesn't work with some Native Extensions (SOLVED)

Nice update.
You are right, Chrome is a ugly slow (now, was better last version).

If you export (build) to hmtl check the release box. Should be better.

1 Like


I’ve already checked release version checkbox, as britzl proposed little earlier. But this doesn’t really help.

With Safari also works just fine (desktop/iPhone SE).
Chrome 61 with iPhone SE is also fine.

Chrome for desktop, what is wrong with you? :smiley:




So, now one may win or lose (at last). Main menu with instructions added.

Still lags in Chrome. Any suggestions of how to spot what exactly causes lags? What debug features may help me in this? (I’ve already checked release version).



My suggestion would be to use the web profiler on when building and running from within the editor and look at things such as draw calls (in the right column named counters). Note that the web profiler doesn’t work for HTML5, but running it against a desktop build will at least give you an idea of the resource counters of your project, with draw calls being of interest since many draw calls will have a negative impact on performance.

You can also try the visual profiler for HTML5 to get an idea of where you’re spending your time. The visual profiler is harder to read since it fluctuates a lot.

There is probably also some HTML5/webgl profiler tools that can be used but I’m not sure which ones… :slight_smile:

1 Like


Here is the progress with debuging (no progress, actually):

Didn’t find anything interesting with web profiler. Everything seems ok. Am I right that mem usage shows memory usage in bytes?

Screens of web profiler

Versions with visual profiler enabled: - orthgraphic render script - default render script

Screens of web profiler

It seems that in Chrome “render” and “render script” (“engine” also) are different from Firefox ones. So I tried to return default render script but that doesn’t help.

Also, GameObject field differs a lot. # ~50-90 in Chrome and ~1-5 in Firefox. What could this mean?

So, maybe someone may guide me with some further steps? Thanks!



Hmm. yeah. not sure what’s going on with the huge difference between Chrome and Firefox. You are using a release build right? You have 14 draw calls for something that should only require 2 or 3 draw calls. On web you want to minimise draw calls as much as possible. Have you read this post?

1 Like


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.

1 Like


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:

1 Like