From 0abec8156bd944aa883d544850ee1187219ba943 Mon Sep 17 00:00:00 2001 From: Lucas Fryzek Date: Tue, 17 Sep 2024 22:02:33 +0100 Subject: Initial commit --- .gitattributes | 2 + .gitignore | 16 ++ addons/fpc/EditorModule.gd | 49 +++++ addons/fpc/character.gd | 407 +++++++++++++++++++++++++++++++++++ addons/fpc/character.tscn | 425 +++++++++++++++++++++++++++++++++++++ addons/fpc/debug.gd | 18 ++ addons/fpc/reticles/reticle_0.tscn | 37 ++++ addons/fpc/reticles/reticle_1.tscn | 104 +++++++++ icon.svg | 1 + icon.svg.import | 37 ++++ models/round_room.blend | Bin 0 -> 910976 bytes models/round_room.blend.import | 72 +++++++ models/round_room.blend1 | Bin 0 -> 910976 bytes models/round_room_Door.res | Bin 0 -> 3758 bytes models/round_room_RoundRoom.res | Bin 0 -> 14353 bytes prefabs/bsp_level_generator.tscn | 8 + prefabs/bullet.tscn | 17 ++ prefabs/door.tscn | 16 ++ prefabs/enemy.tscn | 29 +++ prefabs/level_generator.tscn | 6 + prefabs/round_room.tscn | 16 ++ prefabs/test_arena.tscn | 120 +++++++++++ project.godot | 65 ++++++ scripts/bsp_level_generator.gd | 78 +++++++ scripts/bullet.gd | 17 ++ scripts/enemy.gd | 87 ++++++++ scripts/level_generator.gd | 118 ++++++++++ scripts/player.gd | 76 +++++++ scripts/spin_ground.gd | 15 ++ test.tscn | 46 ++++ test_world.tscn | 106 +++++++++ textures/dark.png | Bin 0 -> 2774 bytes textures/dark.png.import | 35 +++ textures/green.png | Bin 0 -> 2774 bytes textures/green.png.import | 35 +++ textures/orange.png | Bin 0 -> 2774 bytes textures/orange.png.import | 35 +++ textures/purple.png | Bin 0 -> 2774 bytes textures/purple.png.import | 34 +++ textures/red.png | Bin 0 -> 2774 bytes textures/red.png.import | 34 +++ 41 files changed, 2161 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 addons/fpc/EditorModule.gd create mode 100644 addons/fpc/character.gd create mode 100644 addons/fpc/character.tscn create mode 100644 addons/fpc/debug.gd create mode 100644 addons/fpc/reticles/reticle_0.tscn create mode 100644 addons/fpc/reticles/reticle_1.tscn create mode 100644 icon.svg create mode 100644 icon.svg.import create mode 100644 models/round_room.blend create mode 100644 models/round_room.blend.import create mode 100644 models/round_room.blend1 create mode 100644 models/round_room_Door.res create mode 100644 models/round_room_RoundRoom.res create mode 100644 prefabs/bsp_level_generator.tscn create mode 100644 prefabs/bullet.tscn create mode 100644 prefabs/door.tscn create mode 100644 prefabs/enemy.tscn create mode 100644 prefabs/level_generator.tscn create mode 100644 prefabs/round_room.tscn create mode 100644 prefabs/test_arena.tscn create mode 100644 project.godot create mode 100644 scripts/bsp_level_generator.gd create mode 100644 scripts/bullet.gd create mode 100644 scripts/enemy.gd create mode 100644 scripts/level_generator.gd create mode 100644 scripts/player.gd create mode 100644 scripts/spin_ground.gd create mode 100644 test.tscn create mode 100644 test_world.tscn create mode 100644 textures/dark.png create mode 100644 textures/dark.png.import create mode 100644 textures/green.png create mode 100644 textures/green.png.import create mode 100644 textures/orange.png create mode 100644 textures/orange.png.import create mode 100644 textures/purple.png create mode 100644 textures/purple.png.import create mode 100644 textures/red.png create mode 100644 textures/red.png.import diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f34a2c1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Godot 4+ specific ignores +.godot/ +/android/ + +# Godot-specific ignores +.import/ +export.cfg +export_presets.cfg + +# Imported translations (automatically generated from CSV files) +*.translation + +# Mono-specific ignores +.mono/ +data_*/ +mono_crash.*.json diff --git a/addons/fpc/EditorModule.gd b/addons/fpc/EditorModule.gd new file mode 100644 index 0000000..fa1320b --- /dev/null +++ b/addons/fpc/EditorModule.gd @@ -0,0 +1,49 @@ +@tool +extends Node + +# This does not effect runtime yet but will in the future. + +@export_category("Controller Editor Module") +@export_range(-360.0, 360.0, 0.01, "or_greater", "or_less") var head_y_rotation : float = 0.0: + set(new_rotation): + if HEAD: + head_y_rotation = new_rotation + HEAD.rotation.y = deg_to_rad(head_y_rotation) + update_configuration_warnings() +@export_range(-90.0, 90.0, 0.01, "or_greater", "or_less") var head_x_rotation : float = 0.0: + set(new_rotation): + if HEAD: + head_x_rotation = new_rotation + HEAD.rotation.x = deg_to_rad(head_x_rotation) + update_configuration_warnings() + +@export_group("Nodes") +@export var CHARACTER : CharacterBody3D +@export var head_path : String = "Head" # Relative to the parent node +#@export var CAMERA : Camera3D +#@export var HEADBOB_ANIMATION : AnimationPlayer +#@export var JUMP_ANIMATION : AnimationPlayer +#@export var CROUCH_ANIMATION : AnimationPlayer +#@export var COLLISION_MESH : CollisionShape3D + +@onready var HEAD = get_node("../" + head_path) + + +func _ready(): + if !Engine.is_editor_hint(): + print("not editor") + HEAD.rotation.y = deg_to_rad(head_y_rotation) + HEAD.rotation.x = deg_to_rad(head_x_rotation) + + +func _get_configuration_warnings(): + var warnings = [] + + if head_y_rotation > 360: + warnings.append("The head rotation is greater than 360") + + if head_y_rotation < -360: + warnings.append("The head rotation is less than -360") + + # Returning an empty array gives no warnings + return warnings diff --git a/addons/fpc/character.gd b/addons/fpc/character.gd new file mode 100644 index 0000000..a09c999 --- /dev/null +++ b/addons/fpc/character.gd @@ -0,0 +1,407 @@ + +# COPYRIGHT Colormatic Studios +# MIT licence +# Quality Godot First Person Controller v2 + + +extends CharacterBody3D + + +## The settings for the character's movement and feel. +@export_category("Character") +## The speed that the character moves at without crouching or sprinting. +@export var base_speed : float = 3.0 +## The speed that the character moves at when sprinting. +@export var sprint_speed : float = 6.0 +## The speed that the character moves at when crouching. +@export var crouch_speed : float = 1.0 +## The speed that dapens current velocity +@export var dapen_speed : float = 3.0 + +## How fast the character speeds up and slows down when Motion Smoothing is on. +@export var acceleration : float = 10.0 +## How high the player jumps. +@export var jump_velocity : float = 4.5 +## How far the player turns when the mouse is moved. +@export var mouse_sensitivity : float = 0.1 +## Invert the Y input for mouse and joystick +@export var invert_mouse_y : bool = false # Possibly add an invert mouse X in the future +## Wether the player can use movement inputs. Does not stop outside forces or jumping. See Jumping Enabled. +@export var immobile : bool = false +## The reticle file to import at runtime. By default are in res://addons/fpc/reticles/. Set to an empty string to remove. +@export_file var default_reticle + +@export_group("Nodes") +## The node that holds the camera. This is rotated instead of the camera for mouse input. +@export var HEAD : Node3D +@export var CAMERA : Camera3D +@export var HEADBOB_ANIMATION : AnimationPlayer +@export var JUMP_ANIMATION : AnimationPlayer +@export var CROUCH_ANIMATION : AnimationPlayer +@export var COLLISION_MESH : CollisionShape3D + +@export_group("Controls") +# We are using UI controls because they are built into Godot Engine so they can be used right away +@export var JUMP : String = "ui_accept" +@export var LEFT : String = "ui_left" +@export var RIGHT : String = "ui_right" +@export var FORWARD : String = "ui_up" +@export var BACKWARD : String = "ui_down" +## By default this does not pause the game, but that can be changed in _process. +@export var PAUSE : String = "ui_cancel" +@export var CROUCH : String = "crouch" +@export var SPRINT : String = "sprint" + +# Uncomment if you want controller support +#@export var controller_sensitivity : float = 0.035 +#@export var LOOK_LEFT : String = "look_left" +#@export var LOOK_RIGHT : String = "look_right" +#@export var LOOK_UP : String = "look_up" +#@export var LOOK_DOWN : String = "look_down" + +@export_group("Feature Settings") +## Enable or disable jumping. Useful for restrictive storytelling environments. +@export var jumping_enabled : bool = true +## Wether the player can move in the air or not. +@export var in_air_momentum : bool = true +## Smooths the feel of walking. +@export var motion_smoothing : bool = true +@export var sprint_enabled : bool = true +@export var crouch_enabled : bool = true +@export_enum("Hold to Crouch", "Toggle Crouch") var crouch_mode : int = 0 +@export_enum("Hold to Sprint", "Toggle Sprint") var sprint_mode : int = 0 +## Wether sprinting should effect FOV. +@export var dynamic_fov : bool = true +## If the player holds down the jump button, should the player keep hopping. +@export var continuous_jumping : bool = true +## Enables the view bobbing animation. +@export var view_bobbing : bool = true +## Enables an immersive animation when the player jumps and hits the ground. +@export var jump_animation : bool = true +## This determines wether the player can use the pause button, not wether the game will actually pause. +@export var pausing_enabled : bool = true +## Use with caution. +@export var gravity_enabled : bool = true + + +# Member variables +var speed : float = base_speed +var current_speed : float = 0.0 +# States: normal, crouching, sprinting +var state : String = "normal" +var low_ceiling : bool = false # This is for when the cieling is too low and the player needs to crouch. +var was_on_floor : bool = true # Was the player on the floor last frame (for landing animation) + +# The reticle should always have a Control node as the root +var RETICLE : Control + +# Get the gravity from the project settings to be synced with RigidBody nodes +var gravity : float = ProjectSettings.get_setting("physics/3d/default_gravity") # Don't set this as a const, see the gravity section in _physics_process + +# Stores mouse input for rotating the camera in the phyhsics process +var mouseInput : Vector2 = Vector2(0,0) + +var local_velocity: Vector3 = Vector3(0,0,0) + +func _ready(): + #It is safe to comment this line if your game doesn't start with the mouse captured + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED + + # If the controller is rotated in a certain direction for game design purposes, redirect this rotation into the head. + HEAD.rotation.y = rotation.y + rotation.y = 0 + + if default_reticle: + change_reticle(default_reticle) + + # Reset the camera position + # If you want to change the default head height, change these animations. + HEADBOB_ANIMATION.play("RESET") + JUMP_ANIMATION.play("RESET") + CROUCH_ANIMATION.play("RESET") + + check_controls() + +func check_controls(): # If you add a control, you might want to add a check for it here. + # The actions are being disabled so the engine doesn't halt the entire project in debug mode + if !InputMap.has_action(JUMP): + push_error("No control mapped for jumping. Please add an input map control. Disabling jump.") + jumping_enabled = false + if !InputMap.has_action(LEFT): + push_error("No control mapped for move left. Please add an input map control. Disabling movement.") + immobile = true + if !InputMap.has_action(RIGHT): + push_error("No control mapped for move right. Please add an input map control. Disabling movement.") + immobile = true + if !InputMap.has_action(FORWARD): + push_error("No control mapped for move forward. Please add an input map control. Disabling movement.") + immobile = true + if !InputMap.has_action(BACKWARD): + push_error("No control mapped for move backward. Please add an input map control. Disabling movement.") + immobile = true + if !InputMap.has_action(PAUSE): + push_error("No control mapped for pause. Please add an input map control. Disabling pausing.") + pausing_enabled = false + if !InputMap.has_action(CROUCH): + push_error("No control mapped for crouch. Please add an input map control. Disabling crouching.") + crouch_enabled = false + if !InputMap.has_action(SPRINT): + push_error("No control mapped for sprint. Please add an input map control. Disabling sprinting.") + sprint_enabled = false + + +func change_reticle(reticle): # Yup, this function is kinda strange + if RETICLE: + RETICLE.queue_free() + + RETICLE = load(reticle).instantiate() + RETICLE.character = self + $UserInterface.add_child(RETICLE) + + +func _physics_process(delta): + up_direction = Vector3.UP.rotated(Vector3(0, 0, 1), global_rotation.z) + # Big thanks to github.com/LorenzoAncora for the concept of the improved debug values + current_speed = Vector3.ZERO.distance_to(get_real_velocity()) + $UserInterface/DebugPanel.add_property("Speed", snappedf(current_speed, 0.001), 1) + $UserInterface/DebugPanel.add_property("Target speed", speed, 2) + var cv : Vector3 = get_real_velocity() + var vd : Array[float] = [ + snappedf(cv.x, 0.001), + snappedf(cv.y, 0.001), + snappedf(cv.z, 0.001) + ] + var readable_velocity : String = "X: " + str(vd[0]) + " Y: " + str(vd[1]) + " Z: " + str(vd[2]) + $UserInterface/DebugPanel.add_property("Velocity", readable_velocity, 3) + + # Gravity + #gravity = ProjectSettings.get_setting("physics/3d/default_gravity") # If the gravity changes during your game, uncomment this code + if not is_on_floor() and gravity and gravity_enabled: + #var gravity_vector = Vector3(0, -gravity * delta, 0).rotated(Vector3(0, 0, 1), global_rotation.z) + #velocity += gravity_vector + local_velocity.y -= gravity * delta + + handle_jumping() + + var input_dir = Vector2.ZERO + if !immobile: # Immobility works by interrupting user input, so other forces can still be applied to the player + input_dir = Input.get_vector(LEFT, RIGHT, FORWARD, BACKWARD) + handle_movement(delta, input_dir) + + handle_head_rotation() + + # The player is not able to stand up if the ceiling is too low + low_ceiling = $CrouchCeilingDetection.is_colliding() + + handle_state(input_dir) + if dynamic_fov: # This may be changed to an AnimationPlayer + update_camera_fov() + + if view_bobbing: + headbob_animation(input_dir) + + if jump_animation: + if !was_on_floor and is_on_floor(): # The player just landed + match randi() % 2: #TODO: Change this to detecting velocity direction + 0: + JUMP_ANIMATION.play("land_left", 0.25) + 1: + JUMP_ANIMATION.play("land_right", 0.25) + + was_on_floor = is_on_floor() # This must always be at the end of physics_process + + +func handle_jumping(): + if jumping_enabled: + if continuous_jumping: # Hold down the jump button + if Input.is_action_pressed(JUMP) and is_on_floor() and !low_ceiling: + if jump_animation: + JUMP_ANIMATION.play("jump", 0.25) + local_velocity.y += jump_velocity # Adding instead of setting so jumping on slopes works properly + else: + if Input.is_action_just_pressed(JUMP) and is_on_floor() and !low_ceiling: + if jump_animation: + JUMP_ANIMATION.play("jump", 0.25) + local_velocity.y += jump_velocity + +func handle_movement(delta, input_dir): + var direction = input_dir.rotated(-HEAD.rotation.y) + direction = Vector3(direction.x, 0, direction.y) + var glob_rot = global_transform.basis.get_rotation_quaternion() + velocity = glob_rot * local_velocity + var collided = move_and_slide() + local_velocity = glob_rot.inverse() * velocity + + #print(local_velocity) + if in_air_momentum: + if direction.length_squared() > 0.001: + if motion_smoothing: + local_velocity.x = lerp(local_velocity.x, direction.x * speed, acceleration * delta) + local_velocity.z = lerp(local_velocity.z, direction.z * speed, acceleration * delta) + local_velocity.y = lerp(local_velocity.y, 0.0, dapen_speed * delta) + else: + local_velocity.x = direction.x * speed + local_velocity.z = direction.z * speed + else: + local_velocity += -dapen_speed * delta * local_velocity.normalized(); + else: + if motion_smoothing: + local_velocity.x = lerp(local_velocity.x, direction.x * speed, acceleration * delta) + local_velocity.z = lerp(local_velocity.z, direction.z * speed, acceleration * delta) + else: + local_velocity.x = direction.x * speed + local_velocity.z = direction.z * speed + +func handle_head_rotation(): + HEAD.rotation_degrees.y -= mouseInput.x * mouse_sensitivity + if invert_mouse_y: + HEAD.rotation_degrees.x -= mouseInput.y * mouse_sensitivity * -1.0 + else: + HEAD.rotation_degrees.x -= mouseInput.y * mouse_sensitivity + + # Uncomment for controller support + #var controller_view_rotation = Input.get_vector(LOOK_DOWN, LOOK_UP, LOOK_RIGHT, LOOK_LEFT) * controller_sensitivity # These are inverted because of the nature of 3D rotation. + #HEAD.rotation.x += controller_view_rotation.x + #if invert_mouse_y: + #HEAD.rotation.y += controller_view_rotation.y * -1.0 + #else: + #HEAD.rotation.y += controller_view_rotation.y + + + mouseInput = Vector2(0,0) + HEAD.rotation.x = clamp(HEAD.rotation.x, deg_to_rad(-90), deg_to_rad(90)) + + +func handle_state(moving): + if sprint_enabled: + if sprint_mode == 0: + if Input.is_action_pressed(SPRINT) and state != "crouching": + if moving: + if state != "sprinting": + enter_sprint_state() + else: + if state == "sprinting": + enter_normal_state() + elif state == "sprinting": + enter_normal_state() + elif sprint_mode == 1: + if moving: + # If the player is holding sprint before moving, handle that cenerio + if Input.is_action_pressed(SPRINT) and state == "normal": + enter_sprint_state() + if Input.is_action_just_pressed(SPRINT): + match state: + "normal": + enter_sprint_state() + "sprinting": + enter_normal_state() + elif state == "sprinting": + enter_normal_state() + + if crouch_enabled: + if crouch_mode == 0: + if Input.is_action_pressed(CROUCH) and state != "sprinting": + if state != "crouching": + enter_crouch_state() + elif state == "crouching" and !$CrouchCeilingDetection.is_colliding(): + enter_normal_state() + elif crouch_mode == 1: + if Input.is_action_just_pressed(CROUCH): + match state: + "normal": + enter_crouch_state() + "crouching": + if !$CrouchCeilingDetection.is_colliding(): + enter_normal_state() + + +# Any enter state function should only be called once when you want to enter that state, not every frame. + +func enter_normal_state(): + #print("entering normal state") + var prev_state = state + if prev_state == "crouching": + CROUCH_ANIMATION.play_backwards("crouch") + state = "normal" + speed = base_speed + +func enter_crouch_state(): + #print("entering crouch state") + var prev_state = state + state = "crouching" + speed = crouch_speed + CROUCH_ANIMATION.play("crouch") + +func enter_sprint_state(): + #print("entering sprint state") + var prev_state = state + if prev_state == "crouching": + CROUCH_ANIMATION.play_backwards("crouch") + state = "sprinting" + speed = sprint_speed + + +func update_camera_fov(): + if state == "sprinting": + CAMERA.fov = lerp(CAMERA.fov, 85.0, 0.3) + else: + CAMERA.fov = lerp(CAMERA.fov, 75.0, 0.3) + + +func headbob_animation(moving): + if moving and is_on_floor(): + var use_headbob_animation : String + match state: + "normal","crouching": + use_headbob_animation = "walk" + "sprinting": + use_headbob_animation = "sprint" + + var was_playing : bool = false + if HEADBOB_ANIMATION.current_animation == use_headbob_animation: + was_playing = true + + HEADBOB_ANIMATION.play(use_headbob_animation, 0.25) + HEADBOB_ANIMATION.speed_scale = (current_speed / base_speed) * 1.75 + if !was_playing: + HEADBOB_ANIMATION.seek(float(randi() % 2)) # Randomize the initial headbob direction + # Let me explain that piece of code because it looks like it does the opposite of what it actually does. + # The headbob animation has two starting positions. One is at 0 and the other is at 1. + # randi() % 2 returns either 0 or 1, and so the animation randomly starts at one of the starting positions. + # This code is extremely performant but it makes no sense. + + else: + if HEADBOB_ANIMATION.current_animation == "sprint" or HEADBOB_ANIMATION.current_animation == "walk": + HEADBOB_ANIMATION.speed_scale = 1 + HEADBOB_ANIMATION.play("RESET", 1) + + +func _process(delta): + $UserInterface/DebugPanel.add_property("FPS", Performance.get_monitor(Performance.TIME_FPS), 0) + var status : String = state + if !is_on_floor(): + status += " in the air" + $UserInterface/DebugPanel.add_property("State", status, 4) + + if pausing_enabled: + if Input.is_action_just_pressed(PAUSE): + # You may want another node to handle pausing, because this player may get paused too. + match Input.mouse_mode: + Input.MOUSE_MODE_CAPTURED: + Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + #get_tree().paused = false + Input.MOUSE_MODE_VISIBLE: + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED + #get_tree().paused = false + + +func _unhandled_input(event : InputEvent): + if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: + mouseInput.x += event.relative.x + mouseInput.y += event.relative.y + # Toggle debug menu + elif event is InputEventKey: + if event.is_released(): + # Where we're going, we don't need InputMap + if event.keycode == 4194338: # F7 + $UserInterface/DebugPanel.visible = !$UserInterface/DebugPanel.visible diff --git a/addons/fpc/character.tscn b/addons/fpc/character.tscn new file mode 100644 index 0000000..a43e940 --- /dev/null +++ b/addons/fpc/character.tscn @@ -0,0 +1,425 @@ +[gd_scene load_steps=21 format=3 uid="uid://cc1m2a1obsyn4"] + +[ext_resource type="Script" path="res://addons/fpc/character.gd" id="1_0t4e8"] +[ext_resource type="Script" path="res://addons/fpc/EditorModule.gd" id="3_v3ckk"] +[ext_resource type="Script" path="res://addons/fpc/debug.gd" id="3_x1wcc"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_kp17n"] +albedo_color = Color(0.909804, 0.596078, 0, 1) +clearcoat_enabled = true +clearcoat_roughness = 0.2 + +[sub_resource type="CapsuleMesh" id="CapsuleMesh_jw1de"] +material = SubResource("StandardMaterial3D_kp17n") + +[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_uy03j"] + +[sub_resource type="Animation" id="Animation_j8cx7"] +resource_name = "RESET" +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Mesh:scale") +tracks/0/interp = 2 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(1, 1, 1)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Collision:scale") +tracks/1/interp = 2 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(1, 1, 1)] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Mesh:position") +tracks/2/interp = 2 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 1, 0)] +} +tracks/3/type = "value" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath("Collision:position") +tracks/3/interp = 2 +tracks/3/loop_wrap = true +tracks/3/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 1, 0)] +} +tracks/4/type = "value" +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/path = NodePath("Head:position") +tracks/4/interp = 2 +tracks/4/loop_wrap = true +tracks/4/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 1.5, 0)] +} + +[sub_resource type="Animation" id="Animation_5ec5e"] +resource_name = "crouch" +length = 0.2 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Mesh:scale") +tracks/0/interp = 2 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.2), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector3(1, 1, 1), Vector3(1, 0.75, 1)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Collision:scale") +tracks/1/interp = 2 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 0.2), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector3(1, 1, 1), Vector3(1, 0.75, 1)] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Mesh:position") +tracks/2/interp = 2 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 0.2), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector3(0, 1, 0), Vector3(0, 0.75, 0)] +} +tracks/3/type = "value" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath("Collision:position") +tracks/3/interp = 2 +tracks/3/loop_wrap = true +tracks/3/keys = { +"times": PackedFloat32Array(0, 0.2), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector3(0, 1, 0), Vector3(0, 0.75, 0)] +} +tracks/4/type = "value" +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/path = NodePath("Head:position") +tracks/4/interp = 2 +tracks/4/loop_wrap = true +tracks/4/keys = { +"times": PackedFloat32Array(0, 0.2), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector3(0, 1.5, 0), Vector3(0, 1.12508, 0)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_5e5t5"] +_data = { +"RESET": SubResource("Animation_j8cx7"), +"crouch": SubResource("Animation_5ec5e") +} + +[sub_resource type="Animation" id="Animation_gh776"] +resource_name = "RESET" +length = 0.001 +loop_mode = 1 +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Camera:position:x") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} +tracks/1/type = "bezier" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Camera:position:y") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} + +[sub_resource type="Animation" id="Animation_8ku67"] +resource_name = "sprint" +length = 2.0 +loop_mode = 1 +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Camera:position:x") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0, 1, 0, 1, 0), +"points": PackedFloat32Array(0.06, -0.25, 0, 0.25, -0.01, 0, 0, 0, 0, 0, -0.06, -0.25, 0.01, 0.25, 0.01, 0, 0, 0, 0, 0, 0.06, -0.25, -0.01, 0.25, 0), +"times": PackedFloat32Array(0, 0.5, 1, 1.5, 2) +} +tracks/1/type = "bezier" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Camera:position:y") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"handle_modes": PackedInt32Array(0, 0, 0, 0, 0), +"points": PackedFloat32Array(0.05, -0.25, 0, 0.2, -0.01, 0, -0.2, 0.000186046, 0.2, 0.000186046, 0.05, -0.2, -0.01, 0.2, -0.01, 0, -0.2, 0, 0.2, 0, 0.05, -0.2, -0.01, 0.25, 0), +"times": PackedFloat32Array(0, 0.5, 1, 1.5, 2) +} + +[sub_resource type="Animation" id="Animation_lrqmv"] +resource_name = "walk" +length = 2.0 +loop_mode = 1 +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Camera:position:x") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0, 1, 0, 1, 0), +"points": PackedFloat32Array(0.04, -0.25, 0, 0.25, 0, 0, 0, 0, 0, 0, -0.04, -0.25, 0, 0.25, 0, 0, 0, 0, 0, 0, 0.04, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0, 0.5, 1, 1.5, 2) +} +tracks/1/type = "bezier" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Camera:position:y") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"handle_modes": PackedInt32Array(0, 0, 0, 0, 0), +"points": PackedFloat32Array(-0.05, -0.25, 0, 0.2, 0.005, 0, -0.2, 0.000186046, 0.2, 0.000186046, -0.05, -0.2, 0.005, 0.2, 0.005, 0, -0.2, 0, 0.2, 0, -0.05, -0.2, 0.005, 0.25, 0), +"times": PackedFloat32Array(0, 0.5, 1, 1.5, 2) +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_o0unb"] +_data = { +"RESET": SubResource("Animation_gh776"), +"sprint": SubResource("Animation_8ku67"), +"walk": SubResource("Animation_lrqmv") +} + +[sub_resource type="Animation" id="Animation_fvvjq"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Camera:rotation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 0, 0)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Camera:position") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 0, 0)] +} + +[sub_resource type="Animation" id="Animation_s07ye"] +resource_name = "jump" +length = 3.0 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Camera:rotation") +tracks/0/interp = 2 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.6, 3), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [Vector3(0, 0, 0), Vector3(0.0349066, 0, 0), Vector3(0, 0, 0)] +} + +[sub_resource type="Animation" id="Animation_l1rph"] +resource_name = "land_left" +length = 1.5 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Camera:rotation") +tracks/0/interp = 2 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.5, 1.5), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [Vector3(0, 0, 0), Vector3(-0.0349066, 0, 0.0174533), Vector3(0, 0, 0)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Camera:position") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 0.5, 1.5), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [Vector3(0, 0, 0), Vector3(0, -0.1, 0), Vector3(0, 0, 0)] +} + +[sub_resource type="Animation" id="Animation_vsknp"] +resource_name = "land_right" +length = 1.5 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Camera:rotation") +tracks/0/interp = 2 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.5, 1.5), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [Vector3(0, 0, 0), Vector3(-0.0349066, 0, -0.0174533), Vector3(0, 0, 0)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Camera:position") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 0.5, 1.5), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [Vector3(0, 0, 0), Vector3(0, -0.1, 0), Vector3(0, 0, 0)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_qeg5r"] +_data = { +"RESET": SubResource("Animation_fvvjq"), +"jump": SubResource("Animation_s07ye"), +"land_left": SubResource("Animation_l1rph"), +"land_right": SubResource("Animation_vsknp") +} + +[sub_resource type="Theme" id="Theme_wdf0f"] +MarginContainer/constants/margin_bottom = 10 +MarginContainer/constants/margin_left = 10 +MarginContainer/constants/margin_right = 10 +MarginContainer/constants/margin_top = 10 + +[sub_resource type="SphereShape3D" id="SphereShape3D_k4wwl"] + +[node name="Character" type="CharacterBody3D" node_paths=PackedStringArray("HEAD", "CAMERA", "HEADBOB_ANIMATION", "JUMP_ANIMATION", "CROUCH_ANIMATION", "COLLISION_MESH")] +script = ExtResource("1_0t4e8") +default_reticle = "res://addons/fpc/reticles/reticle_1.tscn" +HEAD = NodePath("Head") +CAMERA = NodePath("Head/Camera") +HEADBOB_ANIMATION = NodePath("Head/HeadbobAnimation") +JUMP_ANIMATION = NodePath("Head/JumpAnimation") +CROUCH_ANIMATION = NodePath("CrouchAnimation") +COLLISION_MESH = NodePath("Collision") + +[node name="Mesh" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) +mesh = SubResource("CapsuleMesh_jw1de") + +[node name="Collision" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) +shape = SubResource("CapsuleShape3D_uy03j") + +[node name="CrouchAnimation" type="AnimationPlayer" parent="."] +libraries = { +"": SubResource("AnimationLibrary_5e5t5") +} + +[node name="Head" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0) + +[node name="Camera" type="Camera3D" parent="Head"] + +[node name="HeadbobAnimation" type="AnimationPlayer" parent="Head"] +libraries = { +"": SubResource("AnimationLibrary_o0unb") +} +blend_times = [&"RESET", &"RESET", 0.5, &"RESET", &"walk", 0.5, &"walk", &"RESET", 0.5] + +[node name="JumpAnimation" type="AnimationPlayer" parent="Head"] +libraries = { +"": SubResource("AnimationLibrary_qeg5r") +} +speed_scale = 4.0 + +[node name="UserInterface" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 1 + +[node name="DebugPanel" type="PanelContainer" parent="UserInterface"] +visible = false +layout_mode = 0 +offset_left = 10.0 +offset_top = 10.0 +offset_right = 453.0 +offset_bottom = 50.0 +theme = SubResource("Theme_wdf0f") +script = ExtResource("3_x1wcc") + +[node name="MarginContainer" type="MarginContainer" parent="UserInterface/DebugPanel"] +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="UserInterface/DebugPanel/MarginContainer"] +layout_mode = 2 + +[node name="CrouchCeilingDetection" type="ShapeCast3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) +shape = SubResource("SphereShape3D_k4wwl") +target_position = Vector3(0, 0.5, 0) + +[node name="EditorModule" type="Node" parent="."] +script = ExtResource("3_v3ckk") diff --git a/addons/fpc/debug.gd b/addons/fpc/debug.gd new file mode 100644 index 0000000..efdb7a4 --- /dev/null +++ b/addons/fpc/debug.gd @@ -0,0 +1,18 @@ +extends PanelContainer + + +func _process(delta): + if visible: + pass + +func add_property(title : String, value, order : int): # This can either be called once for a static property or called every frame for a dynamic property + var target + target = $MarginContainer/VBoxContainer.find_child(title, true, false) # I have no idea what true and false does here, the function should be more specific + if !target: + target = Label.new() # Debug lines are of type Label + $MarginContainer/VBoxContainer.add_child(target) + target.name = title + target.text = title + ": " + str(value) + elif visible: + target.text = title + ": " + str(value) + $MarginContainer/VBoxContainer.move_child(target, order) diff --git a/addons/fpc/reticles/reticle_0.tscn b/addons/fpc/reticles/reticle_0.tscn new file mode 100644 index 0000000..2828124 --- /dev/null +++ b/addons/fpc/reticles/reticle_0.tscn @@ -0,0 +1,37 @@ +[gd_scene load_steps=2 format=3 uid="uid://coqpusufa8a6k"] + +[sub_resource type="GDScript" id="GDScript_10f85"] +script/source = "extends CenterContainer + + +@export_category(\"Reticle\") +@export_group(\"Nodes\") +@export var character : CharacterBody3D + +@export_group(\"Settings\") +@export var dot_size : int = 1 +@export var dot_color : Color = Color.WHITE + + +func _process(_delta): + if visible: # If the reticle is disabled (not visible), don't bother updating it + update_reticle_settings() + +func update_reticle_settings(): + $dot.scale.x = dot_size + $dot.scale.y = dot_size + $dot.color = dot_color +" + +[node name="Reticle" type="CenterContainer"] +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +grow_horizontal = 2 +grow_vertical = 2 +script = SubResource("GDScript_10f85") + +[node name="dot" type="Polygon2D" parent="."] +polygon = PackedVector2Array(-1, -1, 1, -1, 1, 1, -1, 1) diff --git a/addons/fpc/reticles/reticle_1.tscn b/addons/fpc/reticles/reticle_1.tscn new file mode 100644 index 0000000..bb83b83 --- /dev/null +++ b/addons/fpc/reticles/reticle_1.tscn @@ -0,0 +1,104 @@ +[gd_scene load_steps=2 format=3 uid="uid://3mij3cjhkwsm"] + +[sub_resource type="GDScript" id="GDScript_a8kpl"] +script/source = "extends CenterContainer + + +@export_category(\"Reticle\") +@export_group(\"Nodes\") +@export var reticle_lines : Array[Line2D] +@export var character : CharacterBody3D + +@export_group(\"Animate\") +@export var animated_reticle : bool = true +@export var reticle_speed : float = 0.5 +@export var reticle_spread : float = 4.0 + +@export_group(\"Dot Settings\") +@export var dot_size : int = 1 +@export var dot_color : Color = Color.WHITE + +@export_group(\"Line Settings\") +@export var line_color : Color = Color.WHITE +@export var line_width : int = 2 +@export var line_length : int = 10 +@export var line_distance : int = 5 +@export_enum(\"None\", \"Round\") var cap_mode : int = 0 + + +func _process(_delta): + if visible: # If the reticle is disabled (not visible), don't bother updating it + update_reticle_settings() + if animated_reticle: + animate_reticle_lines() + + +func animate_reticle_lines(): + var vel = character.get_real_velocity() + var origin = Vector3(0,0,0) + var pos = Vector2(0,0) + var speed = origin.distance_to(vel) + + reticle_lines[0].position = lerp(reticle_lines[0].position, pos + Vector2(0, -speed * reticle_spread), reticle_speed) + reticle_lines[1].position = lerp(reticle_lines[1].position, pos + Vector2(-speed * reticle_spread, 0), reticle_speed) + reticle_lines[2].position = lerp(reticle_lines[2].position, pos + Vector2(speed * reticle_spread, 0), reticle_speed) + reticle_lines[3].position = lerp(reticle_lines[3].position, pos + Vector2(0, speed * reticle_spread), reticle_speed) + + +func update_reticle_settings(): + # Dot + $dot.scale.x = dot_size + $dot.scale.y = dot_size + $dot.color = dot_color + + # Lines + for line in reticle_lines: + line.default_color = line_color + line.width = line_width + if cap_mode == 0: + line.begin_cap_mode = Line2D.LINE_CAP_NONE + line.end_cap_mode = Line2D.LINE_CAP_NONE + elif cap_mode == 1: + line.begin_cap_mode = Line2D.LINE_CAP_ROUND + line.end_cap_mode = Line2D.LINE_CAP_ROUND + + # Please someone find a better way to do this + reticle_lines[0].points[0].y = -line_distance + reticle_lines[0].points[1].y = -line_length - line_distance + reticle_lines[1].points[0].x = -line_distance + reticle_lines[1].points[1].x = -line_length - line_distance + reticle_lines[2].points[0].x = line_distance + reticle_lines[2].points[1].x = line_length + line_distance + reticle_lines[3].points[0].y = line_distance + reticle_lines[3].points[1].y = line_length + line_distance +" + +[node name="Reticle" type="CenterContainer" node_paths=PackedStringArray("reticle_lines")] +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +grow_horizontal = 2 +grow_vertical = 2 +script = SubResource("GDScript_a8kpl") +reticle_lines = [NodePath("top"), NodePath("left"), NodePath("right"), NodePath("bottom")] + +[node name="dot" type="Polygon2D" parent="."] +polygon = PackedVector2Array(-1, -1, 1, -1, 1, 1, -1, 1) + +[node name="top" type="Line2D" parent="."] +points = PackedVector2Array(0, -5, 0, -15) +width = 2.0 + +[node name="left" type="Line2D" parent="."] +points = PackedVector2Array(-5, 0, -15, 0) +width = 2.0 + +[node name="right" type="Line2D" parent="."] +points = PackedVector2Array(5, 0, 15, 0) +width = 2.0 + +[node name="bottom" type="Line2D" parent="."] +points = PackedVector2Array(0, 5, 0, 15) +width = 2.0 diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..9d8b7fa --- /dev/null +++ b/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon.svg.import b/icon.svg.import new file mode 100644 index 0000000..7e0ff20 --- /dev/null +++ b/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://1l588sis1kjo" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/models/round_room.blend b/models/round_room.blend new file mode 100644 index 0000000..3012aad Binary files /dev/null and b/models/round_room.blend differ diff --git a/models/round_room.blend.import b/models/round_room.blend.import new file mode 100644 index 0000000..619bdcd --- /dev/null +++ b/models/round_room.blend.import @@ -0,0 +1,72 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://b45rhi68gaw0r" +path="res://.godot/imported/round_room.blend-32f220a608468c77b0da4f4e3d6b019c.scn" + +[deps] + +source_file="res://models/round_room.blend" +dest_files=["res://.godot/imported/round_room.blend-32f220a608468c77b0da4f4e3d6b019c.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +_subresources={ +"meshes": { +"round_room_Door": { +"generate/lightmap_uv": 0, +"generate/lods": 0, +"generate/shadow_meshes": 0, +"lods/normal_merge_angle": 60.0, +"lods/normal_split_angle": 25.0, +"save_to_file/enabled": true, +"save_to_file/path": "res://models/round_room_Door.res" +}, +"round_room_RoundRoom": { +"generate/lightmap_uv": 0, +"generate/lods": 0, +"generate/shadow_meshes": 0, +"lods/normal_merge_angle": 60.0, +"lods/normal_split_angle": 25.0, +"save_to_file/enabled": true, +"save_to_file/path": "res://models/round_room_RoundRoom.res" +} +} +} +blender/nodes/visible=0 +blender/nodes/active_collection_only=false +blender/nodes/punctual_lights=true +blender/nodes/cameras=true +blender/nodes/custom_properties=true +blender/nodes/modifiers=1 +blender/meshes/colors=false +blender/meshes/uvs=true +blender/meshes/normals=true +blender/meshes/tangents=true +blender/meshes/skins=2 +blender/meshes/export_bones_deforming_mesh_only=false +blender/materials/unpack_enabled=true +blender/materials/export_materials=1 +blender/animation/limit_playback=true +blender/animation/always_sample=true +blender/animation/group_tracks=true diff --git a/models/round_room.blend1 b/models/round_room.blend1 new file mode 100644 index 0000000..2b3aded Binary files /dev/null and b/models/round_room.blend1 differ diff --git a/models/round_room_Door.res b/models/round_room_Door.res new file mode 100644 index 0000000..4710c77 Binary files /dev/null and b/models/round_room_Door.res differ diff --git a/models/round_room_RoundRoom.res b/models/round_room_RoundRoom.res new file mode 100644 index 0000000..952b1e4 Binary files /dev/null and b/models/round_room_RoundRoom.res differ diff --git a/prefabs/bsp_level_generator.tscn b/prefabs/bsp_level_generator.tscn new file mode 100644 index 0000000..9b3c198 --- /dev/null +++ b/prefabs/bsp_level_generator.tscn @@ -0,0 +1,8 @@ +[gd_scene load_steps=2 format=3 uid="uid://w7hxcvuvud"] + +[ext_resource type="Script" path="res://scripts/bsp_level_generator.gd" id="1_6jn1x"] + +[node name="BspLevelGenerator" type="Node2D"] +script = ExtResource("1_6jn1x") + +[node name="Camera2D" type="Camera2D" parent="."] diff --git a/prefabs/bullet.tscn b/prefabs/bullet.tscn new file mode 100644 index 0000000..db6cf54 --- /dev/null +++ b/prefabs/bullet.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=4 format=3 uid="uid://cmhycifu5uwoc"] + +[ext_resource type="Script" path="res://scripts/bullet.gd" id="1_3dasu"] + +[sub_resource type="BoxMesh" id="BoxMesh_bp3aw"] +size = Vector3(0.05, 0.05, 1) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_c2hx3"] +shading_mode = 0 +albedo_color = Color(0, 1, 0, 1) + +[node name="Bullet" type="Node3D"] +script = ExtResource("1_3dasu") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("BoxMesh_bp3aw") +surface_material_override/0 = SubResource("StandardMaterial3D_c2hx3") diff --git a/prefabs/door.tscn b/prefabs/door.tscn new file mode 100644 index 0000000..bfe3abe --- /dev/null +++ b/prefabs/door.tscn @@ -0,0 +1,16 @@ +[gd_scene load_steps=3 format=3 uid="uid://lq1udyctjxaj"] + +[ext_resource type="ArrayMesh" uid="uid://wwps1q5d5bo8" path="res://models/round_room_Door.res" id="1_f3lgx"] + +[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_r75os"] +data = PackedVector3Array(-0.5167, 1.2472, -7, -1.2472, -0.5167, -7, -1.2472, 0.5166, -7, -1.2472, -0.5167, -7, 0.5166, -1.2472, -7, -0.5167, -1.2472, -7, 0.5166, -1.2472, -7, 1.2472, 0.5166, -7, 1.2472, -0.5167, -7, 1.2472, 0.5166, -7, -0.5167, 1.2472, -7, 0.5166, 1.2472, -7, -0.5167, 1.2472, -7, 0.5166, -1.2472, -7, -1.2472, -0.5167, -7, 0.5166, -1.2472, -7, -0.5167, 1.2472, -7, 1.2472, 0.5166, -7) + +[node name="Door" type="Node3D"] + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = ExtResource("1_f3lgx") + +[node name="StaticBody3D" type="StaticBody3D" parent="MeshInstance3D"] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/StaticBody3D"] +shape = SubResource("ConcavePolygonShape3D_r75os") diff --git a/prefabs/enemy.tscn b/prefabs/enemy.tscn new file mode 100644 index 0000000..9ed692e --- /dev/null +++ b/prefabs/enemy.tscn @@ -0,0 +1,29 @@ +[gd_scene load_steps=5 format=3 uid="uid://cuad3khwmhnsa"] + +[ext_resource type="Script" path="res://scripts/enemy.gd" id="1_aut2k"] + +[sub_resource type="CapsuleMesh" id="CapsuleMesh_xh601"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_7r0x4"] + +[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_s5qw4"] + +[node name="Enemy" type="CharacterBody3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.54414, -1.58742) +motion_mode = 1 +wall_min_slide_angle = 0.0872665 +script = ExtResource("1_aut2k") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) +mesh = SubResource("CapsuleMesh_xh601") +surface_material_override/0 = SubResource("StandardMaterial3D_7r0x4") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) +shape = SubResource("CapsuleShape3D_s5qw4") + +[node name="HitTimer" type="Timer" parent="."] +wait_time = 0.2 + +[connection signal="timeout" from="HitTimer" to="." method="_on_hit_timer_timeout"] diff --git a/prefabs/level_generator.tscn b/prefabs/level_generator.tscn new file mode 100644 index 0000000..73924f6 --- /dev/null +++ b/prefabs/level_generator.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://dcu5otkh0t1pg"] + +[ext_resource type="Script" path="res://scripts/level_generator.gd" id="1_nqcyo"] + +[node name="LevelGenerator" type="Node3D"] +script = ExtResource("1_nqcyo") diff --git a/prefabs/round_room.tscn b/prefabs/round_room.tscn new file mode 100644 index 0000000..4601f05 --- /dev/null +++ b/prefabs/round_room.tscn @@ -0,0 +1,16 @@ +[gd_scene load_steps=3 format=3 uid="uid://bps2lettms1up"] + +[ext_resource type="ArrayMesh" uid="uid://bemri7myupqwc" path="res://models/round_room_RoundRoom.res" id="1_8mdb7"] + +[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_wurhb"] +data = PackedVector3Array(-1.9134, 1.5, -5, -0.5166, 1.2472, -5, -1.2472, 0.5166, -5, 4.9995, 1.5, -1.9132, 1.9134, -1.5, -5, 1.9134, 1.5, -5, 4.9995, 1.5, -1.9132, 4.9995, -1.5, -1.9132, 1.9134, -1.5, -5, 1.9134, 1.5, 5, 4.9995, -1.5, 1.9136, 4.9995, 1.5, 1.9136, 1.9134, 1.5, 5, 1.9134, -1.5, 5, 4.9995, -1.5, 1.9136, 0.5166, 1.2472, 5, 1.2472, 0.5166, 5, 1.9134, 1.5, 5, -1.9134, -1.5, 5, -5, 1.5, 1.9134, -5, -1.5, 1.9134, -1.9134, -1.5, 5, -1.9134, 1.5, 5, -5, 1.5, 1.9134, 4.9995, 1.5, 1.9136, -1.9134, 1.5, 5, 1.9134, 1.5, 5, -1.9134, 1.5, 5, -5, 1.5, -1.9134, -5, 1.5, 1.9134, -5, 1.5, -1.9134, 1.9134, 1.5, -5, -1.9134, 1.5, -5, 1.9134, 1.5, -5, 4.9995, 1.5, 1.9136, 4.9995, 1.5, -1.9132, 4.9995, 1.5, 1.9136, -5, 1.5, -1.9134, -1.9134, 1.5, 5, -5, 1.5, -1.9134, 4.9995, 1.5, 1.9136, 1.9134, 1.5, -5, -5, 1.5, 1.9134, -5, 1.2472, -0.5166, -5, 1.2472, 0.5166, -5, 1.5, 1.9134, -5, 1.5, -1.9134, -5, 1.2472, -0.5166, -5, -1.5, -1.9134, -1.9134, 1.5, -5, -1.9134, -1.5, -5, -5, -1.5, -1.9134, -5, 1.5, -1.9134, -1.9134, 1.5, -5, 4.9995, -1.5, -1.9132, -1.9134, -1.5, -5, 1.9134, -1.5, -5, -1.9134, -1.5, -5, -5, -1.5, 1.9134, -5, -1.5, -1.9134, -5, -1.5, 1.9134, 1.9134, -1.5, 5, -1.9134, -1.5, 5, 1.9134, -1.5, 5, 4.9995, -1.5, -1.9132, 4.9995, -1.5, 1.9136, 4.9995, -1.5, -1.9132, -5, -1.5, 1.9134, -1.9134, -1.5, -5, -5, -1.5, 1.9134, 4.9995, -1.5, -1.9132, 1.9134, -1.5, 5, 5.0003, 0.5166, -1.2473, 7, -0.5166, -1.2472, 5.0003, -0.5166, -1.2473, 5.0003, 0.5166, -1.2473, 7, 0.5166, -1.2472, 7, -0.5166, -1.2472, 5.0003, -0.5166, -1.2473, 7, -1.2472, -0.5166, 5.0003, -1.2472, -0.5167, 5.0003, -0.5166, -1.2473, 7, -0.5166, -1.2472, 7, -1.2472, -0.5166, 5.0003, -1.2472, -0.5167, 7, -1.2472, 0.5166, 5.0003, -1.2472, 0.5165, 5.0003, -1.2472, -0.5167, 7, -1.2472, -0.5166, 7, -1.2472, 0.5166, 5.0003, -1.2472, 0.5165, 7, -0.5166, 1.2472, 5.0003, -0.5166, 1.2471, 5.0003, -1.2472, 0.5165, 7, -1.2472, 0.5166, 7, -0.5166, 1.2472, 5.0003, 0.5166, 1.2471, 7, -0.5166, 1.2472, 7, 0.5166, 1.2472, 5.0003, 0.5166, 1.2471, 5.0003, -0.5166, 1.2471, 7, -0.5166, 1.2472, 5.0003, 1.2472, 0.5165, 7, 0.5166, 1.2472, 7, 1.2472, 0.5166, 5.0003, 1.2472, 0.5165, 5.0003, 0.5166, 1.2471, 7, 0.5166, 1.2472, 5.0003, 1.2472, -0.5167, 7, 1.2472, 0.5166, 7, 1.2472, -0.5166, 5.0003, 1.2472, -0.5167, 5.0003, 1.2472, 0.5165, 7, 1.2472, 0.5166, 5.0003, 1.2472, -0.5167, 7, 0.5166, -1.2472, 5.0003, 0.5166, -1.2473, 5.0003, 1.2472, -0.5167, 7, 1.2472, -0.5166, 7, 0.5166, -1.2472, 4.9995, 1.5, -1.9132, 5.0003, 1.2472, -0.5167, 5.0003, 0.5166, -1.2473, 4.9995, 1.5, -1.9132, 5.0003, 1.2472, 0.5165, 5.0003, 1.2472, -0.5167, 4.9995, 1.5, -1.9132, 4.9995, 1.5, 1.9136, 5.0003, 1.2472, 0.5165, 5.0003, 1.2472, 0.5165, 4.9995, 1.5, 1.9136, 5.0003, 0.5166, 1.2471, 4.9995, 1.5, 1.9136, 5.0003, -0.5166, 1.2471, 5.0003, 0.5166, 1.2471, 4.9995, 1.5, 1.9136, 4.9995, -1.5, 1.9136, 5.0003, -0.5166, 1.2471, 5.0003, -0.5166, 1.2471, 4.9995, -1.5, 1.9136, 5.0003, -1.2472, 0.5165, 4.9995, -1.5, 1.9136, 5.0003, -1.2472, -0.5167, 5.0003, -1.2472, 0.5165, 4.9995, -1.5, 1.9136, 4.9995, -1.5, -1.9132, 5.0003, -1.2472, -0.5167, 5.0003, -1.2472, -0.5167, 4.9995, -1.5, -1.9132, 5.0003, -0.5166, -1.2473, 4.9995, -1.5, -1.9132, 5.0003, 0.5166, -1.2473, 5.0003, -0.5166, -1.2473, 4.9995, -1.5, -1.9132, 4.9995, 1.5, -1.9132, 5.0003, 0.5166, -1.2473, -7, 0.5166, -1.2472, -5, -0.5166, -1.2472, -7, -0.5166, -1.2472, -7, 0.5166, -1.2472, -5, 0.5166, -1.2472, -5, -0.5166, -1.2472, -7, -0.5166, -1.2472, -5, -1.2472, -0.5166, -7, -1.2472, -0.5166, -7, -0.5166, -1.2472, -5, -0.5166, -1.2472, -5, -1.2472, -0.5166, -7, -1.2472, -0.5166, -5, -1.2472, 0.5166, -7, -1.2472, 0.5166, -7, -1.2472, -0.5166, -5, -1.2472, -0.5166, -5, -1.2472, 0.5166, -7, -1.2472, 0.5166, -5, -0.5166, 1.2472, -7, -0.5166, 1.2472, -7, -1.2472, 0.5166, -5, -1.2472, 0.5166, -5, -0.5166, 1.2472, -7, 0.5166, 1.2472, -5, -0.5166, 1.2472, -5, 0.5166, 1.2472, -7, 0.5166, 1.2472, -7, -0.5166, 1.2472, -5, -0.5166, 1.2472, -7, 1.2472, 0.5166, -5, 0.5166, 1.2472, -5, 1.2472, 0.5166, -7, 1.2472, 0.5166, -7, 0.5166, 1.2472, -5, 0.5166, 1.2472, -5, 1.2472, 0.5166, -5, 0.5166, 1.2472, -5, 1.5, 1.9134, -7, 1.2472, -0.5166, -5, 1.2472, 0.5166, -5, 1.2472, -0.5166, -7, 1.2472, -0.5166, -7, 1.2472, 0.5166, -5, 1.2472, 0.5166, -7, 1.2472, -0.5166, -5, 0.5166, -1.2472, -7, 0.5166, -1.2472, -7, 1.2472, -0.5166, -5, 1.2472, -0.5166, -5, 0.5166, -1.2472, -5, 1.2472, -0.5166, -5, 1.5, -1.9134, -5, 0.5166, -1.2472, -5, 1.5, -1.9134, -5, -0.5166, -1.2472, -5, 0.5166, -1.2472, -5, 1.5, -1.9134, -5, -1.5, -1.9134, -5, -0.5166, -1.2472, -5, -0.5166, -1.2472, -5, -1.5, -1.9134, -5, -1.2472, -0.5166, -5, -1.5, -1.9134, -5, -1.2472, 0.5166, -5, -1.2472, -0.5166, -5, -1.5, -1.9134, -5, -1.5, 1.9134, -5, -1.2472, 0.5166, -5, -1.2472, 0.5166, -5, -1.5, 1.9134, -5, -0.5166, 1.2472, -5, -1.5, 1.9134, -5, 0.5166, 1.2472, -5, -0.5166, 1.2472, -5, -1.5, 1.9134, -5, 1.5, 1.9134, -5, 0.5166, 1.2472, -1.2472, 0.5166, -5, -1.2472, -0.5166, -7, -1.2472, -0.5166, -5, -1.2472, 0.5166, -5, -1.2472, 0.5166, -7, -1.2472, -0.5166, -7, -1.2472, -0.5166, -5, -0.5166, -1.2472, -7, -0.5166, -1.2472, -5, -1.2472, -0.5166, -5, -1.2472, -0.5166, -7, -0.5166, -1.2472, -7, -0.5166, -1.2472, -5, 0.5166, -1.2472, -7, 0.5166, -1.2472, -5, -0.5166, -1.2472, -5, -0.5166, -1.2472, -7, 0.5166, -1.2472, -7, 0.5166, -1.2472, -5, 1.2472, -0.5166, -7, 1.2472, -0.5166, -5, 0.5166, -1.2472, -5, 0.5166, -1.2472, -7, 1.2472, -0.5166, -7, 1.2472, 0.5166, -5, 1.2472, -0.5166, -7, 1.2472, 0.5166, -7, 1.2472, 0.5166, -5, 1.2472, -0.5166, -5, 1.2472, -0.5166, -7, 0.5166, 1.2472, -5, 1.2472, 0.5166, -7, 0.5166, 1.2472, -7, 0.5166, 1.2472, -5, 1.2472, 0.5166, -5, 1.2472, 0.5166, -7, -0.5166, 1.2472, -5, 0.5166, 1.2472, -7, -0.5166, 1.2472, -7, -0.5166, 1.2472, -5, 0.5166, 1.2472, -5, 0.5166, 1.2472, -7, -0.5166, 1.2472, -5, -1.2472, 0.5166, -7, -1.2472, 0.5166, -5, -0.5166, 1.2472, -5, -0.5166, 1.2472, -7, -1.2472, 0.5166, -7, 1.9134, 1.5, -5, -0.5166, 1.2472, -5, -1.9134, 1.5, -5, 1.9134, 1.5, -5, 0.5166, 1.2472, -5, -0.5166, 1.2472, -5, 0.5166, 1.2472, -5, 1.9134, 1.5, -5, 1.2472, 0.5166, -5, 1.9134, -1.5, -5, 1.2472, 0.5166, -5, 1.9134, 1.5, -5, 1.9134, -1.5, -5, 1.2472, -0.5166, -5, 1.2472, 0.5166, -5, 1.2472, -0.5166, -5, 1.9134, -1.5, -5, 0.5166, -1.2472, -5, -1.9134, -1.5, -5, 0.5166, -1.2472, -5, 1.9134, -1.5, -5, -1.9134, -1.5, -5, -0.5166, -1.2472, -5, 0.5166, -1.2472, -5, -0.5166, -1.2472, -5, -1.9134, -1.5, -5, -1.2472, -0.5166, -5, -1.9134, 1.5, -5, -1.2472, -0.5166, -5, -1.9134, -1.5, -5, -1.9134, 1.5, -5, -1.2472, 0.5166, -5, -1.2472, -0.5166, -5, -1.2472, 0.5166, 7, -1.2472, -0.5166, 5, -1.2472, -0.5166, 7, -1.2472, 0.5166, 7, -1.2472, 0.5166, 5, -1.2472, -0.5166, 5, -1.2472, -0.5166, 7, -0.5166, -1.2472, 5, -0.5166, -1.2472, 7, -1.2472, -0.5166, 7, -1.2472, -0.5166, 5, -0.5166, -1.2472, 5, -0.5166, -1.2472, 7, 0.5166, -1.2472, 5, 0.5166, -1.2472, 7, -0.5166, -1.2472, 7, -0.5166, -1.2472, 5, 0.5166, -1.2472, 5, 0.5166, -1.2472, 7, 1.2472, -0.5166, 5, 1.2472, -0.5166, 7, 0.5166, -1.2472, 7, 0.5166, -1.2472, 5, 1.2472, -0.5166, 5, 1.2472, 0.5166, 7, 1.2472, -0.5166, 5, 1.2472, 0.5166, 5, 1.2472, 0.5166, 7, 1.2472, -0.5166, 7, 1.2472, -0.5166, 5, 0.5166, 1.2472, 7, 1.2472, 0.5166, 5, 0.5166, 1.2472, 5, 0.5166, 1.2472, 7, 1.2472, 0.5166, 7, 1.2472, 0.5166, 5, -0.5166, 1.2472, 7, 0.5166, 1.2472, 5, -0.5166, 1.2472, 5, -0.5166, 1.2472, 7, 0.5166, 1.2472, 7, 0.5166, 1.2472, 5, -0.5166, 1.2472, 7, -1.2472, 0.5166, 5, -1.2472, 0.5166, 7, -0.5166, 1.2472, 7, -0.5166, 1.2472, 5, -1.2472, 0.5166, 5, -1.9134, 1.5, 5, 0.5166, 1.2472, 5, 1.9134, 1.5, 5, -1.9134, 1.5, 5, -0.5166, 1.2472, 5, 0.5166, 1.2472, 5, -0.5166, 1.2472, 5, -1.9134, 1.5, 5, -1.2472, 0.5166, 5, -1.9134, -1.5, 5, -1.2472, 0.5166, 5, -1.9134, 1.5, 5, -1.9134, -1.5, 5, -1.2472, -0.5166, 5, -1.2472, 0.5166, 5, -1.2472, -0.5166, 5, -1.9134, -1.5, 5, -0.5166, -1.2472, 5, 1.9134, -1.5, 5, -0.5166, -1.2472, 5, -1.9134, -1.5, 5, 1.9134, -1.5, 5, 0.5166, -1.2472, 5, -0.5166, -1.2472, 5, 0.5166, -1.2472, 5, 1.9134, -1.5, 5, 1.2472, -0.5166, 5, 1.9134, 1.5, 5, 1.2472, -0.5166, 5, 1.9134, -1.5, 5, 1.9134, 1.5, 5, 1.2472, 0.5166, 5, 1.2472, -0.5166, 5) + +[node name="RoundRoom" type="Node3D"] + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = ExtResource("1_8mdb7") + +[node name="StaticBody3D" type="StaticBody3D" parent="MeshInstance3D"] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/StaticBody3D"] +shape = SubResource("ConcavePolygonShape3D_wurhb") diff --git a/prefabs/test_arena.tscn b/prefabs/test_arena.tscn new file mode 100644 index 0000000..7b7a510 --- /dev/null +++ b/prefabs/test_arena.tscn @@ -0,0 +1,120 @@ +[gd_scene load_steps=9 format=3 uid="uid://dlevowk0jrhlg"] + +[ext_resource type="PackedScene" uid="uid://cc1m2a1obsyn4" path="res://addons/fpc/character.tscn" id="1_vc6b5"] +[ext_resource type="Script" path="res://scripts/player.gd" id="2_puqns"] +[ext_resource type="PackedScene" uid="uid://cuad3khwmhnsa" path="res://prefabs/enemy.tscn" id="3_4ykmj"] + +[sub_resource type="Environment" id="Environment_2poci"] +background_color = Color(0.130548, 0.170599, 0.433834, 1) +ambient_light_source = 2 +ambient_light_color = Color(0.244776, 0.244776, 0.244776, 1) +ambient_light_energy = 2.27 + +[sub_resource type="BoxMesh" id="BoxMesh_ox60m"] +size = Vector3(0.1, 0.1, 0.5) + +[sub_resource type="Animation" id="Animation_l0ukc"] +resource_name = "RESET" +length = 0.001 +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:position:x") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} +tracks/1/type = "bezier" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath(".:position:y") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(1.5, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} + +[sub_resource type="Animation" id="Animation_nw35k"] +resource_name = "walk" +length = 2.0 +tracks/0/type = "bezier" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:position:x") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"handle_modes": PackedInt32Array(0, 0, 0, 0, 0), +"points": PackedFloat32Array(0.04, -0.25, 0, 0.25, 0, 0, 0, 0, 0, 0, -0.04, -0.25, 0, 0.25, 0, 0, 0, 0, 0, 0, 0.04, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0, 0.5, 1, 1.5, 2) +} +tracks/1/type = "bezier" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath(".:position:y") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"handle_modes": PackedInt32Array(0, 0, 0, 0, 0), +"points": PackedFloat32Array(1.45, -0.25, 0, 0.2, 0.005, 1.5, -0.2, 0.000186046, 0.2, 0.000186046, 1.45, -0.2, 0.005, 0.2, 0.005, 1.5, -0.2, 0, 0.2, 0, 1.45, -0.2, 0.005, 0.25, 0), +"times": PackedFloat32Array(0, 0.5, 1, 1.5, 2) +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_7dyvd"] +_data = { +"RESET": SubResource("Animation_l0ukc"), +"walk": SubResource("Animation_nw35k") +} + +[node name="Node3D" type="WorldEnvironment"] +environment = SubResource("Environment_2poci") + +[node name="OmniLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 0, -0.0795405) + +[node name="Player" parent="." node_paths=PackedStringArray("HEAD", "HEADBOB_ANIMATION") instance=ExtResource("1_vc6b5")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.97532, -1.28752, 0.602886) +HEAD = NodePath("PlayerCam") +HEADBOB_ANIMATION = NodePath("PlayerCam/HeadAnimation") +LEFT = "left" +RIGHT = "right" +FORWARD = "forward" +BACKWARD = "backward" +jumping_enabled = false +in_air_momentum = false +sprint_enabled = false +crouch_enabled = false + +[node name="PlayerCam" type="Node3D" parent="Player"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0) +script = ExtResource("2_puqns") +grapple_distance = 50.0 + +[node name="Camera3D" type="Camera3D" parent="Player/PlayerCam"] +current = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Player/PlayerCam"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.215, -0.09, 0) +mesh = SubResource("BoxMesh_ox60m") + +[node name="HeadAnimation" type="AnimationPlayer" parent="Player/PlayerCam"] +libraries = { +"": SubResource("AnimationLibrary_7dyvd") +} + +[node name="Enemy" parent="." node_paths=PackedStringArray("target") instance=ExtResource("3_4ykmj")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.49959, -1.54414, -8.92046) +collision_layer = 5 +motion_mode = 0 +target = NodePath("../Player") +gravity_enabled = true + +[node name="CSGBox3D" type="CSGBox3D" parent="."] +use_collision = true +flip_faces = true +size = Vector3(20, 4, 20) diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..7fa9387 --- /dev/null +++ b/project.godot @@ -0,0 +1,65 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="SpaceGame" +run/main_scene="res://test.tscn" +config/features=PackedStringArray("4.3", "GL Compatibility") +config/icon="res://icon.svg" + +[debug] + +gdscript/warnings/integer_division=0 + +[input] + +left={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null) +] +} +right={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null) +] +} +forward={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null) +] +} +backward={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +] +} +crouch={ +"deadzone": 0.5, +"events": [] +} +sprint={ +"deadzone": 0.5, +"events": [] +} +attack={ +"deadzone": 0.5, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(184, 6),"global_position":Vector2(193, 52),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null) +] +} + +[layer_names] + +3d_physics/layer_2="grapple" + +[rendering] + +renderer/rendering_method="gl_compatibility" +renderer/rendering_method.mobile="gl_compatibility" diff --git a/scripts/bsp_level_generator.gd b/scripts/bsp_level_generator.gd new file mode 100644 index 0000000..af34e0b --- /dev/null +++ b/scripts/bsp_level_generator.gd @@ -0,0 +1,78 @@ +extends Node2D + +@export var width: int = 40 +@export var height: int = 40 +@export var min_dim: int = 5 + +var min_room_size: int = min_dim * min_dim + +var rects: Array[Vector4i] = [] + +class BSPNode: + var min_dims: Vector2i + var max_dims: Vector2i + var left: BSPNode + var right: BSPNode + + func _init(p_min_dims: Vector2i, p_max_dims: Vector2i, p_left: BSPNode, p_right: BSPNode): + min_dims = p_min_dims + max_dims = p_max_dims + left = p_left + right = p_right + +func generate_level(axis: int, min_space: Vector2i, max_space: Vector2i, depth: int = 0) -> BSPNode: + var dims = max_space - min_space + if dims[axis] / 2 < min_dim: + #rects.append(Vector4i(min_space.x, min_space.y, max_space.x, max_space.y)) + return null + + var new_axis = (axis + 1) % 2 + # 10% we stop here and just create a big room + if (depth > 2 and randi_range(0, 9) == 0) \ + or dims.x * dims.y <= min_dim * min_dim \ + or dims[new_axis] / 2 < min_dim: + rects.append(Vector4i(min_space.x, min_space.y, max_space.x, max_space.y)) + return BSPNode.new(min_space, max_space, null, null) + + # Calculate min and max ranges so that a split + # doesn't create a room that violates min dimensions + var min_value = min_space[axis] + min_dim + var max_value = max_space[axis] - min_dim + var split = randi_range(min_value, max_value) + print("Spliting axis ", axis, " at ", split) + + var left_min_space = min_space + var left_max_space = max_space + left_max_space[axis] = split + var left = generate_level(new_axis, left_min_space, left_max_space, depth + 1) + + var right_min_space = min_space + right_min_space[axis] = split + var right_max_space = max_space + var right = generate_level(new_axis, right_min_space, right_max_space, depth + 1) + + assert((left == null and right == null) or (left != null and right != null)) + + if left == null and right == null: + rects.append(Vector4i(min_space.x, min_space.y, max_space.x, max_space.y)) + + return BSPNode.new(min_space, max_space, left, right) + +func _ready() -> void: + var starting_axis = randi_range(0, 1) + var min_space = Vector2i(0, 0) + var max_space = Vector2i(width, height) + var map = generate_level(starting_axis, min_space, max_space) + +func _draw(): + var mult = 1 + for rect in rects: + var pos1 = 5*Vector2i(rect.x, rect.y) + var pos2 = 5*Vector2i(rect.z, rect.w) + var dims = pos2 - pos1 + draw_rect(Rect2(pos1, dims), mult*Color(0.01, 0.01, 0.01)) + draw_line(pos1, Vector2i(pos1.x, pos2.y), Color(0, 1, 0)) + draw_line(Vector2i(pos1.x, pos2.y), pos2, Color(0, 1, 0)) + draw_line(pos2, Vector2i(pos2.x, pos1.y), Color(0, 1, 0)) + draw_line(Vector2i(pos2.x, pos1.y), pos1, Color(0, 1, 0)) + mult += 2 diff --git a/scripts/bullet.gd b/scripts/bullet.gd new file mode 100644 index 0000000..93c119a --- /dev/null +++ b/scripts/bullet.gd @@ -0,0 +1,17 @@ +extends Node3D + +var target: Vector3 + +var bullet_speed = 100.0 + +# Called when the node enters the scene tree for the first time. +#func _ready() -> void: +# pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta: float) -> void: + position = position.move_toward(target, bullet_speed * delta) + + if (target - position).length_squared() <= 2: + queue_free() diff --git a/scripts/enemy.gd b/scripts/enemy.gd new file mode 100644 index 0000000..569905f --- /dev/null +++ b/scripts/enemy.gd @@ -0,0 +1,87 @@ +extends CharacterBody3D + +## Speed of enemy +@export var speed: float = 2.0 +## Target for enemy to follow +@export var target: Node3D + +## Whether to use gravity on enemy +@export var gravity_enabled: bool = false + +var has_astar: bool = false +var astar: AStar3D +var tar_vec: Vector3 +var gravity : float = ProjectSettings.get_setting("physics/3d/default_gravity") + +var original_color: Color + +func _ready() -> void: + if gravity_enabled: + motion_mode = MotionMode.MOTION_MODE_GROUNDED + +func chase_target(delta: float) -> void: + var target_pos = target.position + var direction = (target_pos - position).normalized() + + if direction: + velocity.x = direction.x * speed + velocity.z = direction.z * speed + else: + velocity.x = move_toward(velocity.x, 0, speed) + velocity.z = move_toward(velocity.z, 0, speed) + + if not is_on_floor() and gravity_enabled: + velocity.y -= gravity * delta + + move_and_slide() + +func _physics_process(delta: float) -> void: + if target == null: + return + + if not has_astar: + # Just try to chase player directly + chase_target(delta) + return + + if Input.is_action_pressed("ui_right"): + return + + var target_pos = target.position + var closest_me = astar.get_closest_point(position) + var closest_target = astar.get_closest_point(target_pos) + + var direction: Vector3 + if closest_me == closest_target: + direction = (target_pos - position).normalized() + else: + var target_path = astar.get_point_path(closest_me, closest_target) + if len(target_path) >= 2: + direction = (target_path[1] - position).normalized() + + if direction: + #velocity.x = move_toward(velocity.x, direction.x * speed, 10.0 * delta) + #velocity.z = move_toward(velocity.z, direction.z * speed, 10.0 * delta) + velocity.x = direction.x * speed + velocity.z = direction.z * speed + else: + velocity.x = move_toward(velocity.x, 0, speed) + velocity.z = move_toward(velocity.z, 0, speed) + + move_and_slide() + +func on_hit(_hit_position: Vector3) -> void: + if $HitTimer.is_stopped(): + var material: StandardMaterial3D = $MeshInstance3D.get_active_material(0) + original_color = material.albedo_color + material.albedo_color = Color(1.0, 0.0, 0.0, 1.0) + $HitTimer.start() + +func _on_level_generator_astar_created(in_astar: AStar3D) -> void: + astar = in_astar + has_astar = true + +func _on_hit_timer_timeout() -> void: + var material: StandardMaterial3D = $MeshInstance3D.get_active_material(0) + material.albedo_color = original_color + $HitTimer.stop() diff --git a/scripts/level_generator.gd b/scripts/level_generator.gd new file mode 100644 index 0000000..94a87dd --- /dev/null +++ b/scripts/level_generator.gd @@ -0,0 +1,118 @@ +extends Node3D + +@export var width: int = 10 +@export var height: int = 10 + +var room = preload("res://prefabs/round_room.tscn") +var door = preload("res://prefabs/door.tscn") + +var bounds: Vector3 = Vector3.ZERO +var astar: AStar3D + +signal astar_created + +func get_grid_index(pos: Vector2i) -> int: + return pos.y*height + pos.x + +func set_grid_index(grid: Array[int], pos: Vector2i): + # If the point lies outside the grid we return + if pos.x < 0 or pos.x >= width or pos.y < 0 or pos.y >= height: + return + + var index = get_grid_index(pos) + + # If we already set this point we exit + if grid[index] != 0: + return + + grid[index] = 1 + var new_room: Node3D = room.instantiate() + var mesh = new_room.find_child("MeshInstance3D") + # TODO can we just load and cache the bounds? + bounds = mesh.get_aabb().size + var offset_pos = Vector3(pos.x - width / 2, 0, pos.y - height / 2) + new_room.position = (offset_pos * bounds) + #print("Placing at ", pos) + add_child(new_room) + + var next = [pos + Vector2i.UP, + pos + Vector2i.LEFT, + pos + Vector2i.DOWN, + pos + Vector2i.RIGHT] + + for n in next: + var chance = randi_range(0, 1) + if chance == 0: + set_grid_index(grid, n) + +func place_door(grid: Array[int], pos: Vector2i): + var index = get_grid_index(pos) + if grid[index] == 0: + return + + var next = [pos + Vector2i.UP, + pos + Vector2i.LEFT, + pos + Vector2i.DOWN, + pos + Vector2i.RIGHT] + + var angle = -90 + for n in next: + angle += 90 + var next_index = get_grid_index(n) + if n.x < 0 or n.x >= width or n.y < 0 or n.y >= height or grid[next_index] == 0: + var new_door: Node3D = door.instantiate() + var offset_pos = Vector3(pos.x - width / 2, 0, pos.y - height / 2) + new_door.position = (offset_pos * bounds) + new_door.rotate_y(deg_to_rad(angle)) + add_child(new_door) + +func place_doors(grid: Array[int]): + for y in range(0, height): + for x in range(0, width): + place_door(grid, Vector2i(x, y)) + +func compute_astar(grid: Array[int]): + for y in range(0, height): + for x in range(0, width): + var pos = Vector2i(x, y) + var index = get_grid_index(pos) + if grid[index] == 0: + continue + var offset_pos = Vector3(pos.x - width / 2, 0, pos.y - height / 2) + astar.add_point(index, offset_pos * bounds) + + for y in range(0, height): + for x in range(0, width): + var pos = Vector2i(x, y) + var index = get_grid_index(pos) + if grid[index] == 0: + continue + + var next = [pos + Vector2i.UP, + pos + Vector2i.LEFT, + pos + Vector2i.DOWN, + pos + Vector2i.RIGHT] + for n in next: + var next_index = get_grid_index(n) + if n.x < 0 or n.x >= width or n.y < 0 or n.y >= height or grid[next_index] == 0: + continue + + astar.connect_points(index, next_index) + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + astar = AStar3D.new() + var grid: Array[int] = [0] + grid.resize(width*height) + grid.fill(0) + + var middle_x: int = width / 2 + var middle_y: int = height / 2 + + var pos = Vector2i(middle_x, middle_y) + set_grid_index(grid, pos) + + place_doors(grid) + compute_astar(grid) + + astar_created.emit(astar) diff --git a/scripts/player.gd b/scripts/player.gd new file mode 100644 index 0000000..e76b4d1 --- /dev/null +++ b/scripts/player.gd @@ -0,0 +1,76 @@ +extends Node3D + +@export var grapple_distance: float = 10 +@export var grapple_speed: float = 10 +@export var fire_distance: float = 100 + +enum State { + NO_GRAPPLE, + FREE, + GRAPPLING +} + +var current_state: State = State.FREE +var grapple_target: Vector3 = Vector3.ZERO + +var bullet_inst = preload("res://prefabs/bullet.tscn") + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + pass # Replace with function body. + +func do_grapple() -> void: + if Input.is_action_just_pressed("attack") and current_state == State.FREE: + var space_state = get_world_3d().direct_space_state + + var starting_pos = global_position + var ending_pos = starting_pos + grapple_distance * -global_transform.basis.z + var query = PhysicsRayQueryParameters3D.create(starting_pos, ending_pos) + query.collision_mask = 0x2 + var result = space_state.intersect_ray(query) + + if result: + grapple_target = result.position + global_transform.basis.z + current_state = State.GRAPPLING + + if Input.is_action_just_released("attack") and current_state == State.GRAPPLING: + current_state = State.FREE + grapple_target = Vector3.ZERO + + + #print("State ", current_state, " ", grapple_target) + if current_state == State.GRAPPLING: + var dir_to_target = (grapple_target - global_position).normalized() + + get_parent().local_velocity = dir_to_target * grapple_speed + +func fire_weapon() -> void: + if Input.is_action_just_pressed("attack"): + var space_state = get_world_3d().direct_space_state + var starting_pos = global_position + var ending_pos = starting_pos + fire_distance * -global_transform.basis.z + var query = PhysicsRayQueryParameters3D.create(starting_pos, ending_pos) + var result = space_state.intersect_ray(query) + + var end = ending_pos + if result: + print("Hit! ") + if result.collider.has_method("on_hit"): + result.collider.on_hit(result.position) + end = result.position + else: + print("Miss") + + var bullet: Node3D = bullet_inst.instantiate() + bullet.position = starting_pos + bullet.target = end + get_tree().get_root().add_child(bullet) + bullet.look_at(end) + +func _physics_process(_delta: float) -> void: + do_grapple() + fire_weapon() + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(_delta: float) -> void: + pass diff --git a/scripts/spin_ground.gd b/scripts/spin_ground.gd new file mode 100644 index 0000000..078a757 --- /dev/null +++ b/scripts/spin_ground.gd @@ -0,0 +1,15 @@ +extends Node3D + +@export var rotation_dir: float = 1 +@export var rotation_axis: Vector3 = Vector3.BACK + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + #rotate_z(deg_to_rad(180)) + pass + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta: float) -> void: + rotate(rotation_axis, rotation_dir * delta); + pass diff --git a/test.tscn b/test.tscn new file mode 100644 index 0000000..a8eb607 --- /dev/null +++ b/test.tscn @@ -0,0 +1,46 @@ +[gd_scene load_steps=6 format=3 uid="uid://cuyu3mwm6sp3c"] + +[ext_resource type="PackedScene" uid="uid://cc1m2a1obsyn4" path="res://addons/fpc/character.tscn" id="1_00nvw"] +[ext_resource type="Script" path="res://scripts/player.gd" id="1_cfdah"] +[ext_resource type="PackedScene" uid="uid://cuad3khwmhnsa" path="res://prefabs/enemy.tscn" id="3_1yqys"] +[ext_resource type="PackedScene" uid="uid://dcu5otkh0t1pg" path="res://prefabs/level_generator.tscn" id="3_ykfds"] + +[sub_resource type="Environment" id="Environment_2poci"] +background_color = Color(0.130548, 0.170599, 0.433834, 1) +ambient_light_source = 2 +ambient_light_color = Color(0.244776, 0.244776, 0.244776, 1) +ambient_light_energy = 2.27 + +[node name="Node3D" type="WorldEnvironment"] +environment = SubResource("Environment_2poci") + +[node name="OmniLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 0, -0.0795405) + +[node name="Player" parent="." node_paths=PackedStringArray("HEAD") instance=ExtResource("1_00nvw")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.97532, -1.28752, 0.602886) +motion_mode = 1 +HEAD = NodePath("PlayerCam") +LEFT = "left" +RIGHT = "right" +FORWARD = "forward" +BACKWARD = "backward" +jumping_enabled = false +sprint_enabled = false +crouch_enabled = false +gravity_enabled = false + +[node name="PlayerCam" type="Node3D" parent="Player"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0) +script = ExtResource("1_cfdah") +grapple_distance = 50.0 + +[node name="Camera3D" type="Camera3D" parent="Player/PlayerCam"] +current = true + +[node name="Enemy" parent="." node_paths=PackedStringArray("target") instance=ExtResource("3_1yqys")] +target = NodePath("../Player") + +[node name="LevelGenerator" parent="." instance=ExtResource("3_ykfds")] + +[connection signal="astar_created" from="LevelGenerator" to="Enemy" method="_on_level_generator_astar_created"] diff --git a/test_world.tscn b/test_world.tscn new file mode 100644 index 0000000..b6901b9 --- /dev/null +++ b/test_world.tscn @@ -0,0 +1,106 @@ +[gd_scene load_steps=15 format=3 uid="uid://cs4drhmc1bql5"] + +[ext_resource type="PackedScene" uid="uid://cc1m2a1obsyn4" path="res://addons/fpc/character.tscn" id="1_e18vq"] +[ext_resource type="Texture2D" uid="uid://pe7a4weirj2g" path="res://textures/dark.png" id="2_08fdt"] +[ext_resource type="Texture2D" uid="uid://cxjxvqmf4boxq" path="res://textures/green.png" id="3_q4clv"] +[ext_resource type="Texture2D" uid="uid://dsv4jm4vydflb" path="res://textures/orange.png" id="4_1ns5t"] + +[sub_resource type="PhysicalSkyMaterial" id="PhysicalSkyMaterial_edcox"] +ground_color = Color(0.160784, 0.815686, 0.905882, 1) + +[sub_resource type="Sky" id="Sky_2iust"] +sky_material = SubResource("PhysicalSkyMaterial_edcox") + +[sub_resource type="Environment" id="Environment_20rw3"] +background_mode = 2 +sky = SubResource("Sky_2iust") +tonemap_mode = 1 +ssao_enabled = true + +[sub_resource type="Gradient" id="Gradient_ur0vy"] +colors = PackedColorArray(0, 0.476245, 0.0193456, 1, 0.360494, 0.612721, 0.119744, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_jd3pw"] +frequency = 0.0027 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_7akuf"] +width = 1024 +height = 1024 +in_3d_space = true +seamless = true +color_ramp = SubResource("Gradient_ur0vy") +noise = SubResource("FastNoiseLite_jd3pw") + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_67ysu"] +albedo_texture = SubResource("NoiseTexture2D_7akuf") +uv1_scale = Vector3(0.1, 0.1, 0.1) +uv1_triplanar = true + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_gomnb"] +albedo_texture = ExtResource("2_08fdt") +metallic = 0.81 +metallic_specular = 0.2 +roughness = 0.5 +uv1_triplanar = true +uv1_triplanar_sharpness = 0.000850145 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_u0sbk"] +albedo_texture = ExtResource("3_q4clv") +metallic = 0.81 +metallic_specular = 0.2 +roughness = 0.5 +uv1_triplanar = true +uv1_triplanar_sharpness = 0.000850145 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_7j4uu"] +albedo_texture = ExtResource("4_1ns5t") +metallic = 0.81 +metallic_specular = 0.2 +roughness = 0.5 +uv1_triplanar = true +uv1_triplanar_sharpness = 0.000850145 + +[node name="test_world" type="Node3D"] + +[node name="Character" parent="." instance=ExtResource("1_e18vq")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_20rw3") + +[node name="sun" type="DirectionalLight3D" parent="."] +transform = Transform3D(0.87959, -0.436605, 0.188936, 0, 0.397148, 0.917755, -0.475732, -0.807248, 0.349328, 0, 0, 0) +light_energy = 2.0 +shadow_enabled = true + +[node name="terrain" type="Node3D" parent="."] + +[node name="CSGBox3D" type="CSGBox3D" parent="terrain"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10, -0.5, 10) +use_collision = true +size = Vector3(30, 1, 30) +material = SubResource("StandardMaterial3D_67ysu") + +[node name="CSGBox3D2" type="CSGBox3D" parent="terrain"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.5, -10) +use_collision = true +size = Vector3(10, 1, 10) +material = SubResource("StandardMaterial3D_gomnb") + +[node name="CSGBox3D3" type="CSGBox3D" parent="terrain"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 1.8, -13) +use_collision = true +size = Vector3(4, 0.5, 4) +material = SubResource("StandardMaterial3D_gomnb") + +[node name="CSGBox3D4" type="CSGBox3D" parent="terrain"] +transform = Transform3D(0.939693, 0.34202, 0, -0.34202, 0.939693, 0, 0, 0, 1, -9.5, 1.2, -10) +use_collision = true +size = Vector3(10, 1, 10) +material = SubResource("StandardMaterial3D_u0sbk") + +[node name="CSGBox3D5" type="CSGBox3D" parent="terrain"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.5, 3, -15.5) +use_collision = true +size = Vector3(19, 8, 1) +material = SubResource("StandardMaterial3D_7j4uu") diff --git a/textures/dark.png b/textures/dark.png new file mode 100644 index 0000000..69be211 Binary files /dev/null and b/textures/dark.png differ diff --git a/textures/dark.png.import b/textures/dark.png.import new file mode 100644 index 0000000..2a82a3f --- /dev/null +++ b/textures/dark.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://pe7a4weirj2g" +path.s3tc="res://.godot/imported/dark.png-6d46f668c80e231a58e570df85aad257.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://textures/dark.png" +dest_files=["res://.godot/imported/dark.png-6d46f668c80e231a58e570df85aad257.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 diff --git a/textures/green.png b/textures/green.png new file mode 100644 index 0000000..7bc7cf8 Binary files /dev/null and b/textures/green.png differ diff --git a/textures/green.png.import b/textures/green.png.import new file mode 100644 index 0000000..7c7e044 --- /dev/null +++ b/textures/green.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cxjxvqmf4boxq" +path.s3tc="res://.godot/imported/green.png-b4f8ddc6b00d4e627f0e027e2e1193bf.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://textures/green.png" +dest_files=["res://.godot/imported/green.png-b4f8ddc6b00d4e627f0e027e2e1193bf.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 diff --git a/textures/orange.png b/textures/orange.png new file mode 100644 index 0000000..dec5b59 Binary files /dev/null and b/textures/orange.png differ diff --git a/textures/orange.png.import b/textures/orange.png.import new file mode 100644 index 0000000..311f8ac --- /dev/null +++ b/textures/orange.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dsv4jm4vydflb" +path.s3tc="res://.godot/imported/orange.png-6785d3f8216fd22318e8ea839823715b.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://textures/orange.png" +dest_files=["res://.godot/imported/orange.png-6785d3f8216fd22318e8ea839823715b.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 diff --git a/textures/purple.png b/textures/purple.png new file mode 100644 index 0000000..48a51c1 Binary files /dev/null and b/textures/purple.png differ diff --git a/textures/purple.png.import b/textures/purple.png.import new file mode 100644 index 0000000..9dc0969 --- /dev/null +++ b/textures/purple.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cl4kewig3pk7s" +path="res://.godot/imported/purple.png-23488e84f4f0a47488be2c78494f2155.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://textures/purple.png" +dest_files=["res://.godot/imported/purple.png-23488e84f4f0a47488be2c78494f2155.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/textures/red.png b/textures/red.png new file mode 100644 index 0000000..bf1cb17 Binary files /dev/null and b/textures/red.png differ diff --git a/textures/red.png.import b/textures/red.png.import new file mode 100644 index 0000000..c8c15aa --- /dev/null +++ b/textures/red.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d1h161t0v6hau" +path="res://.godot/imported/red.png-3cad0ca19141406d60f5fd2311159a86.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://textures/red.png" +dest_files=["res://.godot/imported/red.png-3cad0ca19141406d60f5fd2311159a86.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 -- cgit