diff --git a/physics/box2d_sensor_toggle/all.texture_profiles b/physics/box2d_sensor_toggle/all.texture_profiles new file mode 100644 index 00000000..5b0d7762 --- /dev/null +++ b/physics/box2d_sensor_toggle/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_sensor_toggle/box2d_v2.appmanifest b/physics/box2d_sensor_toggle/box2d_v2.appmanifest new file mode 100644 index 00000000..b3abe8c8 --- /dev/null +++ b/physics/box2d_sensor_toggle/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_sensor_toggle/box2d_v3.appmanifest b/physics/box2d_sensor_toggle/box2d_v3.appmanifest new file mode 100644 index 00000000..9751deca --- /dev/null +++ b/physics/box2d_sensor_toggle/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_sensor_toggle/example.md b/physics/box2d_sensor_toggle/example.md new file mode 100644 index 00000000..e0e204f2 --- /dev/null +++ b/physics/box2d_sensor_toggle/example.md @@ -0,0 +1,74 @@ +--- +tags: physics, box2d +title: Box2D Sensors +brief: Create Box2D sensors from static collision shapes. +author: Defold Foundation +scripts: sensor_box2d_v3.script, sensor_box2d_v2.script, spawn.script +thumbnail: thumbnail.webp +--- + +This example shows how to utilize the Box2D scripting API to operate with sensors (triggers). +It spawns dynamic physics balls from slightly different random positions near the top of the scene, +and gravity pulls each ball down, and these pass through two collision objects. + +## What You'll Learn + +- How to get a Box2D body from a collision object with `b2d.get_body()`. +- How to turn a Box2D V2 fixture into a sensor with `b2d.fixture.set_sensor()`. +- How to recreate a Box2D V3 shape as a sensor with `b2d.body.create_shape()`. +- How to count V2 sensor overlaps from `trigger_response` enter/exit messages. +- How to poll V3 sensor overlaps with `b2d.shape.get_sensor_overlaps()`. + +## Setup + +The collection contains one `controller` game object with `spawn.script` and a `ball_factory`. +The factory creates `ball.go` - a small prototype with one sprite and one dynamic circle collision object. + +The two sensor game objects both contain: + +- `sensor_box2d_v3.script` - for Box2D V3 example handling +- `sensor_box2d_v2.script` - for Box2D V2 example handling +- A sprite, label, and static collision object with component id `collisionobject`. + +The collision objects are of type `Static` in the editor. + +All sensors use the `sensor` collision group and mask the `ball` group. +The spawned ball belongs to the `ball` collision group and masks the `sensor` group, +so the sensor overlaps only include spawned balls. + +![setup](setup.png) + +The `game.project` currently uses `/box2d_v3.appmanifest`. +To test V2 locally, change `Native Extensions -> App Manifest` to `/box2d_v2.appmanifest`. +Gravity set in `game.project` causes the falling motion. + +## How It Works + +The controller spawns a ball repeateadly with `factory.create()`. +Each ball is spawned at a random X position near the center, and is deleted after a short delay. +The spawned balls pass through the sensor's collision object shapes. + +Each sensor has two backend scripts (V2 and V3), but only one runs processing depending on a choosen Box2D version. +Each script checks `b2d.get_version().major` in `init()` and returns immediately when the active backend does not match. + +At startup, the active Box2D script changes the static collision geometry into a sensor (trigger) through the `b2d` API. +Box2D V2 and V3 expose this through different scripting APIs: + +- V2 uses fixtures and Defold trigger messages. +- V3 uses shapes and can poll a sensor shape's current overlaps directly. + +In Box2D V2, `sensor_box2d_v2.script` gets the body with `b2d.get_body("#collisionobject")`, +reads the first fixture with `b2d.body.get_fixtures()`, and calls `b2d.fixture.set_sensor()`, +so the fixture no longer blocks the balls. V2 fixture sensors do not expose a `get_sensor_overlaps()` polling API. +But Defold still sends `trigger_response` messages when another collision object enters or exits the sensor, +and the script maintains a Lua table of current overlapping ball ids. + +In Box2D V3, `sensor_box2d_v3.script` uses the shape API. +It reads the first editor-authored shape with `b2d.body.get_shapes()` and `b2d.shape.get_shape()`, +destroys that solid shape, and creates a replacement with `b2d.body.create_shape()` using the same geometry and `sensor = true`. +The V3 script then calls `b2d.shape.enable_sensor_events()` for the new sensor shape. +In `update()`, it polls the current overlaps with `b2d.shape.get_sensor_overlaps()`. +This returns shape info tables for the shapes currently overlapping the sensor. + +Both scripts gives us the same result: each sensor sprite scales up while at least one ball overlaps it, +and the label shows the current overlap count reported by the active backend path. diff --git a/physics/box2d_sensor_toggle/example/ball.go b/physics/box2d_sensor_toggle/example/ball.go new file mode 100644 index 00000000..593e8dcb --- /dev/null +++ b/physics/box2d_sensor_toggle/example/ball.go @@ -0,0 +1,42 @@ +embedded_components { + id: "sprite" + type: "sprite" + data: "default_animation: \"ball\"\n" + "material: \"/builtins/materials/sprite.material\"\n" + "size {\n" + " x: 254.0\n" + " y: 254.0\n" + "}\n" + "textures {\n" + " sampler: \"texture_sampler\"\n" + " texture: \"/textures/textures.atlas\"\n" + "}\n" + "" + scale { + x: 0.5 + y: 0.5 + } +} +embedded_components { + id: "collisionobject" + type: "collisionobject" + data: "type: COLLISION_OBJECT_TYPE_DYNAMIC\n" + "mass: 1.0\n" + "friction: 0.2\n" + "restitution: 0.0\n" + "group: \"ball\"\n" + "mask: \"sensor\"\n" + "embedded_collision_shape {\n" + " shapes {\n" + " shape_type: TYPE_SPHERE\n" + " position {\n" + " }\n" + " rotation {\n" + " }\n" + " index: 0\n" + " count: 1\n" + " }\n" + " data: 32.0\n" + "}\n" + "" +} diff --git a/physics/box2d_sensor_toggle/example/box2d_sensor_toggle.collection b/physics/box2d_sensor_toggle/example/box2d_sensor_toggle.collection new file mode 100644 index 00000000..0381eb2d --- /dev/null +++ b/physics/box2d_sensor_toggle/example/box2d_sensor_toggle.collection @@ -0,0 +1,166 @@ +name: "box2d_sensor_toggle" +scale_along_z: 0 +embedded_instances { + id: "controller" + data: "components {\n" + " id: \"script\"\n" + " component: \"/example/spawn.script\"\n" + "}\n" + "embedded_components {\n" + " id: \"ball_factory\"\n" + " type: \"factory\"\n" + " data: \"prototype: \\\"/example/ball.go\\\"\\n" + "\"\n" + "}\n" + "" + position { + x: 360.0 + y: 100.0 + } +} +embedded_instances { + id: "left_sensor" + data: "components {\n" + " id: \"sensor_box2d_v3\"\n" + " component: \"/example/sensor_box2d_v3.script\"\n" + "}\n" + "components {\n" + " id: \"sensor_box2d_v2\"\n" + " component: \"/example/sensor_box2d_v2.script\"\n" + "}\n" + "embedded_components {\n" + " id: \"sprite\"\n" + " type: \"sprite\"\n" + " data: \"default_animation: \\\"pixel_orange\\\"\\n" + "material: \\\"/builtins/materials/sprite.material\\\"\\n" + "size {\\n" + " x: 300.0\\n" + " y: 150.0\\n" + "}\\n" + "size_mode: SIZE_MODE_MANUAL\\n" + "textures {\\n" + " sampler: \\\"texture_sampler\\\"\\n" + " texture: \\\"/textures/textures.atlas\\\"\\n" + "}\\n" + "\"\n" + "}\n" + "embedded_components {\n" + " id: \"label\"\n" + " type: \"label\"\n" + " data: \"size {\\n" + " x: 220.0\\n" + " y: 50.0\\n" + "}\\n" + "text: \\\"Overlaps: 0\\\"\\n" + "font: \\\"/fonts/text28.font\\\"\\n" + "material: \\\"/builtins/fonts/label-df.material\\\"\\n" + "\"\n" + " position {\n" + " y: -100.0\n" + " }\n" + "}\n" + "embedded_components {\n" + " id: \"collisionobject\"\n" + " type: \"collisionobject\"\n" + " data: \"type: COLLISION_OBJECT_TYPE_STATIC\\n" + "mass: 0.0\\n" + "friction: 0.0\\n" + "restitution: 0.0\\n" + "group: \\\"sensor\\\"\\n" + "mask: \\\"ball\\\"\\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: \\\"sensor\\\"\\n" + " }\\n" + " data: 150.0\\n" + " data: 75.0\\n" + " data: 10.0\\n" + "}\\n" + "\"\n" + "}\n" + "" + position { + x: 200.0 + y: 300.0 + } +} +embedded_instances { + id: "right_sensor" + data: "components {\n" + " id: \"sensor_box2d_v3\"\n" + " component: \"/example/sensor_box2d_v3.script\"\n" + "}\n" + "components {\n" + " id: \"sensor_box2d_v2\"\n" + " component: \"/example/sensor_box2d_v2.script\"\n" + "}\n" + "embedded_components {\n" + " id: \"sprite\"\n" + " type: \"sprite\"\n" + " data: \"default_animation: \\\"pixel_blue\\\"\\n" + "material: \\\"/builtins/materials/sprite.material\\\"\\n" + "size {\\n" + " x: 300.0\\n" + " y: 150.0\\n" + "}\\n" + "size_mode: SIZE_MODE_MANUAL\\n" + "textures {\\n" + " sampler: \\\"texture_sampler\\\"\\n" + " texture: \\\"/textures/textures.atlas\\\"\\n" + "}\\n" + "\"\n" + "}\n" + "embedded_components {\n" + " id: \"label\"\n" + " type: \"label\"\n" + " data: \"size {\\n" + " x: 220.0\\n" + " y: 50.0\\n" + "}\\n" + "text: \\\"Overlaps: 0\\\"\\n" + "font: \\\"/fonts/text28.font\\\"\\n" + "material: \\\"/builtins/fonts/label-df.material\\\"\\n" + "\"\n" + " position {\n" + " y: -100.0\n" + " }\n" + "}\n" + "embedded_components {\n" + " id: \"collisionobject\"\n" + " type: \"collisionobject\"\n" + " data: \"type: COLLISION_OBJECT_TYPE_STATIC\\n" + "mass: 0.0\\n" + "friction: 0.0\\n" + "restitution: 0.0\\n" + "group: \\\"sensor\\\"\\n" + "mask: \\\"ball\\\"\\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: \\\"sensor\\\"\\n" + " }\\n" + " data: 150.0\\n" + " data: 75.0\\n" + " data: 10.0\\n" + "}\\n" + "\"\n" + "}\n" + "" + position { + x: 530.0 + y: 300.0 + } +} diff --git a/physics/box2d_sensor_toggle/example/sensor_box2d_v2.script b/physics/box2d_sensor_toggle/example/sensor_box2d_v2.script new file mode 100644 index 00000000..b26e53a8 --- /dev/null +++ b/physics/box2d_sensor_toggle/example/sensor_box2d_v2.script @@ -0,0 +1,62 @@ +-- Helper function to convert a collision object to a sensor (trigger) for scripting +local function enable_sensor_fixture() + -- `b2d.get_body()` returns the native Box2D body created by this collision object. + local body = b2d.get_body("#collisionobject") + + -- In Box2D V2, collision geometry and material data live in fixtures. + -- The collection-authored fixture starts solid, so the ball would collide with it. + local fixture = b2d.body.get_fixtures(body)[1] + + -- Turning the fixture into a sensor disables physical collision response. + -- Box2D still reports trigger-style enter/exit interactions for overlaps. + b2d.fixture.set_sensor(body, fixture.index, true) +end + +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 + + enable_sensor_fixture() + self.overlaps = {} +end + +local NORMAL_SCALE = vmath.vector3(1.0) +local LARGER_SCALE = vmath.vector3(1.1) + +function on_message(self, message_id, message, sender) + -- If Box2D V2 is not used, skip further processing + if not self.active then + return + end + + -- Defold sends `trigger_response` when a sensor fixture starts or stops + -- overlapping another collision object allowed by the collision mask. + if message_id == hash("trigger_response") then + + -- Store overlaps in a table or clear those that exited the sensor + if message.enter then + self.overlaps[message.other_id] = true + else + self.overlaps[message.other_id] = nil + end + + -- Count overlaps + local count = 0 + for i,v in pairs(self.overlaps) do count = count + 1 end + + -- Set the sprite scale to indicate the overlapping visually + if count > 0 then + go.set("#sprite", "scale", LARGER_SCALE) + else + go.set("#sprite", "scale", NORMAL_SCALE) + end + + -- Update the label text to show the amount of overlaps + label.set_text("#label", "Overlaps: " .. count) + end +end diff --git a/physics/box2d_sensor_toggle/example/sensor_box2d_v3.script b/physics/box2d_sensor_toggle/example/sensor_box2d_v3.script new file mode 100644 index 00000000..3f3df039 --- /dev/null +++ b/physics/box2d_sensor_toggle/example/sensor_box2d_v3.script @@ -0,0 +1,64 @@ +-- Helper function to create a sensor from the collision object for scripting +local function create_sensor_shape() + -- `b2d.get_body()` returns the native Box2D body created by this collision object. + local body = b2d.get_body("#collisionobject") + + -- In Box2D V3, collision geometry is attached to a body as shapes. + -- Read the first editor-authored shape so the runtime sensor keeps the same size. + local shape = b2d.body.get_shapes(body)[1] + local shape_definition = b2d.shape.get_shape(body, shape.index) + + -- The editor-authored shape is solid, so it would block the falling ball. + -- Remove it before creating the replacement sensor shape. + b2d.body.destroy_shape(body, shape.index) + + -- A sensor shape reports overlaps without producing collision response. + -- The ball can pass through it, but Box2D still tracks which shapes overlap it. + local sensor = b2d.body.create_shape(body, { + shape = shape_definition, + friction = 0.0, + restitution = 0.0, + sensor = true, + }) + + -- V3 sensor overlap polling is opt-in. Without this call, + -- `get_sensor_overlaps()` would not return the current overlap list. + b2d.shape.enable_sensor_events(sensor.shape_id, true) + return sensor.shape_id +end + +function init(self) + -- This script uses the Box2D V3 shape API. + self.active = b2d.get_version().major == 3 + + -- If Box2D V3 is not used, skip further processing + if not self.active then + return + end + + self.sensor_shape = create_sensor_shape() + self.overlaps = {} +end + +local NORMAL_SCALE = vmath.vector3(1.0) +local LARGER_SCALE = vmath.vector3(1.1) + +function update(self, dt) + -- If Box2D V3 is not used, skip further processing + if not self.active then + return + end + + -- V3 returns the shapes currently overlapping this sensor shape. + self.overlaps = b2d.shape.get_sensor_overlaps(self.sensor_shape) + + -- Set the sprite scale to indicate the overlapping visually + if #self.overlaps > 0 then + go.set("#sprite", "scale", LARGER_SCALE) + else + go.set("#sprite", "scale", NORMAL_SCALE) + end + + -- Update the label text to show the amount of overlaps + label.set_text("#label", "Overlaps: " .. #self.overlaps) +end diff --git a/physics/box2d_sensor_toggle/example/spawn.script b/physics/box2d_sensor_toggle/example/spawn.script new file mode 100644 index 00000000..f14d814f --- /dev/null +++ b/physics/box2d_sensor_toggle/example/spawn.script @@ -0,0 +1,22 @@ +-- Helper function to spawn a ball at random position on top and remove it after a moment +local function spawn_ball() + -- X position is random between 200-600 + local x = 400 + math.random(-200, 200) + + -- Spawn the ball from the ball_factory, assign the random position + -- and store the created instance's id + local id = factory.create("#ball_factory", vmath.vector3(x, 600, 0.0)) + + -- After a moment remove the spawned ball + timer.delay(1.2, false, function() + go.delete(id) + end) +end + +function init(self) + -- Initialize random number generator + math.randomseed(os.time()) + + -- Use the above helper function to spawn the ball every 0.5 second + timer.delay(0.2, true, spawn_ball) +end diff --git a/physics/box2d_sensor_toggle/fonts/SourceSansPro-Semibold.ttf b/physics/box2d_sensor_toggle/fonts/SourceSansPro-Semibold.ttf new file mode 100644 index 00000000..50205948 Binary files /dev/null and b/physics/box2d_sensor_toggle/fonts/SourceSansPro-Semibold.ttf differ diff --git a/physics/box2d_sensor_toggle/fonts/text28.font b/physics/box2d_sensor_toggle/fonts/text28.font new file mode 100644 index 00000000..3d9c4a8e --- /dev/null +++ b/physics/box2d_sensor_toggle/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_sensor_toggle/game.project b/physics/box2d_sensor_toggle/game.project new file mode 100644 index 00000000..ec2a2909 --- /dev/null +++ b/physics/box2d_sensor_toggle/game.project @@ -0,0 +1,36 @@ +[bootstrap] +main_collection = /example/box2d_sensor_toggle.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 Sensors + +[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_sensor_toggle/setup.png b/physics/box2d_sensor_toggle/setup.png new file mode 100644 index 00000000..b05cd426 Binary files /dev/null and b/physics/box2d_sensor_toggle/setup.png differ diff --git a/physics/box2d_sensor_toggle/textures/ball.png b/physics/box2d_sensor_toggle/textures/ball.png new file mode 100644 index 00000000..01976c24 Binary files /dev/null and b/physics/box2d_sensor_toggle/textures/ball.png differ diff --git a/physics/box2d_sensor_toggle/textures/pixel_blue.png b/physics/box2d_sensor_toggle/textures/pixel_blue.png new file mode 100644 index 00000000..5e924542 Binary files /dev/null and b/physics/box2d_sensor_toggle/textures/pixel_blue.png differ diff --git a/physics/box2d_sensor_toggle/textures/pixel_orange.png b/physics/box2d_sensor_toggle/textures/pixel_orange.png new file mode 100644 index 00000000..32747cae Binary files /dev/null and b/physics/box2d_sensor_toggle/textures/pixel_orange.png differ diff --git a/physics/box2d_sensor_toggle/textures/textures.atlas b/physics/box2d_sensor_toggle/textures/textures.atlas new file mode 100644 index 00000000..a3d24cc4 --- /dev/null +++ b/physics/box2d_sensor_toggle/textures/textures.atlas @@ -0,0 +1,10 @@ +images { + image: "/textures/ball.png" +} +images { + image: "/textures/pixel_blue.png" +} +images { + image: "/textures/pixel_orange.png" +} +extrude_borders: 2 diff --git a/physics/box2d_sensor_toggle/thumbnail.webp b/physics/box2d_sensor_toggle/thumbnail.webp new file mode 100644 index 00000000..f51f8e8f Binary files /dev/null and b/physics/box2d_sensor_toggle/thumbnail.webp differ