diff --git a/physics/box2d_motor_joint/all.texture_profiles b/physics/box2d_motor_joint/all.texture_profiles new file mode 100644 index 00000000..5b0d7762 --- /dev/null +++ b/physics/box2d_motor_joint/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_motor_joint/box2D_V2.appmanifest b/physics/box2d_motor_joint/box2D_V2.appmanifest new file mode 100644 index 00000000..b3abe8c8 --- /dev/null +++ b/physics/box2d_motor_joint/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_motor_joint/box2D_V3.appmanifest b/physics/box2d_motor_joint/box2D_V3.appmanifest new file mode 100644 index 00000000..9751deca --- /dev/null +++ b/physics/box2d_motor_joint/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_motor_joint/example.md b/physics/box2d_motor_joint/example.md new file mode 100644 index 00000000..edb65ca3 --- /dev/null +++ b/physics/box2d_motor_joint/example.md @@ -0,0 +1,52 @@ +--- +tags: physics, box2d +title: Box2D Motor Joint +brief: Create and control a motorized Box2D joint from script using Box2D V2 and V3. +author: Defold Foundation +scripts: box2d_motor_joint_v3.script, box2d_motor_joint_v2.script +thumbnail: thumbnail.webp +--- + +This example creates a motorized Box2D joint at runtime. It works with both Box2D V2 and V3 by attaching one script for each backend. Each script checks `b2d.get_version()` during `init()` and becomes a no-op when the other backend is active. + +Click or tap the window to reverse the motor direction. + +## What You'll Learn + +- How to get Box2D body handles from Defold collision objects +- How to detect the active Box2D version with `b2d.get_version()` +- How to create a pivoted motor joint with `b2d.joint.create_revolute()` +- How to control joint motor speed with `b2d.joint.set_motor_speed()` +- How to tune the Box2D V3 joint solver with `b2d.world.set_joint_tuning()` + +## Setup + +The collection contains a static `pivot` game object, one dynamic `arm` game object with a particle effect, and a controller game object. + +The `pivot` object marks the world point the arm should rotate around. The `arm` object is the dynamic body driven by the joint. The example uses a revolute joint with its motor enabled, because the revolute joint provides a stable hinge pivot while the motor drives the rotation. + +The controller has both backend scripts attached. Each script checks `b2d.get_version()` and only runs when the selected app manifest matches its Box2D backend. + +![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`. + +![game_project](game_project.png) + +## How It Works + +Both scripts read `b2d.get_version()` once. `box2d_motor_joint_v2.script` only continues when the major version is 2, while `box2d_motor_joint_v3.script` only continues when the major version is 3. + +`b2d.get_body()` returns the Box2D bodies owned by the `pivot` and `arm` collision objects. The active script then creates a revolute joint between those bodies with `b2d.joint.create_revolute()`. + +The joint definition uses: + +- `local_anchor_a` on the pivot body +- `local_anchor_b` on the arm body +- `enable_motor` to turn on the joint motor +- `max_motor_torque` to limit how strongly the motor can rotate the arm +- `motor_speed` to set the current motor direction and speed + +The important part is the arm anchor. The pivot is placed in the collection as a visible reference point. The scripts convert that world position into the arm's local space, so the arm rotates around the same visible pivot instead of rotating around its center. + +Click or tap to reverse the motor with `b2d.joint.set_motor_speed()`. The V3 script also calls `b2d.world.set_joint_tuning()` to adjust the joint solver used by the Box2D V3 backend. diff --git a/physics/box2d_motor_joint/example/arm.go b/physics/box2d_motor_joint/example/arm.go new file mode 100644 index 00000000..ddb2bebf --- /dev/null +++ b/physics/box2d_motor_joint/example/arm.go @@ -0,0 +1,55 @@ +components { + id: "trail" + component: "/particlefx/trail.particlefx" + position { + x: 90.0 + z: -0.1 + } +} +components { + id: "play" + component: "/particlefx/play.script" +} +embedded_components { + id: "sprite" + type: "sprite" + data: "default_animation: \"pixel_blue\"\n" + "material: \"/builtins/materials/sprite.material\"\n" + "size {\n" + " x: 200.0\n" + " y: 40.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: 3.0\n" + "friction: 0.4\n" + "restitution: 0.0\n" + "group: \"default\"\n" + "mask: \"default\"\n" + "embedded_collision_shape {\n" + " shapes {\n" + " shape_type: TYPE_BOX\n" + " position {\n" + " }\n" + " rotation {\n" + " }\n" + " index: 0\n" + " count: 3\n" + " }\n" + " data: 100.0\n" + " data: 20.0\n" + " data: 10.0\n" + "}\n" + "linear_damping: 0.05\n" + "angular_damping: 0.2\n" + "" +} diff --git a/physics/box2d_motor_joint/example/box2d_motor_joint.collection b/physics/box2d_motor_joint/example/box2d_motor_joint.collection new file mode 100644 index 00000000..aa87807c --- /dev/null +++ b/physics/box2d_motor_joint/example/box2d_motor_joint.collection @@ -0,0 +1,47 @@ +name: "box2d_motor_joint" +instances { + id: "pivot" + prototype: "/example/pivot.go" + position { + x: 360.0 + y: 360.0 + z: 0.5 + } +} +instances { + id: "arm" + prototype: "/example/arm.go" + position { + x: 480.0 + y: 360.0 + } +} +scale_along_z: 0 +embedded_instances { + id: "controller" + data: "components {\n" + " id: \"box2d_v2\"\n" + " component: \"/example/box2d_motor_joint_v2.script\"\n" + "}\n" + "components {\n" + " id: \"box2d_v3\"\n" + " component: \"/example/box2d_motor_joint_v3.script\"\n" + "}\n" + "embedded_components {\n" + " id: \"label\"\n" + " type: \"label\"\n" + " data: \"size {\\n" + " x: 640.0\\n" + " y: 96.0\\n" + "}\\n" + "text: \\\"Box2D motor joint\\\"\\n" + "font: \\\"/fonts/text28.font\\\"\\n" + "material: \\\"/builtins/fonts/label-df.material\\\"\\n" + "\"\n" + " position {\n" + " x: 360.0\n" + " y: 60.0\n" + " }\n" + "}\n" + "" +} diff --git a/physics/box2d_motor_joint/example/box2d_motor_joint_v2.script b/physics/box2d_motor_joint/example/box2d_motor_joint_v2.script new file mode 100644 index 00000000..8afb2bce --- /dev/null +++ b/physics/box2d_motor_joint/example/box2d_motor_joint_v2.script @@ -0,0 +1,100 @@ +local TOUCH = hash("touch") +local MOTOR_SPEED = 1.5 +local MAX_MOTOR_TORQUE = 50000 + +local function update_label(self) + local direction = self.direction > 0 and "counter-clockwise" or "clockwise" + label.set_text("#label", string.format("Box2D V2 motor joint\nMotor: %s\nClick or touch to reverse", direction)) -- <1> +end + +local function set_motor_speed(self) + b2d.joint.set_motor_speed(self.joint, self.direction * MOTOR_SPEED) -- <2> + update_label(self) +end + +local function reverse_motor(self) + self.direction = -self.direction -- <3> + set_motor_speed(self) +end + +function init(self) + self.direction = -1 + + local b2d_version = b2d.get_version() -- <4> + self.active = b2d_version.major == 2 -- <5> + + if not self.active then -- <6> + return + end + + msg.post(".", "acquire_input_focus") -- <7> + + local pivot_position = go.get_position("pivot") -- <8> + local arm_position = go.get_position("arm") + local pivot = b2d.get_body(msg.url(nil, "pivot", "collisionobject")) -- <9> + local arm = b2d.get_body(msg.url(nil, "arm", "collisionobject")) -- <10> + b2d.body.set_gravity_scale(arm, 0.0) -- <11> + + local arm_anchor = vmath.vector3( + pivot_position.x - arm_position.x, + pivot_position.y - arm_position.y, + pivot_position.z - arm_position.z + ) -- <12> + + self.joint = b2d.joint.create_revolute(pivot, arm, { -- <13> + local_anchor_a = vmath.vector3(), + local_anchor_b = arm_anchor, + enable_motor = true, + max_motor_torque = MAX_MOTOR_TORQUE, + motor_speed = self.direction * MOTOR_SPEED, + collide_connected = false, + }) + + update_label(self) +end + +------------------- +-- Input handling: + +function on_input(self, action_id, action) + if not self.active then -- <14> + return + end + + if action_id == TOUCH and action.pressed then -- <15> + reverse_motor(self) + end +end + +function final(self) + if not self.active then + return + end + + if self.joint then + b2d.joint.destroy(self.joint) -- <16> + self.joint = nil + end + + msg.post(".", "release_input_focus") -- <17> +end + +--[[ +1. Updates the label with the active backend and the current motor direction. +2. Sets the motor speed on the revolute joint through the Box2D joint API. +3. Reverses the stored motor direction before applying the new speed. +4. Reads the active Box2D backend version. +5. Enables this script only when the project is running the Box2D V2 backend. +6. Stops the script early when Box2D V2 is not active. +7. Acquires input focus so this script can receive click or touch input. +8. Reads the editor-placed pivot and arm positions used to calculate the local joint anchor. +9. Gets the Box2D body from the static `pivot` collision object. +10. Gets the Box2D body from the dynamic `arm` collision object. +11. Disables gravity on the arm body so the example focuses on the joint motor. +12. Converts the pivot world position into the arm's local space using the editor positions. This keeps the arm rotating around the visible pivot. +13. Creates a revolute joint with its motor enabled. The revolute joint provides the pivot, while the motor drives the rotation. +14. Skips input handling if this script is inactive. +15. Handles a click or touch press and uses it to reverse the motor direction. +16. Destroys the runtime-created joint during cleanup. +17. Releases input focus when the script or collection is unloaded. +]] diff --git a/physics/box2d_motor_joint/example/box2d_motor_joint_v3.script b/physics/box2d_motor_joint/example/box2d_motor_joint_v3.script new file mode 100644 index 00000000..f7c5a893 --- /dev/null +++ b/physics/box2d_motor_joint/example/box2d_motor_joint_v3.script @@ -0,0 +1,102 @@ +local TOUCH = hash("touch") +local MOTOR_SPEED = 1.5 +local MAX_MOTOR_TORQUE = 50000 + +local function update_label(self) + local direction = self.direction > 0 and "counter-clockwise" or "clockwise" + label.set_text("#label", string.format("Box2D V3 motor joint\nMotor: %s\nClick or touch to reverse", direction)) -- <1> +end + +local function set_motor_speed(self) + b2d.joint.set_motor_speed(self.joint, self.direction * MOTOR_SPEED) -- <2> + update_label(self) +end + +local function reverse_motor(self) + self.direction = -self.direction -- <3> + set_motor_speed(self) +end + +function init(self) + self.direction = -1 + + local b2d_version = b2d.get_version() -- <4> + self.active = b2d_version.major == 3 -- <5> + + if not self.active then -- <6> + return + end + + msg.post(".", "acquire_input_focus") -- <7> + + local world = b2d.get_world() -- <8> + b2d.world.set_gravity(world, vmath.vector3()) -- <9> + b2d.world.set_joint_tuning(world, 60, 1.0) -- <10> + + local pivot_position = go.get_position("pivot") -- <11> + local pivot = b2d.get_body(msg.url(nil, "pivot", "collisionobject")) -- <12> + local arm = b2d.get_body(msg.url(nil, "arm", "collisionobject")) -- <13> + b2d.body.set_gravity_scale(arm, 0.0) -- <14> + + local arm_anchor = b2d.body.get_local_point(arm, pivot_position) -- <15> + + self.joint = b2d.joint.create_revolute(pivot, arm, { -- <16> + local_anchor_a = vmath.vector3(), + local_anchor_b = arm_anchor, + enable_motor = true, + max_motor_torque = MAX_MOTOR_TORQUE, + motor_speed = self.direction * MOTOR_SPEED, + collide_connected = false, + }) + + update_label(self) +end + +------------------- +-- Input handling: + +function on_input(self, action_id, action) + if not self.active then -- <17> + return + end + + if action_id == TOUCH and action.pressed then -- <18> + reverse_motor(self) + end +end + +function final(self) + if not self.active then + return + end + + if self.joint then + b2d.joint.destroy(self.joint) -- <19> + self.joint = nil + end + + msg.post(".", "release_input_focus") -- <20> +end + +--[[ +1. Updates the label with the active backend and the current motor direction. +2. Sets the motor speed on the revolute joint through the Box2D joint API. +3. Reverses the stored motor direction before applying the new speed. +4. Reads the active Box2D backend version. +5. Enables this script only when the project is running the Box2D V3 backend. +6. Stops the script early when Box2D V3 is not active. +7. Acquires input focus so this script can receive click or touch input. +8. Gets the current Box2D world handle. +9. Clears world gravity so the arm stays in the editor-placed setup. +10. Tunes the Box2D V3 joint solver used by the motorized joint. +11. Reads the editor-placed pivot position, which is the world point the arm should rotate around. +12. Gets the Box2D body from the static `pivot` collision object. +13. Gets the Box2D body from the dynamic `arm` collision object. +14. Disables gravity on the arm body so the example focuses on the joint motor. +15. Converts the pivot world position into the arm's local space using the V3 body helper. This keeps the arm rotating around the visible pivot. +16. Creates a revolute joint with its motor enabled. The revolute joint provides the pivot, while the motor drives the rotation. +17. Skips input handling if this script is inactive. +18. Handles a click or touch press and uses it to reverse the motor direction. +19. Destroys the runtime-created joint during cleanup. +20. Releases input focus when the script or collection is unloaded. +]] diff --git a/physics/box2d_motor_joint/example/pivot.go b/physics/box2d_motor_joint/example/pivot.go new file mode 100644 index 00000000..97c2c7d7 --- /dev/null +++ b/physics/box2d_motor_joint/example/pivot.go @@ -0,0 +1,36 @@ +embedded_components { + id: "sprite" + type: "sprite" + data: "default_animation: \"ball\"\n" + "material: \"/builtins/materials/sprite.material\"\n" + "textures {\n" + " sampler: \"texture_sampler\"\n" + " texture: \"/textures/textures.atlas\"\n" + "}\n" + "" +} +embedded_components { + id: "collisionobject" + type: "collisionobject" + data: "type: COLLISION_OBJECT_TYPE_STATIC\n" + "mass: 0.0\n" + "friction: 0.4\n" + "restitution: 0.0\n" + "group: \"default\"\n" + "mask: \"default\"\n" + "embedded_collision_shape {\n" + " shapes {\n" + " shape_type: TYPE_BOX\n" + " position {\n" + " }\n" + " rotation {\n" + " }\n" + " index: 0\n" + " count: 3\n" + " }\n" + " data: 9.0\n" + " data: 9.0\n" + " data: 10.0\n" + "}\n" + "" +} diff --git a/physics/box2d_motor_joint/example/target.go b/physics/box2d_motor_joint/example/target.go new file mode 100644 index 00000000..97c2c7d7 --- /dev/null +++ b/physics/box2d_motor_joint/example/target.go @@ -0,0 +1,36 @@ +embedded_components { + id: "sprite" + type: "sprite" + data: "default_animation: \"ball\"\n" + "material: \"/builtins/materials/sprite.material\"\n" + "textures {\n" + " sampler: \"texture_sampler\"\n" + " texture: \"/textures/textures.atlas\"\n" + "}\n" + "" +} +embedded_components { + id: "collisionobject" + type: "collisionobject" + data: "type: COLLISION_OBJECT_TYPE_STATIC\n" + "mass: 0.0\n" + "friction: 0.4\n" + "restitution: 0.0\n" + "group: \"default\"\n" + "mask: \"default\"\n" + "embedded_collision_shape {\n" + " shapes {\n" + " shape_type: TYPE_BOX\n" + " position {\n" + " }\n" + " rotation {\n" + " }\n" + " index: 0\n" + " count: 3\n" + " }\n" + " data: 9.0\n" + " data: 9.0\n" + " data: 10.0\n" + "}\n" + "" +} diff --git a/physics/box2d_motor_joint/fonts/SourceSansPro-Semibold.ttf b/physics/box2d_motor_joint/fonts/SourceSansPro-Semibold.ttf new file mode 100644 index 00000000..50205948 Binary files /dev/null and b/physics/box2d_motor_joint/fonts/SourceSansPro-Semibold.ttf differ diff --git a/physics/box2d_motor_joint/fonts/text28.font b/physics/box2d_motor_joint/fonts/text28.font new file mode 100644 index 00000000..3d9c4a8e --- /dev/null +++ b/physics/box2d_motor_joint/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_motor_joint/game.project b/physics/box2d_motor_joint/game.project new file mode 100644 index 00000000..d1cb4e75 --- /dev/null +++ b/physics/box2d_motor_joint/game.project @@ -0,0 +1,36 @@ +[bootstrap] +main_collection = /example/box2d_motor_joint.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 Motor Joint + +[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_motor_joint/particlefx/play.script b/physics/box2d_motor_joint/particlefx/play.script new file mode 100644 index 00000000..94f0e318 --- /dev/null +++ b/physics/box2d_motor_joint/particlefx/play.script @@ -0,0 +1,3 @@ +function init(self) + particlefx.play("#trail") +end \ No newline at end of file diff --git a/physics/box2d_motor_joint/particlefx/trail.particlefx b/physics/box2d_motor_joint/particlefx/trail.particlefx new file mode 100644 index 00000000..261de752 --- /dev/null +++ b/physics/box2d_motor_joint/particlefx/trail.particlefx @@ -0,0 +1,143 @@ +emitters { + mode: PLAY_MODE_LOOP + duration: 0.1 + space: EMISSION_SPACE_WORLD + tile_source: "/builtins/graphics/particle_blob.tilesource" + animation: "anim" + material: "/builtins/materials/particlefx.material" + blend_mode: BLEND_MODE_ADD + max_particle_count: 128 + type: EMITTER_TYPE_CIRCLE + properties { + key: EMITTER_KEY_SPAWN_RATE + points { + y: 60.0 + } + } + properties { + key: EMITTER_KEY_SIZE_X + points { + y: 1.0 + } + } + properties { + key: EMITTER_KEY_SIZE_Y + points { + y: 1.0 + } + } + properties { + key: EMITTER_KEY_PARTICLE_LIFE_TIME + points { + y: 2.0 + } + } + properties { + key: EMITTER_KEY_PARTICLE_SIZE + points { + y: 40.0 + } + } + properties { + key: EMITTER_KEY_PARTICLE_RED + points { + y: 0.6 + } + } + properties { + key: EMITTER_KEY_PARTICLE_GREEN + points { + y: 0.8 + } + } + properties { + key: EMITTER_KEY_PARTICLE_BLUE + points { + y: 1.0 + } + } + properties { + key: EMITTER_KEY_PARTICLE_ALPHA + points { + y: 1.0 + } + } + particle_properties { + key: PARTICLE_KEY_SCALE + points { + y: 1.0 + } + } + particle_properties { + key: PARTICLE_KEY_RED + points { + y: 0.021477 + } + points { + x: 0.631762 + y: 0.896974 + t_x: 0.999824 + t_y: -0.018744 + } + points { + x: 1.0 + y: 0.008932 + } + } + particle_properties { + key: PARTICLE_KEY_GREEN + points { + y: 1.0 + } + points { + x: 1.0 + y: 0.025659 + t_x: 0.22075762 + t_y: -0.9753287 + } + } + particle_properties { + key: PARTICLE_KEY_BLUE + points { + y: 1.0 + } + points { + x: 1.0 + y: 0.042386 + t_x: 0.21580979 + t_y: -0.9764354 + } + } + particle_properties { + key: PARTICLE_KEY_ALPHA + points { + y: 0.016727 + t_x: 0.07194582 + t_y: 0.99740857 + } + points { + x: 0.082687 + y: 1.009501 + t_x: 0.99418455 + t_y: 0.10768964 + } + points { + x: 0.688178 + y: 0.380024 + t_x: 0.2855196 + t_y: -0.9583729 + } + points { + x: 1.0 + y: -0.00532 + t_x: 0.94833106 + t_y: -0.3172825 + } + } + particle_properties { + key: PARTICLE_KEY_ANGULAR_VELOCITY + points { + y: 1.0 + } + } +} diff --git a/physics/box2d_motor_joint/setup.png b/physics/box2d_motor_joint/setup.png new file mode 100644 index 00000000..15d95243 Binary files /dev/null and b/physics/box2d_motor_joint/setup.png differ diff --git a/physics/box2d_motor_joint/textures/ball.png b/physics/box2d_motor_joint/textures/ball.png new file mode 100644 index 00000000..01976c24 Binary files /dev/null and b/physics/box2d_motor_joint/textures/ball.png differ diff --git a/physics/box2d_motor_joint/textures/pixel_blue.png b/physics/box2d_motor_joint/textures/pixel_blue.png new file mode 100644 index 00000000..2db50d55 Binary files /dev/null and b/physics/box2d_motor_joint/textures/pixel_blue.png differ diff --git a/physics/box2d_motor_joint/textures/pixel_orange.png b/physics/box2d_motor_joint/textures/pixel_orange.png new file mode 100644 index 00000000..9fb97e44 Binary files /dev/null and b/physics/box2d_motor_joint/textures/pixel_orange.png differ diff --git a/physics/box2d_motor_joint/textures/pixel_white.png b/physics/box2d_motor_joint/textures/pixel_white.png new file mode 100644 index 00000000..0e34154f Binary files /dev/null and b/physics/box2d_motor_joint/textures/pixel_white.png differ diff --git a/physics/box2d_motor_joint/textures/textures.atlas b/physics/box2d_motor_joint/textures/textures.atlas new file mode 100644 index 00000000..f9373bd0 --- /dev/null +++ b/physics/box2d_motor_joint/textures/textures.atlas @@ -0,0 +1,13 @@ +images { + image: "/textures/pixel_white.png" +} +images { + image: "/textures/pixel_blue.png" +} +images { + image: "/textures/pixel_orange.png" +} +images { + image: "/textures/ball.png" +} +extrude_borders: 2 diff --git a/physics/box2d_motor_joint/thumbnail.webp b/physics/box2d_motor_joint/thumbnail.webp new file mode 100644 index 00000000..a0c2d40b Binary files /dev/null and b/physics/box2d_motor_joint/thumbnail.webp differ