-
Notifications
You must be signed in to change notification settings - Fork 1
/
tile_interactor.gd
101 lines (77 loc) · 3.41 KB
/
tile_interactor.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
extends Node
@export var player: BallsPlayer = null
@export var tile_map: TileMap = null
@export var rules: Array[TileRule] = []
#
# Godot Functions
#
func _ready():
player = CheckpointManager.get_player()
CheckpointManager.player_spawned.connect(_on_player_spawned.bind())
CheckpointManager.player_despawned.connect(_on_player_despawned.bind())
CheckpointManager.player_reset.connect(_on_player_reset.bind())
func _physics_process(delta: float):
if not player: return
_process_body(delta, player.ball_a)
_process_body(delta, player.ball_b)
#
# Public Functions
#
func connect_player(new_player: BallsPlayer):
player = new_player
player.tile_collided.connect(_on_tile_collided.bind())
player.grapple_locked.connect(_on_grapple_locked.bind())
player.grapple_unlocked.connect(_on_grapple_unlocked.bind())
#
# Private Functions
#
func _process_body(_delta: float, body: Node2D) -> void:
for layer in tile_map.get_layers_count():
# Figure out what tile the body is on
var overlapped_tile = tile_map.local_to_map(tile_map.to_local(body.global_position))
var tile_id = tile_map.get_cell_source_id(layer, overlapped_tile)
var last_id = body.get_meta("lay%s_last_id" % layer, -1)
var last_tile_pos = body.get_meta("lay%s_last_tile_pos" % layer, Vector2i.ZERO)
# If this body wasn't last on this tile, then call the rules for this tile
if last_tile_pos != overlapped_tile:
for rule in _get_rules_for_id(last_id):
rule.exit_tile(tile_map, layer, last_tile_pos, body, player)
body.set_meta("lay%s_last_id" % layer, tile_id)
body.set_meta("lay%s_last_tile_pos" % layer, overlapped_tile)
for rule in _get_rules_for_id(tile_id):
rule.enter_tile(tile_map, layer, overlapped_tile, body, player)
## Returns an array of rules that apply to the given tile
func _get_rules_for_id(id: int) -> Array[TileRule]:
var get_by_id = func(rule: TileRule) -> bool:
return rule.get_tile_id() == id
return rules.filter(get_by_id)
#
# Signals
#
func _on_tile_collided(hit_tile_map: TileMap, tile_position: Vector2i, body: PhysicsBody2D) -> void:
for layer in tile_map.get_layers_count():
# Figure out what tile the body hit
var tile_id = hit_tile_map.get_cell_source_id(layer, tile_position)
for rule in _get_rules_for_id(tile_id):
rule.hit_tile(hit_tile_map, layer, tile_position, body, player)
func _on_grapple_locked(grapple: Grapple3, point: Vector2, normal: Vector2, _collider: Object):
for layer in tile_map.get_layers_count():
# Figure out what tile the body is on
var overlapped_tile = tile_map.local_to_map(tile_map.to_local(point - normal))
var tile_id = tile_map.get_cell_source_id(layer, overlapped_tile)
for rule in _get_rules_for_id(tile_id):
rule.grapple_locked_tile(tile_map, layer, overlapped_tile, grapple, point, normal, player)
func _on_grapple_unlocked(grapple: Grapple3, point: Vector2, normal: Vector2, _collider: Object):
for layer in tile_map.get_layers_count():
# Figure out what tile the body is on
var overlapped_tile = tile_map.local_to_map(tile_map.to_local(point - normal))
var tile_id = tile_map.get_cell_source_id(layer, overlapped_tile)
for rule in _get_rules_for_id(tile_id):
rule.grapple_unlocked_tile(tile_map, layer, overlapped_tile, grapple, point, normal, player)
func _on_player_spawned(new_player: BallsPlayer):
connect_player(new_player)
func _on_player_despawned(_new_player: BallsPlayer):
player = null
func _on_player_reset():
for rule in rules:
rule.reset()