Loading...
Loading...
Build and debug the core of a Defold game in Lua: game.project settings, collections, game objects and components, script lifecycle and self state, go.property, input focus and bindings, URLs and message passing, factories, collection factories and collection proxies, plus building and smoke-running with Bob. Use when a project has game.project or .collection, .go, .script, .gui_script or .input_binding files, or the request mentions Defold, msg.post, on_message, on_input, acquire_input_focus, factory.create, collection proxy, bob.jar, or a Defold build error.
npx skill4agent add gamedev-skills/awesome-gamedev-agent-skills defold-coregame.project.collection.go.script.gui_scriptlove2d-coregame.project[bootstrap] main_collection[input] game_binding[project] dependencies.go.collection.script.gui_script.luareferences/file-formats.mdpython scripts/check_defold_project.py <project-dir>ERROR/pathsgame.projectcrequirejava -jar bob.jar --root . --variant headless --archive resolve buildbob.jarERROR:references/file-formats.mdreferences/build-and-run.mdERROR:SCRIPT:ERROR:GAMEOBJECT:game.project/main/player.gogame.projectc[bootstrap]
main_collection = /main/main.collectionc
[input]
game_binding = /input/game.input_bindingcgame.project/builtins/...data:references/file-formats.md# main.collection (excerpt): place player.go and override its script's speed
instances {
id: "player"
prototype: "/main/player.go"
component_properties {
id: "player"
properties { id: "speed" value: "250.0" type: PROPERTY_TYPE_NUMBER }
}
}selfgo.property("speed", 200) -- top level only, literal default; editable per instance
local LEFT = hash("left") -- hash ids once, not every frame
local RIGHT = hash("right")
local FIRE = hash("fire")
function init(self)
msg.post(".", "acquire_input_focus") -- no focus, no on_input calls
self.held = {} -- per-instance state lives on self
end
function update(self, dt)
local dir = (self.held[RIGHT] and 1 or 0) - (self.held[LEFT] and 1 or 0)
if dir ~= 0 then
local pos = go.get_position()
pos.x = pos.x + dir * self.speed * dt -- dt-scaled: same speed at any frame rate
go.set_position(pos)
end
end
function on_input(self, action_id, action)
if action_id == LEFT or action_id == RIGHT then
if action.pressed then self.held[action_id] = true
elseif action.released then self.held[action_id] = nil end
return true -- consumed: listeners lower on the stack skip it
elseif action_id == FIRE and action.pressed then
factory.create("#bulletfactory", go.get_position(), nil,
{ velocity = vmath.vector3(0, 600, 0) })
return true
end
end
function final(self)
msg.post(".", "release_input_focus")
endinitfinalfixed_updateupdatelate_updateupdateon_messageon_inputon_reloadfixed_update[engine] fixed_update_frequency[physics] use_fixed_timestep = 1selfpairs(self)pprint(self)msg.urlvmath.vector3vector4vmath.quatresource.atlas("/main/main.atlas").input_bindingkey_triggermouse_triggertrueon_inputpressedreleased[socket:][path][#fragment]".""#""#sprite""enemy#ai""/manager#controller""main:/loader#loader"msg.post("/manager#controller", "enemy_spotted", { id = go.get_id() })
function on_message(self, message_id, message, sender)
if message_id == hash("enemy_spotted") then
print("from", sender, "id", message.id)
end
endERROR:GAMEOBJECT: Instance '/x' could not be found when dispatching message-- factory component "#bulletfactory" -> one game object; properties override go.property values
local id = factory.create("#bulletfactory", pos, nil, { velocity = vmath.vector3(0, 600, 0) })
-- collectionfactory component "#wavefactory" -> table of collection ids -> new instance ids
local ids = collectionfactory.create("#wavefactory", vmath.vector3(480, 500, 0))
local leader = ids[hash("/leader")] -- e.g. hash: [/collection0/leader]
go.delete(ids, true) -- later: delete them and their childrengo.delete(){ [hash("/leader")] = { hp = 5 } }-- excerpt from the loader script; the collection's "#levelproxy" component is a collectionproxy
function init(self)
msg.post(".", "acquire_input_focus") -- else the loaded world gets no input
msg.post("#levelproxy", "async_load") -- or "load"
end
function on_message(self, message_id, message, sender)
if message_id == hash("proxy_loaded") then
msg.post(sender, "init")
msg.post(sender, "enable")
elseif message_id == hash("level_done") then
msg.post("#levelproxy", "unload") -- disables and finalizes first
elseif message_id == hash("proxy_unloaded") then
-- safe to load the next level here
end
endname:msg.post("main:/loader#loader", ...)level1:/level#levelset_time_step { factor = 0, mode = 0 }game.projectbob.jarlibrary.defold_min_versionjava -jar bob.jar --versionthe bootstrap.main_collection '/main/main.collectio' can't be found/main/main.collectioncinput.game_binding.input_bindingcERROR: build/default/_generated_….factory:0: the prototype '/main/x.go' can't be found.go/main/x.goon_inputacquire_input_focusinput.game_bindingtruealready a socket with the same nameproxy_loadedname:"main""default"fixed_update[engine] fixed_update_frequency[physics] use_fixed_timestep = 1module 'modules.util' not foundrequirerequire "modules/util"require "modules.util"/modules/util.luatostring(id)hash: [<unknown:…>]Failed to initialize Remoterysys.exitreferences/file-formats.mdgame.project.collection.go.atlas.input_bindingreferences/build-and-run.mdbob.jarscripts/check_defold_project.py--helpinput-systemsgame-ui-ux.gui_scriptphysics-tuningcamera-systemslate_updatesave-systemssys.savesys.loadgame-feelgo.animateplatformerlevel-designlove2d-core