M1d: creatures, hunting, weapons, food buffs and the hide cloak
- Rabbits, deer and boars with procedural meshes and animated legs, a state machine (idle/wander/flee/charge/dead) and heightmap steering that avoids water, cliffs, the world edge, trees and buildings - Spawner keeps a habitat-based budget around the player (6/4/3) - Melee needs a weapon or tool (club, spear, axe, pickaxe); box sweep hits - Wooden spear (thrust or throw) and crude bow with draw-scaled arrows; projectiles stick in the world as saved pickups - Carcasses: E to butcher for meat, hide and embedded arrows - Boars charge and gore when hit; hurt flash and a brief healing pause - Cooked meat gives Well fed (faster stamina and healing); buffs saved - Hide cloak: wear for warmth, saved, goes in the grave on death - Feathers as meadow pickups (appended, existing save ids unchanged) - New test_creatures_combat suite; run_all.sh gets a per-suite time limit
This commit is contained in:
98
scripts/creatures/creature_meshes.gd
Normal file
98
scripts/creatures/creature_meshes.gd
Normal file
@@ -0,0 +1,98 @@
|
||||
extends RefCounted
|
||||
## Procedural low-poly animals, built from the same helpers as the trees and
|
||||
## items (flat-shaded, vertex colours, no assets).
|
||||
##
|
||||
## Each kind gives a static "body" mesh (torso, head, ears, tail) facing -Z,
|
||||
## one "leg" mesh hanging from the origin down -Y, and the four hip points
|
||||
## the legs pivot on. creature.gd animates the legs.
|
||||
|
||||
const P = preload("res://scripts/world/proc_mesh.gd")
|
||||
|
||||
static var _cache := {}
|
||||
|
||||
static func build(kind: String) -> Dictionary:
|
||||
if _cache.has(kind):
|
||||
return _cache[kind]
|
||||
var d: Dictionary
|
||||
match kind:
|
||||
"rabbit": d = _rabbit()
|
||||
"deer": d = _deer()
|
||||
_: d = _boar()
|
||||
_cache[kind] = d
|
||||
return d
|
||||
|
||||
static func _rng(seed: int) -> RandomNumberGenerator:
|
||||
var r := RandomNumberGenerator.new()
|
||||
r.seed = seed
|
||||
return r
|
||||
|
||||
static func _noise(seed: int, f: float = 1.6) -> FastNoiseLite:
|
||||
var n := FastNoiseLite.new()
|
||||
n.seed = seed
|
||||
n.frequency = f
|
||||
return n
|
||||
|
||||
static func _leg(len: float, r0: float, r1: float, col: Color, hoof: Color, seed: int) -> ArrayMesh:
|
||||
var st := P._begin()
|
||||
var r := _rng(seed)
|
||||
P._cylinder(st, Vector3(0, 0, 0), Vector3(0, -len * 0.55, 0.02), r0, r0 * 0.75, 5, col, r, 0.0)
|
||||
P._cylinder(st, Vector3(0, -len * 0.55, 0.02), Vector3(0, -len, 0), r0 * 0.75, r1, 5, col, r, 0.0, hoof)
|
||||
return P._commit(st)
|
||||
|
||||
static func _rabbit() -> Dictionary:
|
||||
var fur := Color(0.55, 0.46, 0.36)
|
||||
var st := P._begin()
|
||||
var r := _rng(201)
|
||||
var n := _noise(201)
|
||||
P._blob(st, Vector3(0, 0.2, 0.03), Vector3(0.13, 0.13, 0.2), n, 0.15, fur, r, 1)
|
||||
P._blob(st, Vector3(0, 0.31, -0.17), Vector3(0.085, 0.085, 0.1), n, 0.12, fur, r, 1)
|
||||
for s in [-1.0, 1.0]:
|
||||
P._cylinder(st, Vector3(s * 0.035, 0.38, -0.15), Vector3(s * 0.06, 0.56, -0.1), 0.025, 0.018, 4, P._mul(fur, 1.1), r, -1.0, Color(0.85, 0.65, 0.6))
|
||||
P._blob(st, Vector3(s * 0.05, 0.33, -0.25), Vector3.ONE * 0.012, n, 0.0, Color(0.05, 0.04, 0.04), r, 0)
|
||||
P._blob(st, Vector3(0, 0.25, 0.23), Vector3.ONE * 0.05, n, 0.2, Color(0.93, 0.92, 0.88), r, 0)
|
||||
return {"body": P._commit(st), "leg": _leg(0.12, 0.03, 0.025, fur, P._mul(fur, 0.8), 202),
|
||||
"hips": [Vector3(-0.07, 0.12, -0.1), Vector3(0.07, 0.12, -0.1), Vector3(-0.08, 0.14, 0.12), Vector3(0.08, 0.14, 0.12)],
|
||||
"radius": 0.18, "height": 0.4}
|
||||
|
||||
static func _deer() -> Dictionary:
|
||||
var coat := Color(0.62, 0.42, 0.25)
|
||||
var belly := Color(0.85, 0.76, 0.62)
|
||||
var dark := Color(0.2, 0.15, 0.12)
|
||||
var st := P._begin()
|
||||
var r := _rng(211)
|
||||
var n := _noise(211, 1.2)
|
||||
P._blob(st, Vector3(0, 1.0, 0), Vector3(0.26, 0.3, 0.62), n, 0.12, coat, r, 1)
|
||||
P._blob(st, Vector3(0, 0.86, 0.05), Vector3(0.2, 0.14, 0.45), n, 0.1, belly, r, 1)
|
||||
P._cylinder(st, Vector3(0, 1.1, -0.45), Vector3(0, 1.55, -0.68), 0.13, 0.09, 6, coat, r)
|
||||
P._blob(st, Vector3(0, 1.6, -0.78), Vector3(0.11, 0.12, 0.2), n, 0.1, coat, r, 1)
|
||||
P._blob(st, Vector3(0, 1.55, -0.96), Vector3(0.05, 0.05, 0.05), n, 0.0, dark, r, 0)
|
||||
for s in [-1.0, 1.0]:
|
||||
P._cylinder(st, Vector3(s * 0.07, 1.7, -0.72), Vector3(s * 0.2, 1.82, -0.66), 0.04, 0.015, 4, coat, r)
|
||||
P._blob(st, Vector3(s * 0.08, 1.65, -0.86), Vector3.ONE * 0.022, n, 0.0, dark, r, 0)
|
||||
# Small antlers.
|
||||
P._cylinder(st, Vector3(s * 0.04, 1.72, -0.76), Vector3(s * 0.12, 2.0, -0.7), 0.018, 0.01, 4, Color(0.8, 0.74, 0.6), r)
|
||||
P._cylinder(st, Vector3(s * 0.09, 1.88, -0.72), Vector3(s * 0.08, 2.0, -0.86), 0.012, 0.006, 3, Color(0.8, 0.74, 0.6), r)
|
||||
P._blob(st, Vector3(0, 1.12, 0.62), Vector3(0.06, 0.09, 0.05), n, 0.1, belly, r, 0)
|
||||
return {"body": P._commit(st), "leg": _leg(0.88, 0.055, 0.035, coat, dark, 212),
|
||||
"hips": [Vector3(-0.14, 0.9, -0.42), Vector3(0.14, 0.9, -0.42), Vector3(-0.14, 0.92, 0.42), Vector3(0.14, 0.92, 0.42)],
|
||||
"radius": 0.4, "height": 1.7}
|
||||
|
||||
static func _boar() -> Dictionary:
|
||||
var bristle := Color(0.33, 0.25, 0.2)
|
||||
var snout := Color(0.55, 0.4, 0.36)
|
||||
var tusk := Color(0.92, 0.9, 0.82)
|
||||
var st := P._begin()
|
||||
var r := _rng(221)
|
||||
var n := _noise(221, 1.4)
|
||||
P._blob(st, Vector3(0, 0.62, 0.02), Vector3(0.32, 0.34, 0.6), n, 0.18, bristle, r, 1)
|
||||
P._blob(st, Vector3(0, 0.8, -0.2), Vector3(0.18, 0.15, 0.3), n, 0.3, P._mul(bristle, 0.75), r, 1) # mane
|
||||
P._blob(st, Vector3(0, 0.6, -0.62), Vector3(0.2, 0.2, 0.26), n, 0.15, bristle, r, 1)
|
||||
P._cylinder(st, Vector3(0, 0.55, -0.8), Vector3(0, 0.5, -0.98), 0.1, 0.08, 6, snout, r, -1.0, P._mul(snout, 0.8))
|
||||
for s in [-1.0, 1.0]:
|
||||
P._cylinder(st, Vector3(s * 0.08, 0.48, -0.88), Vector3(s * 0.12, 0.62, -0.96), 0.022, 0.006, 4, tusk, r)
|
||||
P._cylinder(st, Vector3(s * 0.1, 0.76, -0.62), Vector3(s * 0.17, 0.9, -0.55), 0.05, 0.015, 4, bristle, r)
|
||||
P._blob(st, Vector3(s * 0.11, 0.68, -0.8), Vector3.ONE * 0.02, n, 0.0, Color(0.05, 0.03, 0.03), r, 0)
|
||||
P._cylinder(st, Vector3(0, 0.7, 0.58), Vector3(0, 0.55, 0.72), 0.02, 0.012, 3, bristle, r)
|
||||
return {"body": P._commit(st), "leg": _leg(0.36, 0.07, 0.05, bristle, Color(0.15, 0.12, 0.1), 222),
|
||||
"hips": [Vector3(-0.17, 0.38, -0.36), Vector3(0.17, 0.38, -0.36), Vector3(-0.17, 0.4, 0.38), Vector3(0.17, 0.4, 0.38)],
|
||||
"radius": 0.42, "height": 0.95}
|
||||
Reference in New Issue
Block a user