From 9a4142419de1badbab364b0df068bc170eb94b5f Mon Sep 17 00:00:00 2001 From: aibrash Date: Tue, 27 Oct 2026 16:44:24 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A1=D1=82=D0=B0=D1=80=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=D1=8B=D0=B9=20=D1=85=D0=B0=D0=B1=20=D1=81=20=D0=BF=D0=BE=D1=80?= =?UTF-8?q?=D1=82=D0=B0=D0=BB=D0=B0=D0=BC=D0=B8,=20=D0=BF=D0=B5=D1=81?= =?UTF-8?q?=D0=BE=D1=87=D0=BD=D0=B8=D1=86=D0=B0=20=D0=BE=D1=82=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=BC=20=D0=BF=D0=B0=D0=BA=D0=B5=D1=82?= =?UTF-8?q?=D0=BE=D0=BC,=20=D0=BF=D1=80=D0=B8=D1=81=D0=B5=D0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - World/Hub: маленькая стартовая комната (код, без ассетов) с порталами на карты; новые карты добавляются записью в PORTALS (влезает 6 порталов). - Песочница (main.tscn) вынесена в world.pck и качается при входе в портал; основной пакет игры вместо 19.7 МБ стал 2.1 МБ. Выходы из карт ведут в хаб. - Экспорт: три пресета (Web — движок и хаб, World, Backrooms). - Присед: удерживать C (на бегу Shift+C по-прежнему подкат), скорость 3.5. Co-Authored-By: Claude Sonnet 5.5 --- Player/character_body_3d.gd | 37 +++++++++- World/Backrooms/backrooms.tscn | 6 +- World/Hub/hub.gd | 119 +++++++++++++++++++++++++++++++++ World/Hub/hub.gd.uid | 1 + World/Hub/hub.tscn | 10 +++ export_presets.cfg | 52 +++++++++++++- main.tscn | 7 +- project.godot | 2 +- 8 files changed, 224 insertions(+), 10 deletions(-) create mode 100644 World/Hub/hub.gd create mode 100644 World/Hub/hub.gd.uid create mode 100644 World/Hub/hub.tscn diff --git a/Player/character_body_3d.gd b/Player/character_body_3d.gd index 917b056..b6f175c 100644 --- a/Player/character_body_3d.gd +++ b/Player/character_body_3d.gd @@ -74,6 +74,8 @@ const SLIDE_COOLDOWN = 0.3 const SLIDE_CAMERA_DROP = 0.6 const SLIDE_HEIGHT_FACTOR = 0.5 const CROUCH_SPEED = 2.5 # Ползём, если над головой низкий потолок +const CROUCH_WALK_SPEED = 3.5 # Скорость в приседе (держим C; на бегу Shift+C — подкат) +const CROUCH_CAMERA_DROP = 0.6 const MIN_SLIDE_SPEED = 7.0 # Минимальная скорость для начала слайда # --- Ступеньки --- @@ -123,6 +125,7 @@ var bob_time: float = 0.0 # Состояние подката var is_sliding: bool = false +var is_crouching: bool = false var slide_cooldown_timer: float = 0.0 var slide_dir: Vector3 = Vector3.ZERO var slide_speed: float = 0.0 @@ -248,7 +251,7 @@ func _unhandled_input(event: InputEvent) -> void: # Битовые флаги состояния для сетевой синхронизации (см. Net.FLAG_*) func get_net_flags() -> int: var flags := 0 - if is_sliding: flags |= Net.FLAG_SLIDING + if is_sliding or is_crouching: flags |= Net.FLAG_SLIDING # У призрака присед выглядит как сплюснутая капсула if is_wallrunning: flags |= Net.FLAG_WALLRUN if is_dashing: flags |= Net.FLAG_DASH if is_mantling: flags |= Net.FLAG_MANTLE @@ -277,6 +280,8 @@ func _physics_process(delta: float) -> void: var space_down := Input.is_key_pressed(KEY_SPACE) + _update_crouch() + # --- Таймеры прыжка (coyote time + jump buffer) --- if is_on_floor(): coyote_timer = COYOTE_TIME @@ -338,7 +343,9 @@ func _physics_process(delta: float) -> void: if is_wallrunning: _wall_jump(wall_normal) elif coyote_timer > 0.0: - if not is_sliding or _can_stand(): + if (not is_sliding and not is_crouching) or _can_stand(): + if is_crouching: + _end_crouch() velocity.y = JUMP_VELOCITY jump_buffer_timer = 0.0 coyote_timer = 0.0 @@ -360,7 +367,9 @@ func _physics_process(delta: float) -> void: # 3. Скорость (Спринт) var current_speed := WALK_SPEED - if Input.is_key_pressed(KEY_SHIFT): + if is_crouching: + current_speed = CROUCH_WALK_SPEED + elif Input.is_key_pressed(KEY_SHIFT): current_speed = SPRINT_SPEED # 4. Бег по стене @@ -714,6 +723,7 @@ func _try_start_slide() -> void: if horizontal.length() < MIN_SLIDE_SPEED: return + is_crouching = false is_sliding = true slide_dir = horizontal.normalized() slide_speed = clamp(max(horizontal.length() * SLIDE_START_MULT, SLIDE_START_SPEED), 0.0, MAX_SPEED) @@ -744,6 +754,23 @@ func _process_slide(delta: float, direction: Vector3, horizontal: Vector3) -> Ve return direction * CROUCH_SPEED return horizontal.move_toward(Vector3.ZERO, CROUCH_SPEED) +# --- ПРИСЕД --- + +# Держим C на земле — приседаем. Встаём, когда отпустили, и над головой есть место +func _update_crouch() -> void: + var busy := is_sliding or is_dashing or is_wallrunning or is_mantling or not is_on_floor() + if not is_crouching: + if Input.is_key_pressed(KEY_C) and not busy: + is_crouching = true + _set_collider_crouched(true) + elif (busy or not Input.is_key_pressed(KEY_C)) and (is_sliding or _can_stand()): + _end_crouch() + +func _end_crouch() -> void: + is_crouching = false + if not is_sliding: + _set_collider_crouched(false) + func _end_slide() -> void: is_sliding = false slide_cooldown_timer = SLIDE_COOLDOWN @@ -784,6 +811,8 @@ func _update_camera(delta: float, input_dir: Vector2) -> void: var target_offset := 0.0 if is_sliding: target_offset = -SLIDE_CAMERA_DROP + elif is_crouching: + target_offset = -CROUCH_CAMERA_DROP elif is_mantling: target_offset = -0.25 head_offset_y = lerp(head_offset_y, target_offset, 12.0 * delta) @@ -879,6 +908,8 @@ func die() -> void: death_timer = DEATH_TIME if is_sliding: _end_slide() + if is_crouching: + _end_crouch() is_dashing = false is_wallrunning = false is_mantling = false diff --git a/World/Backrooms/backrooms.tscn b/World/Backrooms/backrooms.tscn index 84afdda..6fd5631 100644 --- a/World/Backrooms/backrooms.tscn +++ b/World/Backrooms/backrooms.tscn @@ -24,10 +24,10 @@ catch_height = 3.0 sight_limited = true [node name="Exit" type="Area3D" parent="." unique_id=1540431614] -transform = Transform3D(0, 0, 1, 0, 1, 0, -1, 0, 0, -72, -0.15, 9) +transform = Transform3D(0, 0, 1, 0, 1, 0, -1, 0, 0, -92.93203, -0.15, 10.390619) script = ExtResource("5_portal") -target_map = "world" -target_scene = "res://main.tscn" +target_map = "hub" +target_scene = "res://World/Hub/hub.tscn" title = "EXIT" color = Color(0.3, 1, 0.45, 1) diff --git a/World/Hub/hub.gd b/World/Hub/hub.gd new file mode 100644 index 0000000..ab50ee7 --- /dev/null +++ b/World/Hub/hub.gd @@ -0,0 +1,119 @@ +extends Node3D +# Стартовая комната: ничего тяжёлого, только пол, стены и порталы на карты. Сами карты качаются +# отдельными пакетами при входе в портал (World/map_loader.gd) — поэтому игра стартует быстро. +# Чтобы добавить карту — допиши запись в PORTALS: порталы встанут в ряд по центру (влезает 6). + +const PORTALS := [ + {"title": "SANDBOX", "map": "world", "scene": "res://main.tscn", "pack": "world.pck", "color": Color(0.2, 0.9, 1.0)}, + {"title": "BACKROOMS", "map": "backrooms", "scene": "res://World/Backrooms/backrooms.tscn", "pack": "backrooms.pck", "color": Color(1.0, 0.85, 0.25)}, +] + +const ROOM_WIDTH := 28.0 +const ROOM_DEPTH := 18.0 +const ROOM_HEIGHT := 6.0 +const WALL := 0.5 +const PORTAL_SPACING := 4.5 + +const GRID_SHADER := """ +shader_type spatial; +varying vec3 wpos; +void vertex() { wpos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz; } +void fragment() { + vec2 cell = wpos.xz / 2.0; + vec2 g = abs(fract(cell - 0.5) - 0.5) / fwidth(cell); + float line = 1.0 - min(min(g.x, g.y), 1.0); + ALBEDO = mix(vec3(0.03, 0.04, 0.06), vec3(0.1, 0.65, 0.85), line * 0.8); + EMISSION = vec3(0.04, 0.3, 0.4) * line; + ROUGHNESS = 0.9; +} +""" + +func _ready() -> void: + Net.enter_map("hub") + _build_room() + _build_portals() + _build_environment() + +func _build_room() -> void: + var body := StaticBody3D.new() + body.name = "Room" + add_child(body) + + var floor_mat := ShaderMaterial.new() + floor_mat.shader = Shader.new() + floor_mat.shader.code = GRID_SHADER + var wall_mat := StandardMaterial3D.new() + wall_mat.albedo_color = Color(0.09, 0.1, 0.14) + wall_mat.roughness = 1.0 + var ceiling_mat := StandardMaterial3D.new() + ceiling_mat.albedo_color = Color(0.05, 0.055, 0.08) + + var hw := ROOM_WIDTH * 0.5 + var hd := ROOM_DEPTH * 0.5 + _add_box(body, Vector3(ROOM_WIDTH + WALL * 2, 0.5, ROOM_DEPTH + WALL * 2), Vector3(0, -0.25, 0), floor_mat) + _add_box(body, Vector3(ROOM_WIDTH + WALL * 2, 0.5, ROOM_DEPTH + WALL * 2), Vector3(0, ROOM_HEIGHT + 0.25, 0), ceiling_mat) + _add_box(body, Vector3(ROOM_WIDTH + WALL * 2, ROOM_HEIGHT, WALL), Vector3(0, ROOM_HEIGHT * 0.5, -hd - WALL * 0.5), wall_mat) + _add_box(body, Vector3(ROOM_WIDTH + WALL * 2, ROOM_HEIGHT, WALL), Vector3(0, ROOM_HEIGHT * 0.5, hd + WALL * 0.5), wall_mat) + _add_box(body, Vector3(WALL, ROOM_HEIGHT, ROOM_DEPTH), Vector3(-hw - WALL * 0.5, ROOM_HEIGHT * 0.5, 0), wall_mat) + _add_box(body, Vector3(WALL, ROOM_HEIGHT, ROOM_DEPTH), Vector3(hw + WALL * 0.5, ROOM_HEIGHT * 0.5, 0), wall_mat) + +func _add_box(body: StaticBody3D, size: Vector3, pos: Vector3, mat: Material) -> void: + var shape := BoxShape3D.new() + shape.size = size + var cs := CollisionShape3D.new() + cs.shape = shape + cs.position = pos + body.add_child(cs) + + var mesh := BoxMesh.new() + mesh.size = size + mesh.material = mat + var mi := MeshInstance3D.new() + mi.mesh = mesh + mi.position = pos + mi.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF + add_child(mi) + +# Порталы вдоль северной стены лицом в комнату, по центру +func _build_portals() -> void: + var portal_script := load("res://World/portal.gd") + var z := -ROOM_DEPTH * 0.5 + 1.0 + for i in PORTALS.size(): + var info: Dictionary = PORTALS[i] + var portal := Area3D.new() + portal.set_script(portal_script) + portal.target_map = info.map + portal.target_scene = info.scene + portal.pack_name = info.pack + portal.title = info.title + portal.color = info.color + portal.position = Vector3((i - (PORTALS.size() - 1) * 0.5) * PORTAL_SPACING, 0.0, z) + add_child(portal) + + var label := Label3D.new() + label.text = "CHOOSE A MAP" + label.pixel_size = 0.012 + label.font_size = 64 + label.outline_size = 12 + label.modulate = Color(0.7, 0.9, 1.0) + label.position = Vector3(0, ROOM_HEIGHT - 0.35, -ROOM_DEPTH * 0.5 + 0.1) + add_child(label) + +func _build_environment() -> void: + var env := Environment.new() + env.background_mode = Environment.BG_COLOR + env.background_color = Color(0.02, 0.025, 0.04) + env.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR + env.ambient_light_color = Color(0.5, 0.58, 0.75) + env.ambient_light_energy = 0.55 + var we := WorldEnvironment.new() + we.environment = env + add_child(we) + + var lamp := OmniLight3D.new() + lamp.position = Vector3(0, ROOM_HEIGHT - 0.6, 2.0) + lamp.omni_range = 22.0 + lamp.light_energy = 0.8 + lamp.light_color = Color(0.8, 0.9, 1.0) + lamp.shadow_enabled = false + add_child(lamp) diff --git a/World/Hub/hub.gd.uid b/World/Hub/hub.gd.uid new file mode 100644 index 0000000..3fc22b5 --- /dev/null +++ b/World/Hub/hub.gd.uid @@ -0,0 +1 @@ +uid://dac7t22u2s6to diff --git a/World/Hub/hub.tscn b/World/Hub/hub.tscn new file mode 100644 index 0000000..9da40b4 --- /dev/null +++ b/World/Hub/hub.tscn @@ -0,0 +1,10 @@ +[gd_scene format=3] + +[ext_resource type="Script" path="res://World/Hub/hub.gd" id="1_hub"] +[ext_resource type="PackedScene" uid="uid://c3efk6k8xnf57" path="res://Player/Player.tscn" id="2_player"] + +[node name="Hub" type="Node3D"] +script = ExtResource("1_hub") + +[node name="Player" parent="." instance=ExtResource("2_player")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.2, 5) diff --git a/export_presets.cfg b/export_presets.cfg index 3830140..a8fc461 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -10,7 +10,7 @@ dedicated_server=false custom_features="" export_filter="all_resources" include_filter="" -exclude_filter="models/backrooms/*, World/Backrooms/*" +exclude_filter="models/backrooms/*, World/Backrooms/*, main.tscn, World/Floor/*, World/Sky/*, World/tron_01.ogg, World/forest.gd, World/birds.gd, World/levitate.gd, World/nav-bake.gd, models/building_02*, models/tower_01/*, models/house_02/*, models/cyber-office/*, models/obelisk_01/*, models/Tree_01/*, models/empire-state/*" export_path="../grid-world/index.html" patches=PackedStringArray() patch_delta_encoding=false @@ -100,3 +100,53 @@ progressive_web_app/icon_512x512="" progressive_web_app/background_color=Color(0, 0, 0, 1) threads/emscripten_pool_size=8 threads/godot_pool_size=4 + +[preset.2] + +name="World" +platform="Web" +dedicated_server=false +custom_features="" +export_filter="resources" +export_files=PackedStringArray("res://main.tscn") +include_filter="" +exclude_filter="Player/*, models/Bochi-Rock/*, World/portal.gd" +export_path="../grid-world/world.pck" +patches=PackedStringArray() +patch_delta_encoding=false +patch_delta_compression_level_zstd=19 +patch_delta_min_reduction=0.1 +patch_delta_include_filters="*" +patch_delta_exclude_filters="" +encryption_include_filters="" +encryption_exclude_filters="" +seed=0 +encrypt_pck=false +encrypt_directory=false +script_export_mode=2 + +[preset.2.options] + +custom_template/debug="" +custom_template/release="" +variant/extensions_support=true +variant/thread_support=false +vram_texture_compression/for_desktop=true +vram_texture_compression/for_mobile=false +html/export_icon=true +html/custom_html_shell="" +html/head_include="" +html/canvas_resize_policy=2 +html/focus_canvas_on_start=true +html/experimental_virtual_keyboard=false +progressive_web_app/enabled=false +progressive_web_app/ensure_cross_origin_isolation_headers=true +progressive_web_app/offline_page="" +progressive_web_app/display=3 +progressive_web_app/orientation=0 +progressive_web_app/icon_144x144="" +progressive_web_app/icon_180x180="" +progressive_web_app/icon_512x512="" +progressive_web_app/background_color=Color(0, 0, 0, 1) +threads/emscripten_pool_size=8 +threads/godot_pool_size=4 diff --git a/main.tscn b/main.tscn index ee91d87..5aa7a2c 100644 --- a/main.tscn +++ b/main.tscn @@ -135,7 +135,10 @@ transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 188. script = ExtResource("18_navbake") exclude = Array[NodePath]([NodePath("../Architecture/rock"), NodePath("../CharacterBody3D")]) -[node name="BackroomsPortal" type="Area3D" parent="." unique_id=982018721] +[node name="HubPortal" type="Area3D" parent="." unique_id=982018721] transform = Transform3D(-0.49999985, 0, -0.8660255, 0, 1, 0, 0.8660255, 0, -0.49999985, -14.694777, 7.7547903, 22.85205) script = ExtResource("19_portal") -pack_name = "backrooms.pck" +target_map = "hub" +target_scene = "res://World/Hub/hub.tscn" +title = "HUB" +color = Color(0.85, 0.9, 1, 1) diff --git a/project.godot b/project.godot index cdf4903..3a6221e 100644 --- a/project.godot +++ b/project.godot @@ -11,7 +11,7 @@ config_version=5 [application] config/name="world2" -run/main_scene="uid://6vc0m7mc73f1" +run/main_scene="res://World/Hub/hub.tscn" config/features=PackedStringArray("4.7", "GL Compatibility") config/icon="res://icon.svg"