diff --git a/physics/box2d_dynamic_scale/all.texture_profiles b/physics/box2d_dynamic_scale/all.texture_profiles new file mode 100644 index 00000000..5b0d7762 --- /dev/null +++ b/physics/box2d_dynamic_scale/all.texture_profiles @@ -0,0 +1,18 @@ +path_settings { + path: "**" + profile: "Default" +} +profiles { + name: "Default" + platforms { + os: OS_ID_GENERIC + formats { + format: TEXTURE_FORMAT_RGBA + compression_level: BEST + compression_type: COMPRESSION_TYPE_DEFAULT + } + mipmaps: false + max_texture_size: 0 + premultiply_alpha: true + } +} diff --git a/physics/box2d_dynamic_scale/box2d_v2.appmanifest b/physics/box2d_dynamic_scale/box2d_v2.appmanifest new file mode 100644 index 00000000..b3abe8c8 --- /dev/null +++ b/physics/box2d_dynamic_scale/box2d_v2.appmanifest @@ -0,0 +1,95 @@ +platforms: + arm64-ios: + context: + excludeLibs: [] + excludeSymbols: [] + symbols: [] + libs: [] + frameworks: [] + linkFlags: [] + x86_64-ios: + context: + excludeLibs: [] + excludeSymbols: [] + symbols: [] + libs: [] + frameworks: [] + linkFlags: [] + armv7-android: + context: + excludeLibs: [] + excludeJars: [] + excludeSymbols: [] + symbols: [] + libs: [] + linkFlags: [] + jetifier: true + arm64-android: + context: + excludeLibs: [] + excludeJars: [] + excludeSymbols: [] + symbols: [] + libs: [] + linkFlags: [] + jetifier: true + arm64-osx: + context: + excludeLibs: [] + excludeSymbols: [] + symbols: [] + libs: [] + frameworks: [] + linkFlags: [] + x86_64-osx: + context: + excludeLibs: [] + excludeSymbols: [] + symbols: [] + libs: [] + frameworks: [] + linkFlags: [] + x86_64-linux: + context: + excludeLibs: [] + excludeSymbols: [] + symbols: [] + libs: [] + linkFlags: [] + arm64-linux: + context: + excludeLibs: [] + excludeSymbols: [] + symbols: [] + libs: [] + linkFlags: [] + x86-win32: + context: + excludeLibs: [] + excludeSymbols: [] + symbols: [] + libs: [] + linkFlags: [] + x86_64-win32: + context: + excludeLibs: [] + excludeSymbols: [] + symbols: [] + libs: [] + linkFlags: [] + wasm-web: + context: + excludeLibs: [] + excludeJsLibs: [] + excludeSymbols: [] + symbols: [] + libs: [] + linkFlags: [] + wasm_pthread-web: + context: + excludeLibs: [] + excludeJsLibs: [] + excludeSymbols: [] + symbols: [] + libs: [] + linkFlags: [] diff --git a/physics/box2d_dynamic_scale/box2d_v3.appmanifest b/physics/box2d_dynamic_scale/box2d_v3.appmanifest new file mode 100644 index 00000000..9751deca --- /dev/null +++ b/physics/box2d_dynamic_scale/box2d_v3.appmanifest @@ -0,0 +1,100 @@ +platforms: + armv7-ios: + context: + excludeLibs: [physics, box2d_defold, script_box2d_defold] + excludeSymbols: [] + libs: [physics_2d, box2d, script_box2d, physics_3d] + arm64-ios: + context: + excludeLibs: [physics, box2d_defold, script_box2d_defold] + excludeSymbols: [] + symbols: [] + libs: [physics_2d, box2d, script_box2d, physics_3d] + frameworks: [] + linkFlags: [] + x86_64-ios: + context: + excludeLibs: [physics, box2d_defold, script_box2d_defold] + excludeSymbols: [] + symbols: [] + libs: [physics_2d, box2d, script_box2d, physics_3d] + frameworks: [] + linkFlags: [] + armv7-android: + context: + excludeLibs: [physics, box2d_defold, script_box2d_defold] + excludeJars: [] + excludeSymbols: [] + symbols: [] + libs: [physics_2d, box2d, script_box2d, physics_3d] + linkFlags: [] + jetifier: true + arm64-android: + context: + excludeLibs: [physics, box2d_defold, script_box2d_defold] + excludeJars: [] + excludeSymbols: [] + symbols: [] + libs: [physics_2d, box2d, script_box2d, physics_3d] + linkFlags: [] + jetifier: true + arm64-osx: + context: + excludeLibs: [physics, box2d_defold, script_box2d_defold] + excludeSymbols: [] + symbols: [] + libs: [physics_2d, box2d, script_box2d, physics_3d] + frameworks: [] + linkFlags: [] + x86_64-osx: + context: + excludeLibs: [physics, box2d_defold, script_box2d_defold] + excludeSymbols: [] + symbols: [] + libs: [physics_2d, box2d, script_box2d, physics_3d] + frameworks: [] + linkFlags: [] + x86_64-linux: + context: + excludeLibs: [physics, box2d_defold, script_box2d_defold] + excludeSymbols: [] + symbols: [] + libs: [physics_2d, box2d, script_box2d, physics_3d] + linkFlags: [] + arm64-linux: + context: + excludeLibs: [physics, box2d_defold, script_box2d_defold] + excludeSymbols: [] + symbols: [] + libs: [physics_2d, box2d, script_box2d, physics_3d] + linkFlags: [] + x86-win32: + context: + excludeLibs: [libphysics, libbox2d_defold, script_box2d_defold] + excludeSymbols: [] + symbols: [] + libs: [libphysics_2d.lib, libbox2d.lib, libscript_box2d.lib, libphysics_3d.lib] + linkFlags: [] + x86_64-win32: + context: + excludeLibs: [libphysics, libbox2d_defold, script_box2d_defold] + excludeSymbols: [] + symbols: [] + libs: [libphysics_2d.lib, libbox2d.lib, libscript_box2d.lib, libphysics_3d.lib] + linkFlags: [] + wasm-web: + context: + excludeLibs: [physics, box2d_defold, script_box2d_defold] + excludeJsLibs: [] + excludeSymbols: [] + symbols: [] + libs: [physics_2d, box2d, script_box2d, physics_3d] + linkFlags: [] + wasm_pthread-web: + context: + excludeLibs: [physics, box2d_defold, script_box2d_defold] + excludeJsLibs: [] + excludeSymbols: [] + symbols: [] + libs: [physics_2d, box2d, script_box2d, physics_3d] + linkFlags: [] diff --git a/physics/box2d_dynamic_scale/example.md b/physics/box2d_dynamic_scale/example.md new file mode 100644 index 00000000..6d83a001 --- /dev/null +++ b/physics/box2d_dynamic_scale/example.md @@ -0,0 +1,70 @@ +--- +tags: physics, box2d +title: Box2D dynamic shape scale and mass +brief: Resize dynamic Box2D collision shapes at runtime and recalculate body mass. +author: Defold Foundation +scripts: box2d_dynamic_scale_v3.script, box2d_dynamic_scale_v2.script +thumbnail: thumbnail.webp +--- + +This example shows how to change bodies shapes and mass in runtime. + +It includes 4 independent dynamic Box2D bodies. + +Click or tap to give every square body a new random size, +update its collision shape, recalculate its mass, and apply a random impulse. + +## What You'll Learn + +- How to get a Box2D body from a Defold collision object +- How to detect the active Box2D version with `b2d.get_version()` +- How to resize collision geometry through the V2 fixture API +- How to resize collision geometry through the V3 shape API +- How `update_mass = true` makes body mass follow the new collision size +- How to apply a dynamic impulse to the body + +## Setup + +The collection contains four instances of `block.go` game object. +The `block.go` prototype contains: + +- `script_v3`, which runs only with the Box2D V3 backend +- `script_v2`, which runs only with the Box2D V2 backend +- a square sprite +- a dynamic box collision object with base half-extents of `40.0` + +The collection also contains `walls` game object with: + +- one static collision object with four box shapes around the play area +- a label that explains the click or tap interaction. + +![setup](setup.png) + +The `game.project` of this example is configured to build with `/box2d_v3.appmanifest` by default. +To test V2 locally after downloading the example, change `Native Extensions -> App Manifest` in `game.project` to `/box2d_v2.appmanifest`. + +## How It Works + +Both scripts read `b2d.get_version()` in `init()` and are only active if a matching version is used - +`box2d_dynamic_scale_v2.script` only continues when the major version is 2, +while `box2d_dynamic_scale_v3.script` only continues when the major version is 3. + +The active script acquires input focus and initialized a random number generator. + +When the built-in `touch` action is pressed, each block picks a random uniform scale from `0.5` to `1.5`. +The script multiplies the base sprite size and base collision half-extent by that scale, +so the visible square and physics box stay aligned. + +The mass changes because `update_mass = true` makes Box2D recalculate the body mass from the resized shape. + +In Box2D V2, collision geometry is attached to a body through fixtures. +The V2 script reads the first fixture with `b2d.body.get_fixtures()` +and resizes it with `b2d.fixture.set_shape(body, fixture.index, shape, true)`. + +In Box2D V3, collision geometry is attached through shapes. +The V3 script reads the first shape with `b2d.body.get_shapes()` +and resizes it with `b2d.shape.set_shape(shape.shape_id, shape, true)`. + +After resizing, the active script applies a random linear impulse at the body's world center. +Since each body has just recalculated its mass from its new collision size, +the resulting movement makes the size and mass changes visible. diff --git a/physics/box2d_dynamic_scale/example/block.go b/physics/box2d_dynamic_scale/example/block.go new file mode 100644 index 00000000..6be31999 --- /dev/null +++ b/physics/box2d_dynamic_scale/example/block.go @@ -0,0 +1,53 @@ +components { + id: "script_v3" + component: "/example/box2d_dynamic_scale_v3.script" +} +components { + id: "script_v2" + component: "/example/box2d_dynamic_scale_v2.script" +} +embedded_components { + id: "sprite" + type: "sprite" + data: "default_animation: \"body_soft\"\n" + "material: \"/builtins/materials/sprite.material\"\n" + "size {\n" + " x: 80.0\n" + " y: 80.0\n" + "}\n" + "size_mode: SIZE_MODE_MANUAL\n" + "textures {\n" + " sampler: \"texture_sampler\"\n" + " texture: \"/textures/textures.atlas\"\n" + "}\n" + "" +} +embedded_components { + id: "collisionobject" + type: "collisionobject" + data: "type: COLLISION_OBJECT_TYPE_DYNAMIC\n" + "mass: 1.0\n" + "friction: 0.2\n" + "restitution: 0.2\n" + "group: \"block\"\n" + "mask: \"block\"\n" + "mask: \"wall\"\n" + "embedded_collision_shape {\n" + " shapes {\n" + " shape_type: TYPE_BOX\n" + " position {\n" + " }\n" + " rotation {\n" + " }\n" + " index: 0\n" + " count: 3\n" + " id: \"box\"\n" + " }\n" + " data: 40.0\n" + " data: 40.0\n" + " data: 10.0\n" + "}\n" + "linear_damping: 0.2\n" + "angular_damping: 0.1\n" + "" +} diff --git a/physics/box2d_dynamic_scale/example/box2d_dynamic_scale.collection b/physics/box2d_dynamic_scale/example/box2d_dynamic_scale.collection new file mode 100644 index 00000000..de8ab0a6 --- /dev/null +++ b/physics/box2d_dynamic_scale/example/box2d_dynamic_scale.collection @@ -0,0 +1,126 @@ +name: "box2d_dynamic_scale" +instances { + id: "block_small" + prototype: "/example/block.go" + position { + x: 180.0 + y: 500.0 + } +} +instances { + id: "block_medium" + prototype: "/example/block.go" + position { + x: 320.0 + y: 500.0 + } +} +instances { + id: "block_large" + prototype: "/example/block.go" + position { + x: 460.0 + y: 500.0 + } +} +instances { + id: "block_extra_large" + prototype: "/example/block.go" + position { + x: 580.0 + y: 500.0 + } +} +scale_along_z: 0 +embedded_instances { + id: "walls" + data: "embedded_components {\n" + " id: \"collisionobject\"\n" + " type: \"collisionobject\"\n" + " data: \"type: COLLISION_OBJECT_TYPE_STATIC\\n" + "mass: 0.0\\n" + "friction: 0.1\\n" + "restitution: 0.9\\n" + "group: \\\"wall\\\"\\n" + "mask: \\\"block\\\"\\n" + "embedded_collision_shape {\\n" + " shapes {\\n" + " shape_type: TYPE_BOX\\n" + " position {\\n" + " y: -400.0\\n" + " }\\n" + " rotation {\\n" + " }\\n" + " index: 0\\n" + " count: 3\\n" + " id: \\\"floor\\\"\\n" + " }\\n" + " shapes {\\n" + " shape_type: TYPE_BOX\\n" + " position {\\n" + " y: 400.0\\n" + " }\\n" + " rotation {\\n" + " }\\n" + " index: 3\\n" + " count: 3\\n" + " id: \\\"ceiling\\\"\\n" + " }\\n" + " shapes {\\n" + " shape_type: TYPE_BOX\\n" + " position {\\n" + " x: -400.0\\n" + " }\\n" + " rotation {\\n" + " }\\n" + " index: 6\\n" + " count: 3\\n" + " id: \\\"wall_left\\\"\\n" + " }\\n" + " shapes {\\n" + " shape_type: TYPE_BOX\\n" + " position {\\n" + " x: 400.0\\n" + " }\\n" + " rotation {\\n" + " }\\n" + " index: 9\\n" + " count: 3\\n" + " id: \\\"wall_right\\\"\\n" + " }\\n" + " data: 360.0\\n" + " data: 40.0\\n" + " data: 10.0\\n" + " data: 360.0\\n" + " data: 40.0\\n" + " data: 10.0\\n" + " data: 40.0\\n" + " data: 440.0\\n" + " data: 10.0\\n" + " data: 40.0\\n" + " data: 440.0\\n" + " data: 10.0\\n" + "}\\n" + "\"\n" + "}\n" + "embedded_components {\n" + " id: \"label\"\n" + " type: \"label\"\n" + " data: \"size {\\n" + " x: 620.0\\n" + " y: 64.0\\n" + "}\\n" + "text: \\\"Click or tap to change the bodies\\\"\\n" + "font: \\\"/fonts/text28.font\\\"\\n" + "material: \\\"/builtins/fonts/label-df.material\\\"\\n" + "\"\n" + " position {\n" + " y: 300.0\n" + " }\n" + "}\n" + "" + position { + x: 360.0 + y: 360.0 + } +} diff --git a/physics/box2d_dynamic_scale/example/box2d_dynamic_scale_v2.script b/physics/box2d_dynamic_scale/example/box2d_dynamic_scale_v2.script new file mode 100644 index 00000000..0f8dae35 --- /dev/null +++ b/physics/box2d_dynamic_scale/example/box2d_dynamic_scale_v2.script @@ -0,0 +1,75 @@ +function init(self) + -- This script uses the Box2D V2 fixture API. + self.active = b2d.get_version().major == 2 + + -- If Box2D V2 is not used, skip further processing + if not self.active then + return + end + + -- `b2d.get_body()` returns the native Box2D body created by the given collision object. + self.body = b2d.get_body("#collisionobject") + + -- In Box2D V2, collision geometry and material data live in fixtures. + self.fixture_index = b2d.body.get_fixtures(self.body)[1].index + -- v3: + self.shape_id = b2d.body.get_shapes(self.body)[1].shape_id + + -- Acquire input focus to handle inputs + msg.post(".", "acquire_input_focus") + + -- Initialize random number generator + math.randomseed(os.time()) +end + +-- The built-in touch action also covers mouse clicks in the built-in all.input_binding. +local TOUCH = hash("touch") + +-- Base size will be used to change the scale around the initial size +local BASE_SIZE = 80.0 +local BASE_HALF_EXTENT = 40.0 + +-- Helper function to get a random scale with values in range 0.5-1.5 +local function get_random_scale() + local random_number = math.random(5,15)/10 + return vmath.vector3(random_number, random_number, 0) +end + +local function resize_body(self, scale_vector) + local half_extent = BASE_HALF_EXTENT * scale_vector.x + + -- The last parameter update_mass set to true will cause the mass to be updated. + local update_mass = true + + -- Update a box shape using the polygon box convenience format. + -- V2 collision geometry is addressed through fixtures attached to the body. + -- The shape type must match the current fixture shape type. + b2d.fixture.set_shape(self.body, self.fixture_index, { + type = b2d.shape.SHAPE_TYPE_BOX, + hx = half_extent, + hy = half_extent, + }, update_mass) + + -- Also change the vector size to match the new shape + local size_vector = BASE_SIZE * scale_vector + go.set("#sprite", "size", size_vector) +end + +function on_input(self, action_id, action) + -- If Box2D V2 is not used, skip further processing + if not self.active then + return + end + + if action_id == TOUCH and action.pressed then + -- When click or touch is pressed - change the scale randomly + resize_body(self, get_random_scale()) + + -- And apply a random impulse to the center of the body + -- to notice mass differences applied + local random_impulse_x = math.random(-400,400) + local random_impulse_y = math.random(-400,400) + local impulse = vmath.vector3(random_impulse_x, random_impulse_y, 0) + b2d.body.apply_linear_impulse(self.body, impulse, b2d.body.get_world_center(self.body)) + end +end diff --git a/physics/box2d_dynamic_scale/example/box2d_dynamic_scale_v3.script b/physics/box2d_dynamic_scale/example/box2d_dynamic_scale_v3.script new file mode 100644 index 00000000..943e8433 --- /dev/null +++ b/physics/box2d_dynamic_scale/example/box2d_dynamic_scale_v3.script @@ -0,0 +1,73 @@ +function init(self) + -- This script uses the Box2D V3 fixture API. + self.active = b2d.get_version().major == 3 + + -- If Box2D V3 is not used, skip further processing + if not self.active then + return + end + + -- `b2d.get_body()` returns the native Box2D body created by the given collision object. + self.body = b2d.get_body("#collisionobject") + + -- In Box2D V3, collision geometry and material data live in shapes. + self.shape_id = b2d.body.get_shapes(self.body)[1].shape_id + + -- Acquire input focus to handle inputs + msg.post(".", "acquire_input_focus") + + -- Initialize random number generator + math.randomseed(os.time()) +end + +-- The built-in touch action also covers mouse clicks in the built-in all.input_binding. +local TOUCH = hash("touch") + +-- Base size will be used to change the scale around the initial size +local BASE_SIZE = 80.0 +local BASE_HALF_EXTENT = 40.0 + +-- Helper function to get a random scale with values in range 0.5-1.5 +local function get_random_scale() + local random_number = math.random(5,15)/10 + return vmath.vector3(random_number, random_number, 0) +end + +local function resize_body(self, scale_vector) + local half_extent = BASE_HALF_EXTENT * scale_vector.x + + -- The last parameter update_mass set to true will cause the mass to be updated. + local update_mass = true + + -- Update a box shape using the polygon box convenience format. + -- V3 collision geometry is addressed through shapes. + -- The shape type must match the current fixture shape type. + b2d.shape.set_shape(self.shape_id, { + type = b2d.shape.SHAPE_TYPE_BOX, + hx = half_extent, + hy = half_extent, + }, update_mass) + + -- Also change the vector size to match the new shape + local size_vector = BASE_SIZE * scale_vector + go.set("#sprite", "size", size_vector) +end + +function on_input(self, action_id, action) + -- If Box2D V3 is not used, skip further processing + if not self.active then + return + end + + if action_id == TOUCH and action.pressed then + -- When click or touch is pressed - change the scale randomly + resize_body(self, get_random_scale()) + + -- And apply a random impulse to the center of the body + -- to notice mass differences applied + local random_impulse_x = math.random(-400,400) + local random_impulse_y = math.random(-400,400) + local impulse = vmath.vector3(random_impulse_x, random_impulse_y, 0) + b2d.body.apply_linear_impulse(self.body, impulse, b2d.body.get_world_center(self.body)) + end +end diff --git a/physics/box2d_dynamic_scale/example/instructions.go b/physics/box2d_dynamic_scale/example/instructions.go new file mode 100644 index 00000000..e69de29b diff --git a/physics/box2d_dynamic_scale/fonts/SourceSansPro-Semibold.ttf b/physics/box2d_dynamic_scale/fonts/SourceSansPro-Semibold.ttf new file mode 100644 index 00000000..50205948 Binary files /dev/null and b/physics/box2d_dynamic_scale/fonts/SourceSansPro-Semibold.ttf differ diff --git a/physics/box2d_dynamic_scale/fonts/text28.font b/physics/box2d_dynamic_scale/fonts/text28.font new file mode 100644 index 00000000..3d9c4a8e --- /dev/null +++ b/physics/box2d_dynamic_scale/fonts/text28.font @@ -0,0 +1,5 @@ +font: "/fonts/SourceSansPro-Semibold.ttf" +material: "/builtins/fonts/font-df.material" +size: 28 +output_format: TYPE_DISTANCE_FIELD +characters: " !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" diff --git a/physics/box2d_dynamic_scale/game.project b/physics/box2d_dynamic_scale/game.project new file mode 100644 index 00000000..e605cf71 --- /dev/null +++ b/physics/box2d_dynamic_scale/game.project @@ -0,0 +1,36 @@ +[bootstrap] +main_collection = /example/box2d_dynamic_scale.collectionc + +[script] +shared_state = 1 + +[display] +width = 720 +height = 720 +high_dpi = 1 + +[android] +input_method = HiddenInputField + +[physics] +gravity_y = -900.0 +scale = 0.01 +use_fixed_timestep = 1 + +[html5] +scale_mode = no_scale + +[input] +game_binding = /builtins/input/all.input_bindingc + +[project] +title = Box2D Dynamic Scale + +[native_extension] +app_manifest = /box2d_v3.appmanifest + +[render] +clear_color_red = 0.160156 +clear_color_green = 0.164063 +clear_color_blue = 0.183594 + diff --git a/physics/box2d_dynamic_scale/setup.png b/physics/box2d_dynamic_scale/setup.png new file mode 100644 index 00000000..7e26c151 Binary files /dev/null and b/physics/box2d_dynamic_scale/setup.png differ diff --git a/physics/box2d_dynamic_scale/textures/body_soft.png b/physics/box2d_dynamic_scale/textures/body_soft.png new file mode 100644 index 00000000..928ca6ab Binary files /dev/null and b/physics/box2d_dynamic_scale/textures/body_soft.png differ diff --git a/physics/box2d_dynamic_scale/textures/textures.atlas b/physics/box2d_dynamic_scale/textures/textures.atlas new file mode 100644 index 00000000..7eaa8d22 --- /dev/null +++ b/physics/box2d_dynamic_scale/textures/textures.atlas @@ -0,0 +1,4 @@ +images { + image: "/textures/body_soft.png" +} +extrude_borders: 2 diff --git a/physics/box2d_dynamic_scale/thumbnail.webp b/physics/box2d_dynamic_scale/thumbnail.webp new file mode 100644 index 00000000..2ab19fa7 Binary files /dev/null and b/physics/box2d_dynamic_scale/thumbnail.webp differ diff --git a/physics/box2d_weld_joint/example/box2d_weld_joint.script b/physics/box2d_weld_joint/example/box2d_weld_joint.script index 35ed48c8..01a972f6 100644 --- a/physics/box2d_weld_joint/example/box2d_weld_joint.script +++ b/physics/box2d_weld_joint/example/box2d_weld_joint.script @@ -1,5 +1,7 @@ +-- Half of the block size is needed for specifying where the weld will be local BLOCK_HALF_SIZE = 40 +-- Helper function to create a single weld joint between two bodies local function create_weld(self, body_a, body_b, local_anchor_a, local_anchor_b) local joint = b2d.joint.create_weld(body_a, body_b, { -- Local anchors mark the touching edges that should stay locked together. @@ -11,9 +13,11 @@ local function create_weld(self, body_a, body_b, local_anchor_a, local_anchor_b) collide_connected = false, }) + -- We additionally store the created joints references in order to remove them later table.insert(self.joints, joint) end +-- Helper function to create the 2 weld joints in the example local function create_welds(self) -- Weld the right block to the center block at their shared vertical edge. create_weld(self, self.center, self.right, vmath.vector3(BLOCK_HALF_SIZE, 0, 0), vmath.vector3(-BLOCK_HALF_SIZE, 0, 0)) @@ -23,31 +27,36 @@ local function create_welds(self) end function init(self) + -- `b2d.get_body()` returns the native Box2D body created by the given collision object. self.center = b2d.get_body("/center#collisionobject") self.right = b2d.get_body("/right#collisionobject") self.lower = b2d.get_body("/lower#collisionobject") + -- Create a table for joints references and then create weld joints in the example self.joints = {} - create_welds(self) + -- Acquire input focus to handle inputs msg.post(".", "acquire_input_focus") end -function final(self) - for _, joint in ipairs(self.joints) do - b2d.joint.destroy(joint) - end - - msg.post(".", "release_input_focus") -end - local TOUCH = hash("touch") function on_input(self, action_id, action) + -- The built-in touch action also covers mouse clicks in the built-in all.input_binding. if action_id == TOUCH and action.pressed then - -- The welds transfer this velocity change through the whole L-shaped cluster. + -- The weld joints transfer this velocity change through the whole L-shaped cluster. b2d.body.set_linear_velocity(self.right, vmath.vector3(math.random(-300,300), 900, 0)) b2d.body.set_angular_velocity(self.right, math.random(-10,10)) end end + +function final(self) + -- Joints created through b2d.joint should be explicitly destroyed. + for _, joint in ipairs(self.joints) do + b2d.joint.destroy(joint) + end + + -- Release input focus + msg.post(".", "release_input_focus") +end