Big List of Defold Pro Tips!

Activating native keyboards for iOS and Android, and getting user input since most mobile devices don’t have built in keyboards you will need to activate the native keyboard to allow users to enter text into your game.

To show the native keyboard use

gui.show_keyboard()

To hide use

gui.hide_keyboard()

More info: http://www.defold.com/ref/gui/#gui.show_keyboard

NOTE: You don’t need the virtual keyboard open to detect keys on other platforms. Use the below when you want to enter text into selected text boxes / inputs.

To detect and record text, you need to add a text trigger to your Input Binding game.input_binding file. Its default name is TEXT. Leave at as this

Now when you detect input with on_input() use action.text you can get inputted text.

function on_input(self, action_id, action)
	if action.text then
		input_text = input_text .. action.text
	end    
end

Then you’ll display the text wherever and or store it. Keep in mind user focus and putting text in one place at a time, and checking if you should be looking for text at all.

You will still need to detect actions such as backspace to delete characters (I have yet to test this on mobile so am not 100% sure normal backpsace detection works from virtual keyboard). If you want the user to be able to put their virtual cursor somewhere in the text (like most text editors allow) this is possible but takes a little extra work - a way to do it is to store an offset, and change offset when users touch/click a position in the text (with a visual indicator such as a blinking “|”), and then insert the next character there based on offset.

Read this doc for more info http://www.defold.com/manuals/input/


Super Important! Some Asian language inputs are done in parts to form complete characters. In the case of these, instead of just action.text you will want to use action.marked_text too, and create a text trigger for it too (use drop down on “input”)

There is no manual or documentation on MARKED_TEXT yet so it may need experimentation. Is gui.reset_keyboard related to it?

https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPInternational/InternationalizingYourCode/InternationalizingYourCode.html

Based on this, how I assume you use it is that as the user types, you displayed the temporary characters that are in the marked text space, and then when the user finishes typing the final character replaces any of the fragments? So you would need to detect the next action.text and when that happens then clear the action.marked_text temp you added?

Or - you check action.marked_text and if it is true (meaning user entered full character from partials) then you can grab the next character with action.text?

I’ll test this out later to confirm.

This service is good for tests like this https://aws.amazon.com/device-farm/


There’s also MAX_TEXT_COUNT but I don’t have a clue what it’s for.


In game.project in the Android category there is an input_method field. The options for it are (default) KeyEvent and HiddenInputField. KeyEvent exists as an older method, and you should probably switch it to HiddenInputField, which has better support for 3rd party keyboard apps that are popular.


Can input.text be used to make custom key bindings? Not really. It can detect textual input, but it can’t detect characters like (afaik) shift, control, alt, or any of the function keys. It also can’t detect state. input.text also can’t detect alt codes.

What we really need is more arbitrary key input detection.

Input.GetChar() (with support for unprintable keys such as CHAR_TAB, CHAR_BACKSPACE, CHAR_ENTER, CHAR_ESCAPE, CHAR_PAGEUP, CHAR_PAGEDOWN, CHAR_END, CHAR_HOME, CHAR_LEFT, CHAR_UP, CHAR_RIGHT, CHAR_DOWN, CHAR_INSERT, CHAR_DELETE)
Input.PeekChar too maybe?

For gamepads:
(JOY_A, JOY_B, JOY_X, JOY_Y, JOY_LB, JOY_RB, JOY_BACK, JOY_START, JOY_LEFT, JOY_UP, JOY_RIGHT, JOY_DOWN, JOY_LSB, JOY_RSB, JOY_MENU)
Input.JoyDown( button, gamepad)
Input.JoyHit(button, gamepad)
Input.JoyX
Input.JoyY
Input.JoyZ

Input.KeyDown
Input.KeyHit

3 Likes

Don’t create .font files until you’re ready to define a font inside of it.

If you do create a .font and don’t define a font file then if you try to build you’ll likely get a build error.

1 Like

Loving these tips! Keep them coming! Thanks!

3 Likes

This tip goes for a lot of the filetypes you can create in Defold. Materials, tilesources, factories etc Unfortunately the errors are rarely informative. I believe that the upcoming editor will be much better at this.

2 Likes

You can detect if your user (on iOS/Android) is listening to music and disable your game’s audio.

if sound.is_music_playing() then
    for i, group_hash in ipairs(sound.get_groups()) do
        sound.set_group_gain(group_hash, 0)
    end
end

It’s good to give your users options. If you have an option screen with many options allow them to choose to mute the game’s audio if they are playing audio from another app, but having it mute by default is a good idea.

More info: http://www.defold.com/manuals/sound/

8 Likes

Alternative Git hosting. This post explains everything you need to know to setup your own git service with Defold.

3 Likes

Texture compression can take a long time. Be aware that if you have compression_level=BEST making bundles can take a long time. It may look like it has hanged, but if you have this setting on with a large project it’s most likely still busy so give it some more time.

2 Likes

On loading screens, which improve user experience, and load your main collection. As your project grows, and especially as your main collection grows, you will find it takes longer to boot up your game into its ready state. This can be a problem for mobile devices, and for best experience you’ll need to give an indication that your game is still happily getting the game ready for them.

It’s not easy to know how long it will take to load your main collection. You want a visual indicator, you want a progress bar that is constantly moving. It’s not a bad idea to “fake” your progress bars so that they are constantly moving, but have diminishing speed the closer they get to 100%, and then have them instantly jump to 100% before screen transitions. But you’ll still want to make what’s right for your game. Some games “fake” the first 50% and then the rest is real progress based on chunk milestones, but again with loading your main collection there is no indicator just a good guess you can make based on how long it usually takes, and remember if you change the assets in your collection it will change how long it takes to load. Also worth keeping in mind just because your test device loads it quickly doesn’t mean other low end phones will.

If your game loads pretty fast you can skip the progress bar loading screen completely, and just use your splash as the loading screen. With or without the “Loading…” text. You could omit this text, and just have it so that if they tap the screen it then show this “Loading…” text to reassure your users.

It’s worth noting some technical details about Android and iOS. If you make a large main collection and don’t have a loading screen - when your user opens your game they will be faced with just a black screen while they wait for the main collection to load. This is avoided by using a light weight collection that uses the Collection Proxy feature to then load and switch to the main collection.

When iOS apps load they first show a hardware splash image. This image is suggested to be the same image you first display to the user when you render your first screen too. They use this hardware splash to fake out users into believing that apps open faster than they really do. As soon as the app is ready your app takes over, and the best experience is to display the same image and then transition from it. These images are what you can define in the iOS section of game.project file. All of the different sizes are hardware splash images for the various models of Apple products.

You can also put loading screen inbetween loading large collections. I’ve not tested async loading yet, but assuming it works how I think it does if you know you are transitioning screens soon you could pre-load the next screen’s collection and have it ready to go to nearly instantly.

More information on Collection Proxies

I’m preparing a loading screen template and will include it in a future post.

8 Likes

Self hosting a pre-made push notification service. I’ve not used this, just sharing it as it may be useful to some Defold users out there.

Pushkin is a free open source tool for sending push notifications. It was developed with a focus on speed and enabling fast experimentation. Pushkin was mainly built for supporting online mobile games, but can easily be extended to any type of application. It supports both Android and iOS platforms.

Pushkin is designed to be a responsive tool. You can design your systems around Pushkin so it reacts to your game server, database server, client or really any service that can send a HTTP POST request. It is also easily scalable, because you can run as many Pushkin instances as you want. One instance is capable of pushing 500 messages per second.

http://docs.pushkin.io/en/latest/

2 Likes

Pro Tip: Don’t compose long messages in the text box here, do it elsewhere. Things can happen and your message eaten. :sweat:

9 Likes

Use shortcuts to find and open files for editing quickly.

In Preferences -> General -> Keys there is an option Open Resource.

This can be used to open a dialog which will allow you to search for a file to open. It can be any file, and it will be opened with default option. This can be useful if you are working with a big project, and don’t want to hunt for the file in the file tree.

You can change the shortcut for the Open Resource dialog too. I’m testing setting it as simply F1. Depending on OS and setup you may prefer some other shortcut.

Read through the other keys in the editor and experiment with them. Generally once you memorize shortcuts they can speed up your workflow.

2 Likes

Using layers, and ordering within layers based on y position. In some games, you want to have discrete rendering layers for objects. You also want to have objects on layers to be sorted based on y position so that higher objects on the plane are drawn behind objects which are in front of their y position.

Script by @Andreas_Jirenius

Download:

render_order.script (218 Bytes)

render_order.script source

local layer_z = { -0.9, 0.0, 1.0 } -- layer 1, layer 2, layer 3 with default z values

go.property("layer",1) -- exposes this value to be able to be changed in editor, defaults to 1

function update(self, dt)
	local pos = go.get_position()
	pos.z = layer_z[self.layer]-pos.y*0.0001 -- start with layer z default, modify it based on y position
	go.set_position(pos)
end

Add this script as a component to any game object you wish to sort based on layer and y position. You could extend it further for example by adding an additional optional offset property to make certain objects stay on discrete whole number layers but still be above or below everything else on that layer without needing to define more layers.

Remember that your camera z position matters for what is able to be seen by your camera. If you position at z positions behind your camera anything there won’t be visible and so won’t be drawn.

Adding scripts to objects has a runtime cost, and having too many scripts can cause you to hit the default script limit. If you want to sort or manage hundreds of bullets for example it would be better to do that from a single script and not have every bullet object have its own copy of the script.

13 Likes

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.

3 Likes

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)

5 Likes

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:

3 Likes

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)

2 Likes

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)

5 Likes

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

2 Likes

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))()
4 Likes

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
3 Likes