Big List of Defold Pro Tips!


#41

Moving files and folders around directories within Defold. Create a folder in the wrong place? Want to move it somewhere else?

You can drag and drop folders and other resources, but this can be difficult to do properly. It’s more accurate to use the Move… option when you right click on any folder or resource.

Then select a folder to move to

Moving many files at once is possible. You can click a resource in a longer list, hold down shift after you have selected a resources and then click on another resource to select the second resource and anything between. Hold ctrl to select / deselect indivdiual resources once you have other selections active. Then right click and select the move option.


#42

Basic tiled importer. This is basically the example @Andreas_Jirenius made in one of his videos + sloppy parts I did with testing it (but do not worry it will be polished more later). It is rough, but should be enough to get people started, and is more accessible to the public. On my big list of todos, I plan to make a generic importer that can more easily be added to projects and then expanded based on the needs of the project.

  • This method imports Tiled data to replace what is in a Defold tilemap. It’s a very good idea to use Defold’s built in tilemaps for tiles because they are already optimized for batch rendering.
  • Tiled can export .lua files for your maps. That is what this method imports.
  • Remember this is rough, if you want wait until I make a polished and more generic-usable version later.
  • Tiled has many features. When you import maps you’ll want to tailor what data you use based on your game.
  • Tiled has the x,y starting at the top left tile on its maps and is 0 based index. Defold has the x,y starting tile at the bottom left of its tilemaps and is 1 based index. You will need to flip and offset compensate data because of this.
  • Currently Defold does not allow you to define the size of tilemaps with scripting or with properties, it requires you to draw the bounds of your map.
  • The tile images used in example are http://opengameart.org/content/lpc-tile-atlas ok for example but you would want to use your own assets for a real project
  • Supports object layer data and creating game objects at correct position based on the data … you’ll want to add custom properties in Tiled and then pull them as you need them
  • The Tiled level is ugly purely for testing purposes
  • If you make fixes / improvements please share them

Updated: simple_tiled_importer_example.zip (537.6 KB)

Older: simple_tiled_import_example.zip (537.5 KB)


Tilemap.get_bounds seems to be returning too high values for x and y (SOLVED)
Big list of feature requests based on our experience on Ludum Dare
Collision_response_start / collision_response_finish events
Tilemap, custom tiles and pathfinding
#43

A couple of comments:

  1. Shouldn’t the tiled_importer.script be named tiled_importer.lua?
  2. Shouldn’t you require() the tiled_importer module from test.script?
  3. Now there’s a direct call to M.create_level() in test.script but I don’t see how the test.script would have access to M. Oh, wait now I see it. tiled_importer.script declares a global M. This is not really a recommended approach since there’s a high risk of something else also being declared as M and overwriting the tiled_importer.

I have put some suggested improvements here:


#44

Yep, those are the sloppy bits. Thank you for the suggestions - I’ll get it cleaned up!

This kind of thing worked previously in other tests but it’s not working here. Any idea? I want to allow more dynamic map data loading.

function M.create_level(map_data_file, target_tilemap, map_tile_width, map_tile_height, tile_px_width, tile_px_height)
	local script = ("/main/levels/level_1.lua")
	local code = sys.load_resource(script)
	local def = assert(loadstring(code))
	
	--map_data_file = map_data_file or "/main/levels/level_1.lua"
	--local def = assert(loadstring(sys.load_resource(map_data_file)))

Edit: Tested more things and still not sure why it’s not working… it could be “solved” by loading JSON but I’d still like to figure how to make this work

Edit2: Here is sample where it’s working for the JSON decoded file but not for the lua how I would expect. I’m going to continue refactoring with the JSON method and hope someone can give hint on how to get the lua method working. Not a deal breaker.

master.zip (542.9 KB)


#45

Simple JSON loading example. You can load JSON files from the file system, convert them into Lua tables with json.decode, and then use them as you would a Lua table. To be able to load files like this, they must be within a folder defined in your game.project

The code itself is very simple.

    local file = sys.load_resource("/main/json_files/level_1.json")
    local decoded = json.decode(file)
    print(decoded.layers[1].type) -- example of getting data

If you do not want to convert JSON into Lua tables you will have to parse it yourself. If the JSON data is malformed you will get an error.

json_loading_example.zip (2.9 KB)


#46

Uploaded some improvements to original post. Still some more to do but that looks like correct direction right?


#47

loadstring(code) will return a function that when invoked will run the loaded code and return any data from it. I think this is how you need to use it:

local def = assert(loadstring(code))()

#48

That works! Nice! Good to know!

local script = ("/main/files/level_1.lua")
local code = sys.load_resource(script)
local def = assert(loadstring(code))()  
print(def.layers[1].type)

DEBUG:SCRIPT: tilelayer

Adding scripts during runtime
#49

Since Defold doesn’t yet have its collision information for tiles available to scripting directly (afaik), I’m adding support for tiled importer to get meta tile information for a special layer. Then when moving around games can check meta data for collisions or special things such as spawn rates for mobs.

Going to work on it a while longer before sharing new version.


Defold Timer - The native timer extension
#50

Delayed function calls on a timer. A proper way to do this is in Defold backlog. It’s been suggested until then to use go.animate. This module by @britzl is better.

local timer = require ("main.timer")

function hej()
	print("hej!")
end

function init(self)
	timer.seconds(3, hej)
end


function update(self, dt)
	timer.update(dt)
end


Gary's Lament — a text unadventure
Delay functions?
#51

Searching the site for Defold answers.

With Google, search the entire domain with this

site:defold.com keywords

It will search the public docs and the forum. Remember that Google doesn’t have super fresh results always so if you can’t find answers from that search the forum or the docs directly.


#52

If you want to use distance field fonts be sure to remember to change their material too.

If you forget to you’ll end up with text looking like this.



#53

If you are not using hot code reloading you absolutely should be. It can save you a ton of time when you are working on specific areas of your code without needing to rebuild over and over again. I changed my key map for hot code reload to F2.


#54

Having different screens, loading different screens, switching between screens.

This post references this thread. As well as the official docs:

Think of collections as a way to represent a screen. Main menu, game, splash …

Then you have a central script which loads or unloads collections as you switch screens.

If you would like you could add a super light weight inbetween screen which acts as loading screen -
or have unique light weight loading screens depending on what kind of activities you are going to,
and some screens you go to you may already know they are super light weight and don’t need a loading screen inbetween.

Remember that some screens you may want to not be screens you switch to but ones which act as overlays.

  1. The parent object’s script of the collection proxies must ask for input if you want the child screens to be able to get input
  2. If you get the below error edit your .collection files in a text editor and change their name: from default - the file name is NOT this name

ERROR:GAMEOBJECT: The collection 'default' could not be created since there is already a socket with the same name.

Remember that even in the different screens you may be loading / unloading proxy collections as you need them for that screen.

Below is an example showing how to switch between screens - but as mentioned there are further improvements you can make.

ScreenSwitcher.zip (31.6 KB)


Proxy start button
Collection Proxy to load next level
#55

Note that you could use collection proxies at any level. Screens or levels are natural candidates though but you are not restricted to that. In theory you could dynamically load every single object that appears through a proxy—although that is not recommended.


#56

Defining default parameter arguments for functions. This is one way to do it.


function say(msg)
  
  local msg = msg or "Hello" -- if msg is not defined it will be nil
  print(msg)
  
end

say() -- prints "Hello" because no parameter is passed

This style of defining variables is also useful if you have a script which loops that you want to initialize variables once to not be nil without resetting them after they have a truthy value.

local health = health or 0

#57

Sending messages has a cost. Every time you send a message it involves copying and serializing a Lua table. Don’t be afraid to use the messaging system, but try to use it for the right things only. Collisions in systems with many objects for example require extra consideration and optimizations to not overload the message system.

Your on_message functions can also slow down the system depending on how complex that code is. If you are sending many messages it may be this area that needs to be optimized. Use the profiler to see.


#58

Detecting input on edges / corners of the screen. This is very easy to do. You can detect half of the screen for some input and the other half for another. You can detect only the far edges of your screens. Are you using custom rendering? You will want to look at action.screen_x and action.screen_y.

This post by @britzl explains one method for doing this.

Reasons for using this input style: picture book, player movement for a platformer, driving game with steering…


#59

Get current app version to display to your users.

sys.get_config("project.version")

There are many kinds of version number conventions. The way I prefer to do it with my games is 1.0.year.month.day.build so for example today’s would be 1.0.16.4.25 for the first build and 1.0.16.4.25.2 for the second build of the day. I’ve used other systems before but I like this one because you can see when the version was made live at a glance.

You can also use sys.get_config to get anything listed in the game.project file.

sys.get_config("project.title")
sys.get_config("display.width")
sys.get_config("physics.scale")

And so on.


#60

If you are using Tiled to edit your Tilemaps and they’re big, you can quickly create the tilemap file in Defold like this:
Create a tilemap as usual and select the tile source. Select a tile and place it at the origin, then place another tile at a random place, such as 5,5. Save and close the tilemap.

Then in the Project Explorer, right click on the tilemap file and select open with Text Editor. You should see the 2 cell tables for the tiles you added. In the bottom cell set the x and y values of to be how many tiles high and wide your tilemap will be. If you have extra layers, add the values to that as well.

This should make your tilemap the right size for the import.
Well it worked for me :slight_smile: