Skip to content

Blender Combat Demo

App: apps/combat_blender_demo/

Demonstrates Blender-authored combat (engine PLM-198 / ADR 0069) end to end: CombatVolumes.blend carries a Fighter armature with a sword hitbox and a body hurtbox authored in Blender — bone-parented meshes placed in the Plume_Hitboxes / Plume_Hurtboxes collections (Passive + Animated rigid bodies). No hitbox geometry lives in code.

The demo instantiates the Fighter twice, tells the engine who owns which boxes (owner is game-side), and lunges one into the other. The engine turns each Blender volume into a bone-attached Jolt sensor, Jolt reports the overlap, and Combat.onHit fires. Health is the game’s — here the demo just tallies strikes.

Terminal window
% ./plume3d combat_blender_demo

The attacker closes in and lands strikes; a GUI overlay shows the running hit count.

  • On init, loads CombatVolumes.blend and instantiates the Fighter twice (attacker + target).
  • Reads each character’s Blender-authored volumes off the tag maps — character.hitboxes and character.hurtboxes — and sets owner on every box (a hitbox never strikes its own owner). This is the whole “who is whose enemy” wiring; the shapes and bone attachment came from Blender.
  • Registers Combat.onHit(scene) { |hit| … } and tallies each strike. What a hit costs would be the game’s business — there is no HP type in the engine.
  • In update, lunges the attacker along +X until the authored sword volume overlaps the target’s body volume, at which point the sensor fires onHit.
import "engine" for Scene, Resource, Combat
var scene = Scene.new()
var res = Resource.loadBlend("CombatVolumes.blend")
var a = res.instantiate("Fighter", scene) // attacker — carries Blender-authored volumes
var b = res.instantiate("Fighter", scene) // target
// The GAME assigns identity; geometry + bone attachment came from Blender.
for (hb in a.hitboxes.values) { hb.owner = 1 }
for (hu in a.hurtboxes.values) { hu.owner = 1 }
for (hb in b.hitboxes.values) { hb.owner = 2 }
for (hu in b.hurtboxes.values) { hu.owner = 2 }
Combat.onHit(scene) { |hit|
// engine detected the overlap; the game owns the consequence (damage/HP/death live here)
}

The Plume3D Blender add-on ships a Combat Volumes panel: select the mesh, click Mark Hitbox / Mark Hurtbox, and it sets a Passive + Animated rigid body and moves the object into Plume_Hitboxes / Plume_Hurtboxes. The object name becomes the tag (swordhitboxes["sword"]). Bone-parent the mesh to the bone it should ride. That’s the whole authoring contract — see Combat → Authoring volumes in Blender.

Terminal window
% ./plume3d --test apps/combat_blender_demo

Asserts the Blender-authored volumes surface on the instantiated character: hitboxes has the sword key, hurtboxes has the body key, and setting owner on them does not crash. The hit mechanics (sensor overlap, dedup, lifecycle) are covered by tests/unit/test_combat_hitbox.cpp and test_combat_wren.cpp.