Skip to content

Commit

Permalink
wip: refactoring vaniaGame to manage multiple rendered rooms
Browse files Browse the repository at this point in the history
Nearly working, tho setting offsets isn't quite right yet.
  • Loading branch information
russmatney committed May 25, 2024
1 parent 1760306 commit e567c32
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 66 deletions.
78 changes: 77 additions & 1 deletion src/dino/modes/vania/Vania.tscn
Original file line number Diff line number Diff line change
@@ -1,6 +1,82 @@
[gd_scene load_steps=2 format=3 uid="uid://tfkeuag6o577"]
[gd_scene load_steps=11 format=3 uid="uid://tfkeuag6o577"]

[ext_resource type="Script" path="res://src/dino/modes/vania/Vania.gd" id="1_w5rvh"]
[ext_resource type="Script" path="res://src/dino/vania/RoomShape.gd" id="2_ysnxy"]
[ext_resource type="Script" path="res://src/dino/vania/MapInput.gd" id="3_tsuii"]
[ext_resource type="Script" path="res://src/dino/vania/MapDef.gd" id="4_dus2l"]

[sub_resource type="Resource" id="Resource_4hsaf"]
script = ExtResource("2_ysnxy")
cells = Array[Vector3i]([Vector3i(0, 0, 0)])
type = 1

[sub_resource type="Resource" id="Resource_10v7o"]
script = ExtResource("3_tsuii")
genre_type = 0
entities = Array[Resource("res://src/dino/entities/DinoEntity.gd")]([])
enemies = Array[Resource("res://src/dino/enemies/DinoEnemy.gd")]([])
room_shapes = Array[ExtResource("2_ysnxy")]([SubResource("Resource_4hsaf")])
room_effects = Array[Resource("res://src/dino/vania/RoomEffect.gd")]([])
tiles = Array[Resource("res://src/dino/tiles/DinoTiles.gd")]([])
door_mode = 3
neighbor_direction = Vector2i(0, 0)
skip_borders = Array[Vector2i]([])
drops = Array[Resource("res://src/dino/pickups/DropData.gd")]([])
bg_color = Color(0, 0, 0, 1)
grids_path = ""

[sub_resource type="Resource" id="Resource_msijw"]
script = ExtResource("3_tsuii")
genre_type = 0
entities = Array[Resource("res://src/dino/entities/DinoEntity.gd")]([])
enemies = Array[Resource("res://src/dino/enemies/DinoEnemy.gd")]([])
room_shapes = Array[ExtResource("2_ysnxy")]([])
room_effects = Array[Resource("res://src/dino/vania/RoomEffect.gd")]([])
tiles = Array[Resource("res://src/dino/tiles/DinoTiles.gd")]([])
door_mode = 0
neighbor_direction = Vector2i(0, 0)
skip_borders = Array[Vector2i]([])
drops = Array[Resource("res://src/dino/pickups/DropData.gd")]([])
bg_color = Color(0, 0, 0, 1)
grids_path = ""

[sub_resource type="Resource" id="Resource_3she3"]
script = ExtResource("3_tsuii")
genre_type = 0
entities = Array[Resource("res://src/dino/entities/DinoEntity.gd")]([])
enemies = Array[Resource("res://src/dino/enemies/DinoEnemy.gd")]([])
room_shapes = Array[ExtResource("2_ysnxy")]([])
room_effects = Array[Resource("res://src/dino/vania/RoomEffect.gd")]([])
tiles = Array[Resource("res://src/dino/tiles/DinoTiles.gd")]([])
door_mode = 0
neighbor_direction = Vector2i(0, 0)
skip_borders = Array[Vector2i]([])
drops = Array[Resource("res://src/dino/pickups/DropData.gd")]([])
bg_color = Color(0, 0, 0, 1)
grids_path = ""

[sub_resource type="Resource" id="Resource_y4ahk"]
script = ExtResource("3_tsuii")
genre_type = 0
entities = Array[Resource("res://src/dino/entities/DinoEntity.gd")]([])
enemies = Array[Resource("res://src/dino/enemies/DinoEnemy.gd")]([])
room_shapes = Array[ExtResource("2_ysnxy")]([])
room_effects = Array[Resource("res://src/dino/vania/RoomEffect.gd")]([])
tiles = Array[Resource("res://src/dino/tiles/DinoTiles.gd")]([])
door_mode = 0
neighbor_direction = Vector2i(0, 0)
skip_borders = Array[Vector2i]([])
drops = Array[Resource("res://src/dino/pickups/DropData.gd")]([])
bg_color = Color(0, 0, 0, 1)
grids_path = ""

[sub_resource type="Resource" id="Resource_0ffnm"]
script = ExtResource("4_dus2l")
name = ""
input = SubResource("Resource_10v7o")
rooms = Array[ExtResource("3_tsuii")]([SubResource("Resource_msijw"), SubResource("Resource_3she3"), SubResource("Resource_y4ahk")])
sub_map_defs = Array[ExtResource("4_dus2l")]([])

[node name="Vania" type="Node2D"]
script = ExtResource("1_w5rvh")
map_def = SubResource("Resource_0ffnm")
2 changes: 2 additions & 0 deletions src/dino/tiles/DinoTileMap.gd
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ func mix_terrains(opts={}):

var chunk_count = U.rand_of([5,6,7,8]) * cell_count
var tile_coords = get_used_cells(0)
if tile_coords.is_empty():
return

var grids = chunk_defs.grids_with_flag("tile_chunk")

Expand Down
25 changes: 10 additions & 15 deletions src/dino/vania/MapInput.gd
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ class_name MapInput
@export var entities: Array[DinoEntity]
@export var enemies: Array[DinoEnemy]

@export var room_shape: RoomShape
@export var room_shapes: Array[RoomShape]

@export var room_effects: Array[RoomEffect]
Expand Down Expand Up @@ -42,8 +41,6 @@ func _init(opts={}):
genre_type = opts.get("genre_type")
entities.assign(opts.get("entities", []))
enemies.assign(opts.get("enemies", []))
if opts.get("room_shape"):
room_shape = opts.get("room_shape")
room_shapes.assign(opts.get("room_shapes", []))
if opts.get("room_effects"):
room_effects.assign(opts.get("room_effects"))
Expand All @@ -61,7 +58,6 @@ func to_pretty():
entities=entities,
enemies=enemies,
tiles=tiles,
room_shape=room_shape,
room_shapes=room_shapes,
room_effects=room_effects,
door_mode=door_mode,
Expand All @@ -73,6 +69,8 @@ func to_pretty():
## merge ######################################################

func merge(b: MapInput):
if not b:
return self

# enums as ints are such a PITA
var dm = door_mode
Expand All @@ -87,7 +85,6 @@ func merge(b: MapInput):
genre_type=U._or(b.genre_type, genre_type),
entities=U.append_array(entities, b.entities),
enemies=U.append_array(enemies, b.enemies),
room_shape=U._or(b.room_shape, room_shape),
room_shapes=U.distinct(U.append_array(room_shapes, b.room_shapes)),
room_effects=U.distinct(U.append_array(room_effects, b.room_effects)),
tiles=U.distinct(U.append_array(tiles, b.tiles)),
Expand Down Expand Up @@ -118,9 +115,7 @@ func set_room_def_shape(def):
elif not grids.is_empty():
pass

if room_shape:
def.set_local_cells(room_shape.cells)
elif room_shapes and not room_shapes.is_empty():
if room_shapes and not room_shapes.is_empty():
def.set_local_cells(room_shapes.pick_random().cells)
else:
def.set_local_cells(RoomShape.random_shape().cells)
Expand Down Expand Up @@ -220,25 +215,25 @@ static func has_dust(_opts={}):
static func has_room(opts={}):
if opts.get("shape") == null:
Log.warn("has_room missing 'shape'!")
return MapInput.new({room_shape=RoomShape.new({cells=opts.get("shape")})})
return MapInput.new({room_shapes=[RoomShape.new({cells=opts.get("shape")})]})

static func small_room_shape(_opts={}):
return MapInput.new({room_shape=RoomShape.small_room()})
return MapInput.new({room_shapes=[RoomShape.small_room()]})

static func large_room_shape(_opts={}):
return MapInput.new({room_shape=RoomShape.large_rooms().pick_random()})
return MapInput.new({room_shapes=[RoomShape.large_rooms().pick_random()]})

static func tall_room_shape(_opts={}):
return MapInput.new({room_shape=RoomShape.tall_rooms().pick_random()})
return MapInput.new({room_shapes=[RoomShape.tall_rooms().pick_random()]})

static func wide_room_shape(_opts={}):
return MapInput.new({room_shape=RoomShape.wide_rooms().pick_random()})
return MapInput.new({room_shapes=[RoomShape.wide_rooms().pick_random()]})

static func L_room_shape(_opts={}):
return MapInput.new({room_shape=RoomShape.L_rooms().pick_random()})
return MapInput.new({room_shapes=[RoomShape.L_rooms().pick_random()]})

static func T_room_shape(_opts={}):
return MapInput.new({room_shape=RoomShape.T_rooms().pick_random()})
return MapInput.new({room_shapes=[RoomShape.T_rooms().pick_random()]})

## tilemaps ######################################################33

Expand Down
108 changes: 62 additions & 46 deletions src/dino/vania/VaniaGame.gd
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ var player: Node2D
var current_room: Node2D

var modules: Array

signal room_loaded

var generator = VaniaGenerator.new()
Expand Down Expand Up @@ -109,7 +108,6 @@ func mark_room_quests_complete(room_path=null):
func _ready():
modules.append(VaniaRoomTransitions.new(self))

room_loaded.connect(on_room_loaded, CONNECT_DEFERRED)
# MetSys.cell_changed.connect(on_cell_changed, CONNECT_DEFERRED)
# Dino.player_ready.connect(on_player_ready)

Expand All @@ -135,23 +133,11 @@ func _ready():

func add_child_to_level(_node, child):
if current_room and is_instance_valid(current_room):
Log.pr("adding child to current room", child, "current room position: ", current_room.position)
current_room.add_child(child)
else:
add_child(child)

## room loaded #######################################################

func on_room_loaded():
# if not is_room_visited():
# Dino.notif({type="banner", text="%s" % current_room.name, id="room-name"})
mark_room_visited()

# TODO should/could be on vaniaGame directly
# would make sense for the multi-room quest refactor
var qm = current_room.quest_manager
qm.quest_complete.connect(on_room_quest_complete)
qm.all_quests_complete.connect(on_room_quests_complete, CONNECT_ONE_SHOT)

func on_room_quest_complete(_quest):
pass
# Log.pr("quest complete", quest)
Expand Down Expand Up @@ -283,14 +269,18 @@ func load_initial_room():
Log.warn("No room_defs returned, did the generator fail?")
return

var rooms = room_defs.filter(func(rd): return rd.entities().any(func(ent): return ent.get_entity_id() == DinoEntityIds.PLAYERSPAWNPOINT))
# TODO filter/sort by is_start or some such metadata
var rooms = room_defs.filter(func(rd):
return rd.entities().any(func(ent):
return ent.get_entity_id() == DinoEntityIds.PLAYERSPAWNPOINT))

if rooms.is_empty():
Log.warn("No room with player spawn point! Isn't this 'guaranteed' elsewhere?")
rooms = room_defs
# prefer first room def, but consider opts/mode from mapDef
var rpath = rooms[0].room_path
_load_room(rpath, {setup=func(room):
room.set_room_def(get_room_def(rpath))})

var def = rooms[0]

_load_room(def)

## start_vania_game

Expand Down Expand Up @@ -472,27 +462,32 @@ func remove_room(count=1):
## load room #######################################################

# overwriting metsys's Game.load_room to support 'setup' and setting a default layer
func _load_room(path: String, opts={}):
if not path.is_absolute_path():
path = MetSys.get_full_room_path(path)

if current_room:
current_room.queue_free()
await current_room.tree_exited
current_room = null

current_room = load(path).instantiate()
if opts.get("setup"):
opts.get("setup").call(current_room)
add_child(current_room)

if MetSys.get_current_room_instance() != null:
MetSys.current_layer = MetSys.get_current_room_instance().get_layer()
else:
Log.warn("No current room_instance, defaulting to layer 0")
MetSys.current_layer = 0
func _load_room(def: VaniaRoomDef, opts={}):
var next_room = get_vania_room(def)

if not next_room:
next_room = load(def.room_path).instantiate()
next_room.set_room_def(def)
add_child(next_room)

if MetSys.get_current_room_instance() != null:
MetSys.current_layer = MetSys.get_current_room_instance().get_layer()
else:
Log.warn("No current room_instance, defaulting to layer 0")
MetSys.current_layer = 0

# not quite right, maybe gets eaten by run/quest manager?
mark_room_visited(def.room_path)

room_loaded.emit()
# make sure metsys knows this is the 'current' room
MetSys.current_room = next_room.room_instance
add_vania_room(next_room)
room_loaded.emit()

if not next_room:
Log.warn("no next_room? wut?", next_room)

current_room = next_room

func reload_current_room():
MetSys.room_changed.emit(MetSys.get_current_room_name(), false)
Expand Down Expand Up @@ -523,7 +518,33 @@ func _set_player_position():
if p:
MetSys.set_player_position(p.position)

## room defs #######################################################
## rooms #######################################################

var loaded_rooms: Dictionary = {}

func get_vania_rooms():
return loaded_rooms.values()

func get_vania_room(def_or_path) -> VaniaRoom:
var path: String
if def_or_path is String:
path = def_or_path
elif def_or_path is VaniaRoomDef:
path = def_or_path.room_path
else:
Log.warn("Unexpected get_vania_room input", def_or_path)

return loaded_rooms.get(path)

func add_vania_room(room):
var path = room.room_def.room_path
loaded_rooms[path] = room

func erase_vania_room(room):
var path = room.room_def.room_path
loaded_rooms.erase(path)

## room_defs #######################################################

func get_room_def(path):
for rd in room_defs:
Expand All @@ -534,11 +555,6 @@ func current_room_def():
var path = MetSys.get_current_room_name()
return get_room_def(path)

# i wonder if these ever get out sync
func current_room_def_alt():
if current_room:
return current_room.room_def

## player reactions ##################################################3

# connected via player ready and `add_child_to_level` / Util level_root api :/
Expand Down
20 changes: 16 additions & 4 deletions src/dino/vania/VaniaRoomTransitions.gd
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,18 @@ func _on_room_changed(target_room: String, ignore_same_room=true):

if new_room_def == null:
Log.warn("No new room def in room transition, aborting", target_room)
return
if prev_room_def == null:
Log.warn("No prev room def in room transition, aborting", MetSys.get_current_room_name())
return

var prev_room_instance = MetSys.get_current_room_instance()
if prev_room_instance:
prev_room_instance.get_parent().remove_child(prev_room_instance)

await game._load_room(target_room, {setup=func(room):
room.set_room_def(game.get_room_def(target_room))})
game._load_room(new_room_def)

Log.info("%s rooms now loaded", len(game.get_vania_rooms()))
# TODO at some n rooms, drop far-away rooms
# maybe check for rooms that are n-cells away?

var og_player = Dino.current_player_node()
var og_p_position = og_player.position
Expand All @@ -42,6 +45,15 @@ func _on_room_changed(target_room: String, ignore_same_room=true):
var offset = Vector2()
if prev_room_instance:
offset = MetSys.get_current_room_instance().get_room_position_offset(prev_room_instance)
Log.pr("offset from prev!", offset)

# reposition all rooms according to the offset
for room in game.get_vania_rooms():
if room.room_def.room_path == target_room:
continue
Log.pr("repositioning room", room.name, room.position)
room.position -= offset
Log.pr("repositioned room", room.name, room.position)

# maybe some nice way to handle this
if abs(og_p_velocity.x) > abs(og_p_velocity.y):
Expand Down

0 comments on commit e567c32

Please sign in to comment.