From 029a43fa4096804f5f7246510838fd6626f4d7af Mon Sep 17 00:00:00 2001 From: Nikolai Fedorov Date: Wed, 22 Apr 2026 17:53:15 +0300 Subject: [PATCH] generate level not from code --- scenes/Level.tscn | 104 +++++++++++++++++++++++++++++++++ scripts/Level.gd | 29 ++++++++++ scripts/Level.gd.uid | 1 + scripts/Main.gd | 134 ++++++------------------------------------- 4 files changed, 152 insertions(+), 116 deletions(-) create mode 100644 scenes/Level.tscn create mode 100644 scripts/Level.gd create mode 100644 scripts/Level.gd.uid diff --git a/scenes/Level.tscn b/scenes/Level.tscn new file mode 100644 index 0000000..50a6cd2 --- /dev/null +++ b/scenes/Level.tscn @@ -0,0 +1,104 @@ +[gd_scene format=3 uid="uid://clevel2xm8n4p"] + +[ext_resource type="Script" path="res://scripts/Level.gd" id="1_level"] + +[sub_resource type="Environment" id="Environment_1"] +background_mode = 1 +background_color = Color(0.04, 0.04, 0.08, 1) +ambient_light_source = 2 +ambient_light_color = Color(0.35, 0.35, 0.5, 1) +ambient_light_energy = 0.6 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"] +albedo_color = Color(0.12, 0.12, 0.18, 1) +roughness = 1.0 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_2"] +albedo_color = Color(0.28, 0.28, 0.42, 1) +roughness = 0.9 +metallic = 0.1 + +[sub_resource type="PlaneMesh" id="PlaneMesh_1"] +size = Vector2(28, 28) +subdivide_width = 8 +subdivide_depth = 8 + +[sub_resource type="BoxShape3D" id="BoxShape3D_1"] +size = Vector3(28, 0.2, 28) + +[sub_resource type="BoxMesh" id="BoxMesh_1"] +size = Vector3(30.4, 1.0, 1.2) + +[sub_resource type="BoxMesh" id="BoxMesh_2"] +size = Vector3(1.2, 1.0, 28.0) + +[sub_resource type="BoxShape3D" id="BoxShape3D_2"] +size = Vector3(30.4, 1.0, 1.2) + +[sub_resource type="BoxShape3D" id="BoxShape3D_3"] +size = Vector3(1.2, 1.0, 28.0) + +[node name="Level" type="Node3D"] +script = ExtResource("1_level") + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_1") + +[node name="Sun" type="DirectionalLight3D" parent="."] +rotation_degrees = Vector3(-55, -25, 0) +light_energy = 1.8 +shadow_enabled = true + +[node name="Floor" type="MeshInstance3D" parent="."] +mesh = SubResource("PlaneMesh_1") +material_override = SubResource("StandardMaterial3D_1") + +[node name="FloorBody" type="StaticBody3D" parent="."] +position = Vector3(0, -0.1, 0) + +[node name="CollisionShape3D" type="CollisionShape3D" parent="FloorBody"] +shape = SubResource("BoxShape3D_1") + +[node name="WallNorth" type="StaticBody3D" parent="."] +position = Vector3(0, 0.5, -14.6) +metadata/is_wall = true + +[node name="Mesh" type="MeshInstance3D" parent="WallNorth"] +mesh = SubResource("BoxMesh_1") +material_override = SubResource("StandardMaterial3D_2") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="WallNorth"] +shape = SubResource("BoxShape3D_2") + +[node name="WallSouth" type="StaticBody3D" parent="."] +position = Vector3(0, 0.5, 14.6) +metadata/is_wall = true + +[node name="Mesh" type="MeshInstance3D" parent="WallSouth"] +mesh = SubResource("BoxMesh_1") +material_override = SubResource("StandardMaterial3D_2") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="WallSouth"] +shape = SubResource("BoxShape3D_2") + +[node name="WallEast" type="StaticBody3D" parent="."] +position = Vector3(14.6, 0.5, 0) +metadata/is_wall = true + +[node name="Mesh" type="MeshInstance3D" parent="WallEast"] +mesh = SubResource("BoxMesh_2") +material_override = SubResource("StandardMaterial3D_2") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="WallEast"] +shape = SubResource("BoxShape3D_3") + +[node name="WallWest" type="StaticBody3D" parent="."] +position = Vector3(-14.6, 0.5, 0) +metadata/is_wall = true + +[node name="Mesh" type="MeshInstance3D" parent="WallWest"] +mesh = SubResource("BoxMesh_2") +material_override = SubResource("StandardMaterial3D_2") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="WallWest"] +shape = SubResource("BoxShape3D_3") diff --git a/scripts/Level.gd b/scripts/Level.gd new file mode 100644 index 0000000..4470ef4 --- /dev/null +++ b/scripts/Level.gd @@ -0,0 +1,29 @@ +extends Node3D + +@export var arena_size: float = 14.0 +@export var show_grid: bool = true + +func _ready() -> void: + if show_grid: + _draw_grid() + +func _draw_grid() -> void: + var grid_mat := StandardMaterial3D.new() + grid_mat.albedo_color = Color(0.2, 0.2, 0.3, 0.5) + grid_mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA + grid_mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + var step := 4.0 + var n := int(arena_size / step) + for i in range(-n, n + 1): + for axis in [0, 1]: + var msh := MeshInstance3D.new() + var box := BoxMesh.new() + if axis == 0: + box.size = Vector3(0.05, 0.01, arena_size * 2) + msh.position = Vector3(i * step, 0.005, 0) + else: + box.size = Vector3(arena_size * 2, 0.01, 0.05) + msh.position = Vector3(0, 0.005, i * step) + msh.mesh = box + msh.material_override = grid_mat + add_child(msh) diff --git a/scripts/Level.gd.uid b/scripts/Level.gd.uid new file mode 100644 index 0000000..12dfc99 --- /dev/null +++ b/scripts/Level.gd.uid @@ -0,0 +1 @@ +uid://3llsew1f8mgs diff --git a/scripts/Main.gd b/scripts/Main.gd index d7dc389..9305c01 100644 --- a/scripts/Main.gd +++ b/scripts/Main.gd @@ -3,17 +3,17 @@ extends Node3D const PLAYER_SCENE := preload("res://scenes/Player.tscn") const ENEMY_SCENE := preload("res://scenes/Enemy.tscn") const ROCK_SCENE := preload("res://scenes/Rock.tscn") +const LEVEL_SCENE := preload("res://scenes/Level.tscn") -const ARENA := 14.0 -const WALL_T := 1.2 const CAM_DIST := 8.0 const MOUSE_SENS := 0.18 const PITCH_MIN := 5.0 const PITCH_MAX := 70.0 const SPAWN_TIME := 10 -var cam_yaw: float = 0.0 -var cam_pitch: float = 28.0 +var arena_size: float = 14.0 +var cam_yaw: float = 0.0 +var cam_pitch: float = 28.0 @onready var spawn_timer: Timer = $SpawnTimer @@ -38,8 +38,7 @@ var upgrade_panel: Panel var gameover_panel: Panel func _ready() -> void: - _create_environment() - _create_arena() + _spawn_level() _create_camera() _create_ui() _spawn_player() @@ -61,111 +60,14 @@ func _input(event: InputEvent) -> void: else: Input.mouse_mode = Input.MOUSE_MODE_CAPTURED -# ─── Environment ────────────────────────────────────────────────────────────── +# ─── Level ──────────────────────────────────────────────────────────────────── -func _create_environment() -> void: - var env := Environment.new() - env.background_mode = Environment.BG_COLOR - env.background_color = Color(0.04, 0.04, 0.08) - env.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR - env.ambient_light_color = Color(0.35, 0.35, 0.5) - env.ambient_light_energy = 0.6 - var we := WorldEnvironment.new() - we.environment = env - add_child(we) - - var sun := DirectionalLight3D.new() - sun.rotation_degrees = Vector3(-55, -25, 0) - sun.light_energy = 1.8 - sun.shadow_enabled = true - add_child(sun) - -# ─── Arena ──────────────────────────────────────────────────────────────────── - -func _create_arena() -> void: - var floor_mat := StandardMaterial3D.new() - floor_mat.albedo_color = Color(0.12, 0.12, 0.18) - floor_mat.roughness = 1.0 - - # Floor mesh (visual only) - var fm := MeshInstance3D.new() - var plane := PlaneMesh.new() - plane.size = Vector2(ARENA * 2, ARENA * 2) - plane.subdivide_width = 8 - plane.subdivide_depth = 8 - fm.mesh = plane - fm.material_override = floor_mat - add_child(fm) - - # Floor collider - var fb := StaticBody3D.new() - var fc := CollisionShape3D.new() - var fs := BoxShape3D.new() - fs.size = Vector3(ARENA * 2, 0.2, ARENA * 2) - fc.shape = fs - fb.position.y = -0.1 - fb.add_child(fc) - add_child(fb) - - # Grid lines on floor - _draw_grid() - - # Four walls - var wall_mat := StandardMaterial3D.new() - wall_mat.albedo_color = Color(0.28, 0.28, 0.42) - wall_mat.roughness = 0.9 - wall_mat.metallic = 0.1 - - _make_wall(Vector3(0, 0.5, -(ARENA + WALL_T * 0.5)), - Vector3(ARENA * 2 + WALL_T * 2, 1.0, WALL_T), wall_mat) - _make_wall(Vector3(0, 0.5, (ARENA + WALL_T * 0.5)), - Vector3(ARENA * 2 + WALL_T * 2, 1.0, WALL_T), wall_mat) - _make_wall(Vector3(-(ARENA + WALL_T * 0.5), 0.5, 0), - Vector3(WALL_T, 1.0, ARENA * 2), wall_mat) - _make_wall(Vector3( (ARENA + WALL_T * 0.5), 0.5, 0), - Vector3(WALL_T, 1.0, ARENA * 2), wall_mat) - -func _make_wall(pos: Vector3, size: Vector3, mat: StandardMaterial3D) -> void: - var body := StaticBody3D.new() - body.position = pos - body.set_meta("is_wall", true) - - var col := CollisionShape3D.new() - var shape := BoxShape3D.new() - shape.size = size - col.shape = shape - body.add_child(col) - - var msh := MeshInstance3D.new() - var box := BoxMesh.new() - box.size = size - msh.mesh = box - msh.material_override = mat - body.add_child(msh) - - add_child(body) - -func _draw_grid() -> void: - # Subtle grid as thin quads - var grid_mat := StandardMaterial3D.new() - grid_mat.albedo_color = Color(0.2, 0.2, 0.3, 0.5) - grid_mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA - grid_mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED - var step := 4.0 - var n := int(ARENA / step) - for i in range(-n, n + 1): - for axis in [0, 1]: - var msh := MeshInstance3D.new() - var box := BoxMesh.new() - if axis == 0: - box.size = Vector3(0.05, 0.01, ARENA * 2) - msh.position = Vector3(i * step, 0.005, 0) - else: - box.size = Vector3(ARENA * 2, 0.01, 0.05) - msh.position = Vector3(0, 0.005, i * step) - msh.mesh = box - msh.material_override = grid_mat - add_child(msh) +func _spawn_level() -> void: + var level := LEVEL_SCENE.instantiate() + add_child(level) + var sz = level.get("arena_size") + if sz != null: + arena_size = float(sz) # ─── Camera ─────────────────────────────────────────────────────────────────── @@ -196,7 +98,7 @@ func _spawn_rocks() -> void: var rock := ROCK_SCENE.instantiate() add_child(rock) var angle := randf() * TAU - var dist := randf_range(3.5, ARENA - 2.0) + var dist := randf_range(3.5, arena_size - 2.0) rock.position = Vector3(cos(angle) * dist, 0.0, sin(angle) * dist) # ─── Player ─────────────────────────────────────────────────────────────────── @@ -243,12 +145,12 @@ func _spawn_enemy() -> void: # Spawn at random edge var side := randi() % 4 - var r := randf_range(-(ARENA - 1.0), ARENA - 1.0) + var r := randf_range(-(arena_size - 1.0), arena_size - 1.0) match side: - 0: enemy.position = Vector3(r, 0, -(ARENA - 0.5)) - 1: enemy.position = Vector3(r, 0, (ARENA - 0.5)) - 2: enemy.position = Vector3(-(ARENA - 0.5), 0, r) - 3: enemy.position = Vector3( (ARENA - 0.5), 0, r) + 0: enemy.position = Vector3(r, 0, -(arena_size - 0.5)) + 1: enemy.position = Vector3(r, 0, (arena_size - 0.5)) + 2: enemy.position = Vector3(-(arena_size - 0.5), 0, r) + 3: enemy.position = Vector3( (arena_size - 0.5), 0, r) func add_bonus_score(amount: int) -> void: score += amount