2D multiplayer platformer using Godot Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

58 lines
2.0 KiB

class_name ChunkLoader
extends Node2D
@export var load_distance := 3
@export var unload_distance := 4
signal start_tracking(chunk: Chunk)
signal stop_tracking (chunk: Chunk)
var tracked_chunks: Dictionary[Vector2i, Variant] # value is unused
# TODO: This is a pretty naive implementation, calling this every
# update regardless of whether or how far the players moved.
func _process(delta: float) -> void:
if not multiplayer.is_server(): return
var loader_chunk_pos := Chunk.pos_from_vec(global_position)
# All currently tracked chunks start out in this dictionary.
# Ones outside of `unload_distance` are removed in the loop.
var out_of_range: Dictionary[Vector2i, Variant] = tracked_chunks.duplicate()
var chunk_range := range(-unload_distance, unload_distance + 1)
for x in chunk_range:
for y in chunk_range:
var chunk_pos := loader_chunk_pos + Vector2i(x, y)
out_of_range.erase(chunk_pos)
if tracked_chunks.has(chunk_pos): continue
# Check to see is chunk is in `load_distance`.
var in_load_range := (absi(x) <= load_distance) and ((absi(y) <= load_distance))
if not in_load_range: continue # it's not
var chunk := Game.WORLD.get_or_create_chunk(chunk_pos)
tracked_chunks[chunk_pos] = null
chunk.tracked_by[self] = null
start_tracking.emit(chunk)
# Untrack any chunks outside of `unload_distance`.
for chunk_pos in out_of_range: _forget(chunk_pos, true)
func _exit_tree() -> void:
for chunk_pos in tracked_chunks: _forget(chunk_pos, false)
tracked_chunks.clear()
func _forget(chunk_pos: Vector2i, emit_signal: bool) -> void:
var chunk := Game.WORLD.get_chunk_or_null(chunk_pos)
tracked_chunks.erase(chunk_pos)
chunk.tracked_by.erase(self)
if emit_signal:
stop_tracking.emit(chunk)
# FIXME: This is currently the only way a chunk gets removed:
# When a player tracks it and stops tracking it. However,
# there's other ways a chunk may be created. Consider this!
if chunk.tracked_by.is_empty():
chunk.get_parent().remove_child(chunk)
chunk.queue_free()