RapidGameFramework
Reusable Godot managers for data-driven small games
Loading...
Searching...
No Matches
putt_putt_exploration_manager.gd
Go to the documentation of this file.
1extends RefCounted
2
3
6
7
8func create_room(seed:int, options:Dictionary = {}) -> Dictionary:
9 var size:Array = options.get("size", [5, 5]) if options.get("size", []) is Array else [5, 5]
10 var width:int = max(3, int(size[0]) if size.size() >= 1 else 5)
11 var height:int = max(3, int(size[1]) if size.size() >= 2 else 5)
12 var start:Array = options.get("start", [int(floor(width / 2.0)), height - 1]) if options.get("start", []) is Array else [int(floor(width / 2.0)), height - 1]
13 var target:Array = options.get("target", [int(floor(width / 2.0)), 0]) if options.get("target", []) is Array else [int(floor(width / 2.0)), 0]
14 var required_rooms:int = clampi(int(options.get("required_rooms", 4)), 1, width * height)
15 var state:Dictionary = {
16 "schema_version": 1,
17 "seed": seed,
18 "size": [width, height],
19 "current": _clamped_cell(start, width, height),
20 "target": _clamped_cell(target, width, height),
21 "required_rooms": required_rooms,
22 "entered_count": 1,
23 "revealed": [],
24 "complete": false
25 }
26 state = reveal_around(state, state.get("current", []), int(options.get("reveal_radius", 1)))
27 return state
28
29
30func enter_next_room(state:Dictionary) -> Dictionary:
31 var next:Dictionary = state.duplicate(true)
32 if bool(next.get("complete", false)):
33 return next
34 var size:Array = next.get("size", [5, 5]) if next.get("size", []) is Array else [5, 5]
35 var width:int = max(1, int(size[0]) if size.size() >= 1 else 5)
36 var height:int = max(1, int(size[1]) if size.size() >= 2 else 5)
37 var current:Array = next.get("current", [0, 0]) if next.get("current", []) is Array else [0, 0]
38 var target:Array = next.get("target", [width - 1, 0]) if next.get("target", []) is Array else [width - 1, 0]
39 var step:Array = _step_toward(current, target)
40 next["current"] = _clamped_cell(step, width, height)
41 next["entered_count"] = int(next.get("entered_count", 0)) + 1
42 next = reveal_around(next, next.get("current", []), 1)
43 if _same_cell(next.get("current", []), target) or int(next.get("entered_count", 0)) >= int(next.get("required_rooms", 1)):
44 next["complete"] = true
45 return next
46
47
48func reveal_around(state:Dictionary, cell:Array, radius:int = 1) -> Dictionary:
49 var next:Dictionary = state.duplicate(true)
50 var size:Array = next.get("size", [5, 5]) if next.get("size", []) is Array else [5, 5]
51 var width:int = max(1, int(size[0]) if size.size() >= 1 else 5)
52 var height:int = max(1, int(size[1]) if size.size() >= 2 else 5)
53 var center:Array = _clamped_cell(cell, width, height)
54 var revealed:Array = next.get("revealed", []) if next.get("revealed", []) is Array else []
55 for y in range(int(center[1]) - radius, int(center[1]) + radius + 1):
56 for x in range(int(center[0]) - radius, int(center[0]) + radius + 1):
57 if x < 0 or y < 0 or x >= width or y >= height:
58 continue
59 var key:String = "%d,%d" % [x, y]
60 if not revealed.has(key):
61 revealed.append(key)
62 next["revealed"] = revealed
63 return next
64
65
66func is_complete(state:Dictionary) -> bool:
67 return bool(state.get("complete", false))
68
69
70func progress_text(state:Dictionary) -> String:
71 return "%d/%d rooms" % [int(state.get("entered_count", 0)), int(state.get("required_rooms", 1))]
72
73
74func _step_toward(current:Array, target:Array) -> Array:
75 var cx:int = int(current[0]) if current.size() >= 1 else 0
76 var cy:int = int(current[1]) if current.size() >= 2 else 0
77 var tx:int = int(target[0]) if target.size() >= 1 else cx
78 var ty:int = int(target[1]) if target.size() >= 2 else cy
79 if cy != ty:
80 cy += int(sign(float(ty - cy)))
81 elif cx != tx:
82 cx += int(sign(float(tx - cx)))
83 return [cx, cy]
84
85
86func _clamped_cell(raw:Array, width:int, height:int) -> Array:
87 var x:int = int(raw[0]) if raw.size() >= 1 else 0
88 var y:int = int(raw[1]) if raw.size() >= 2 else 0
89 return [clampi(x, 0, width - 1), clampi(y, 0, height - 1)]
90
91
92func _same_cell(a:Array, b:Array) -> bool:
93 return a.size() >= 2 and b.size() >= 2 and int(a[0]) == int(b[0]) and int(a[1]) == int(b[1])