ludic/examples/library/tiled_p4.ludic
Orkuncakilkaya bf36bc8a8f refactor(runtime,packages,examples): named constants, package enums, idiom sweep
- runtime: HEADLESS_FRAME_PATH, STICK_DEADZONE / STICK_LEFT_X/Y, key and
  byte codes as char literals throughout (`k == 'w'`, `fill(rt_map, ' ', …)`)
- ludic.gameplay/stats: drop the duplicate `stat_field` (it answered "atk"
  for every build stat); Stats.base uses stats_field_name
- ludic.shooter: compare aim modes and fire patterns with AimMode.* and
  WeaponPattern.* instead of raw ints; STICK_RIGHT_X/Y
- ludic.npcai: DecisionMade / brain_set_state use AiState.*
- examples/games/menu.ludic uses Font.load / Ui.* with FONT_PATH and
  BACKDROP named; strings.ludic header says what it prints
- whole tree: `x = x + 1` → `x += 1` (single-term right-hand sides only),
  `0 - x` → `-x`, ASCII codes → char literals; every .ludic and every
  ```ludic fence reformatted with the fixed formatter (whitespace only)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-05 01:12:26 +03:00

78 lines
3.5 KiB
Text

# tiled_p4.ludic — Tiled P4 objects, custom properties/types, templates, opt-in
# spawning (issue #72). All object shapes (rect/ellipse/point/polygon/polyline/
# text) parse and are queryable; class properties resolve their defaults against
# the project custom-type table (objecttypes.xml); a template instance inherits
# its template's fields; and an object maps onto Ludic components on demand.
#
# A full run prints: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
program TiledP4 {
property Position { x: int = 0, y: int = 0 }
property Health { hp: int = 0 }
model Enemy { Position, Health }
handler Boot phase Start {
let m = Tiled.load("assets/tiled-fixtures/p4_map.tmx")
Tiled.load_types("assets/tiled-fixtures/p4_types.xml")
# --- all object shapes parse and are queryable (layer 0 "shapes") ---
if Tiled.object_count(m, 0) == 6 { print(1) }
if Tiled.object_shape(Tiled.object(m, 0, 0)) == "rectangle" { print(2) }
if Tiled.object_shape(Tiled.object(m, 0, 1)) == "ellipse" { print(3) }
if Tiled.object_shape(Tiled.object(m, 0, 2)) == "point" { print(4) }
if Tiled.object_shape(Tiled.object(m, 0, 3)) == "polygon" { print(5) }
if Tiled.object_shape(Tiled.object(m, 0, 4)) == "polyline" { print(6) }
if Tiled.object_shape(Tiled.object(m, 0, 5)) == "text" { print(7) }
# polygon points + text content, via the value tree
let poly = Tiled.object(m, 0, 3)
if Value.count(Value.get(poly, "polygon")) == 4 { print(8) }
let txt = Tiled.object(m, 0, 5)
if Value.as_str(Value.get(Value.get(txt, "text"), "text")) == "Hello" { print(9) }
# --- custom properties + class defaults (layer 1 "spawns") ---
let e0 = Tiled.object(m, 1, 0) # id 10, hp override = 99
if Tiled.prop_int(e0, "hp") == 99 { print(10) }
let e1 = Tiled.object(m, 1, 1) # id 11, no hp -> Enemy default 10
if Tiled.prop_int(e1, "hp") == 10 { print(11) }
if Tiled.prop_int(e1, "speed") == 3 { print(12) } # class default
if Tiled.prop_type(e1, "hp") == "int" { print(13) }
# --- template instance inherits its template's fields (id 12) ---
let e2 = Tiled.object(m, 1, 2)
if Value.as_str(Value.get(e2, "type")) == "Enemy" { print(14) } # type inherited from p4_enemy.tx
if Tiled.prop_int(e2, "hp") == 25 { print(15) } # hp inherited from p4_enemy.tx
# --- opt-in spawn maps an object's class/properties -> components ---
let ent = Tiled.spawn(m, e0, "Enemy")
let pp = World.prop_id("Position")
let ph = World.prop_id("Health")
let ok_pos = World.get(ent, pp, World.field_id(pp, "x")) == 32
let ok_hp = World.get(ent, ph, World.field_id(ph, "hp")) == 99
if ok_pos and ok_hp { print(16) }
# --- the design's named fixture: orthogonal-outside.tmx object shapes ---
let og = Tiled.load("assets/tiled-fixtures/orthogonal-outside.tmx")
var olayer = -1
var oli = 0
while oli < Tiled.layer_count(og) {
if Tiled.object_count(og, oli) > 0 { olayer = oli }
oli += 1
}
var nell = 0
var npt = 0
var npg = 0
var npl = 0
var oi = 0
while oi < Tiled.object_count(og, olayer) {
let sh = Tiled.object_shape(Tiled.object(og, olayer, oi))
if sh == "ellipse" { nell += 1 }
if sh == "point" { npt += 1 }
if sh == "polygon" { npg += 1 }
if sh == "polyline" { npl += 1 }
oi += 1
}
if nell == 1 and npt == 1 and npg == 1 { print(17) }
if npl == 2 { print(18) }
}
handler Run phase Update { quit() }
}