Refactor game structure and update project settings for 2D gameplay. Removed the game stub scene, introduced a new vault scene, and organized game scripts into distinct files for grid management, rendering, and scene control. Updated input actions for camera movement and changed rendering method to Mobile for better performance.

This commit is contained in:
Leonid Pershin
2026-08-10 21:36:56 +03:00
parent adfbbbcec3
commit 044dde7b5f
17 changed files with 838 additions and 158 deletions
+177
View File
@@ -0,0 +1,177 @@
class_name VaultGrid
extends RefCounted
## Модель убежища: сетка этажей и комнаты на ней.
##
## Здесь нет ни узлов, ни отрисовки — только данные и правила размещения.
## Вид (vault_view.gd) читает эту модель, а сохранение сериализует её целиком.
## Размер одной ячейки сетки в пикселях мира.
const CELL := Vector2(140.0, 120.0)
## Колонка 0 — лифтовая шахта, комнаты занимают 1..COLUMNS-1.
const COLUMNS := 9
const FLOORS := 6
const ELEVATOR_COLUMN := 0
## Типы комнат: подпись, цвет, ширина в ячейках и баланс ресурсов за цикл.
const KINDS := {
"living": {
"label": "Жилой блок", "color": "#2ee6c5", "width": 2,
"power": -2, "water": 0, "food": 0,
},
"power": {
"label": "Генератор", "color": "#f2b134", "width": 2,
"power": 8, "water": 0, "food": 0,
},
"water": {
"label": "Водоочистка", "color": "#4aa8f2", "width": 2,
"power": -3, "water": 6, "food": 0,
},
"diner": {
"label": "Столовая", "color": "#f2704a", "width": 2,
"power": -3, "water": 0, "food": 6,
},
"storage": {
"label": "Склад", "color": "#9b8cf5", "width": 1,
"power": -1, "water": 0, "food": 0,
},
}
## Комнаты: [{"kind": String, "floor": int, "column": int}, ...]
var rooms: Array[Dictionary] = []
## Стартовая застройка: без неё убежище выглядит пустой ямой.
func reset_to_starter() -> void:
rooms.clear()
place("living", 0, 1)
place("power", 0, 3)
place("diner", 1, 1)
place("water", 1, 3)
# --- Правила размещения -----------------------------------------------------
static func kind_width(kind: String) -> int:
return int(KINDS[kind]["width"])
func in_bounds(a_floor: int, column: int, width: int) -> bool:
if a_floor < 0 or a_floor >= FLOORS:
return false
if column <= ELEVATOR_COLUMN:
return false
return column + width <= COLUMNS
func can_place(kind: String, a_floor: int, column: int) -> bool:
if not KINDS.has(kind):
return false
var width := kind_width(kind)
if not in_bounds(a_floor, column, width):
return false
for offset in width:
if room_index_at(a_floor, column + offset) >= 0:
return false
return true
func place(kind: String, a_floor: int, column: int) -> bool:
if not can_place(kind, a_floor, column):
return false
rooms.append({"kind": kind, "floor": a_floor, "column": column})
return true
## Индекс комнаты, накрывающей ячейку, или -1.
func room_index_at(a_floor: int, column: int) -> int:
for index in rooms.size():
var room: Dictionary = rooms[index]
if int(room["floor"]) != a_floor:
continue
var start := int(room["column"])
if column >= start and column < start + kind_width(String(room["kind"])):
return index
return -1
func remove_at(a_floor: int, column: int) -> bool:
var index := room_index_at(a_floor, column)
if index < 0:
return false
rooms.remove_at(index)
return true
# --- Геометрия --------------------------------------------------------------
static func cell_rect(a_floor: int, column: int, width: int = 1) -> Rect2:
return Rect2(
Vector2(column * CELL.x, a_floor * CELL.y),
Vector2(CELL.x * width, CELL.y)
)
static func room_rect(room: Dictionary) -> Rect2:
return cell_rect(int(room["floor"]), int(room["column"]), kind_width(String(room["kind"])))
## Ячейка под точкой в координатах вида. Может оказаться за пределами сетки —
## проверяйте in_bounds().
static func cell_at(local_position: Vector2) -> Vector2i:
return Vector2i(
int(floor(local_position.x / CELL.x)),
int(floor(local_position.y / CELL.y))
)
## Прямоугольник всего убежища в координатах вида.
static func bounds() -> Rect2:
return Rect2(Vector2.ZERO, Vector2(COLUMNS * CELL.x, FLOORS * CELL.y))
# --- Сводка по ресурсам -----------------------------------------------------
func totals() -> Dictionary:
var result := {"power": 0, "water": 0, "food": 0}
for room: Dictionary in rooms:
var kind: Dictionary = KINDS[String(room["kind"])]
for key: String in result:
result[key] = int(result[key]) + int(kind[key])
return result
func count_of(kind: String) -> int:
var total := 0
for room: Dictionary in rooms:
if String(room["kind"]) == kind:
total += 1
return total
# --- Сериализация -----------------------------------------------------------
func to_array() -> Array:
var data := []
for room: Dictionary in rooms:
data.append({
"kind": String(room["kind"]),
"floor": int(room["floor"]),
"column": int(room["column"]),
})
return data
func from_array(data: Array) -> void:
rooms.clear()
for entry: Variant in data:
if not (entry is Dictionary):
continue
var room: Dictionary = entry
var kind := String(room.get("kind", ""))
if not KINDS.has(kind):
continue
rooms.append({
"kind": kind,
"floor": int(room.get("floor", 0)),
"column": int(room.get("column", 1)),
})