From 02c60ae6226c9ac64a0be2ab193776a142fb0609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torjus=20H=C3=A5kestad?= Date: Thu, 14 Aug 2025 12:14:09 +0200 Subject: [PATCH] godot: add initial game --- .gitignore | 1 + flake.lock | 27 ++++++++++++++++++ flake.nix | 36 ++++++++++++++++++++++++ game/.editorconfig | 4 +++ game/Player.gd | 57 +++++++++++++++++++++++++++++++++++++ game/Player.gd.uid | 1 + game/icon.svg | 1 + game/icon.svg.import | 37 ++++++++++++++++++++++++ game/player.tscn | 44 +++++++++++++++++++++++++++++ game/player_debug.gd | 15 ++++++++++ game/player_debug.gd.uid | 1 + game/project.godot | 54 +++++++++++++++++++++++++++++++++++ game/world.tscn | 61 ++++++++++++++++++++++++++++++++++++++++ 13 files changed, 339 insertions(+) create mode 100644 .gitignore create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 game/.editorconfig create mode 100644 game/Player.gd create mode 100644 game/Player.gd.uid create mode 100644 game/icon.svg create mode 100644 game/icon.svg.import create mode 100644 game/player.tscn create mode 100644 game/player_debug.gd create mode 100644 game/player_debug.gd.uid create mode 100644 game/project.godot create mode 100644 game/world.tscn diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..78c7d8f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +game/.godot diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..f2d2da2 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1755027561, + "narHash": "sha256-IVft239Bc8p8Dtvf7UAACMG5P3ZV+3/aO28gXpGtMXI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..47f089c --- /dev/null +++ b/flake.nix @@ -0,0 +1,36 @@ +{ + description = "Godot test project"; + + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + outputs = + { self, nixpkgs }: + let + allSystems = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + forAllSystems = + f: + nixpkgs.lib.genAttrs allSystems ( + system: + f { + pkgs = import nixpkgs { inherit system; }; + } + ); + in + { + devShells = forAllSystems ( + { pkgs }: + { + default = pkgs.mkShell { + packages = with pkgs; [ + godot + ]; + }; + } + ); + }; +} diff --git a/game/.editorconfig b/game/.editorconfig new file mode 100644 index 0000000..f28239b --- /dev/null +++ b/game/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +charset = utf-8 diff --git a/game/Player.gd b/game/Player.gd new file mode 100644 index 0000000..0474ca1 --- /dev/null +++ b/game/Player.gd @@ -0,0 +1,57 @@ +extends CharacterBody3D + +const SPEED = 5.0 +const JUMP_VELOCITY = 4.5 +const SENSITIVITY = 0.005 + +var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") + +@onready var head = $Head +@onready var camera = $Head/Camera3D +@onready var dash_timer = $DashTimer +@onready var player_debug = $Head/Camera3D/PlayerDebug + +func _ready() -> void: + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + +func _unhandled_input(event: InputEvent) -> void: + if event is InputEventMouseMotion: + head.rotate_y(-event.relative.x * SENSITIVITY) + camera.rotate_x(-event.relative.y * SENSITIVITY) + camera.rotation.x = clamp(camera.rotation.x, deg_to_rad(-40), deg_to_rad(80)) + + if Input.is_action_just_pressed("ui_cancel"): + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + + if Input.is_action_just_pressed("debug_overlay"): + player_debug.visible = !player_debug.visible + +func _physics_process(delta: float) -> void: + if not is_on_floor(): + velocity.y -= gravity * delta + + if Input.is_action_just_pressed("jump") and is_on_floor(): + velocity.y = JUMP_VELOCITY + + var input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_backward") + var direction = (head.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized() + + if direction: + velocity.x = direction.x * SPEED + velocity.z = direction.z * SPEED + else: + velocity.x = 0.0 + velocity.z = 0.0 + + if Input.is_action_just_pressed("dash") and dash_timer.is_stopped(): + velocity.x = velocity.x * 10 + velocity.z = velocity.z * 10 + dash_timer.start() + + if player_debug.visible: + player_debug.add_stat("vel_x", str(velocity.x)) + player_debug.add_stat("vel_y", str(velocity.y)) + player_debug.add_stat("vel_z", str(velocity.z)) + player_debug.add_stat("dash_cd", str(dash_timer.time_left)) + + move_and_slide() diff --git a/game/Player.gd.uid b/game/Player.gd.uid new file mode 100644 index 0000000..700c45e --- /dev/null +++ b/game/Player.gd.uid @@ -0,0 +1 @@ +uid://5vty5riyfef2 diff --git a/game/icon.svg b/game/icon.svg new file mode 100644 index 0000000..9d8b7fa --- /dev/null +++ b/game/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/game/icon.svg.import b/game/icon.svg.import new file mode 100644 index 0000000..0395fe5 --- /dev/null +++ b/game/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c5q4unny4gqid" +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/game/player.tscn b/game/player.tscn new file mode 100644 index 0000000..6b51a58 --- /dev/null +++ b/game/player.tscn @@ -0,0 +1,44 @@ +[gd_scene load_steps=6 format=3 uid="uid://dkldpdufpl28x"] + +[ext_resource type="Script" uid="uid://5vty5riyfef2" path="res://Player.gd" id="1_4flbx"] +[ext_resource type="Script" uid="uid://cad5seggccvp6" path="res://player_debug.gd" id="2_onrkg"] + +[sub_resource type="CapsuleMesh" id="CapsuleMesh_fj7yv"] + +[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_tlwt5"] +points = PackedVector3Array(-0.125207, -0.532801, -0.480507, 0.0227831, 0.47607, 0.498884, 0.169713, 0.559144, 0.464172, 0.231051, -0.803591, 0.320455, 0.40741, 0.651043, -0.243523, -0.482789, 0.594843, 0.0822132, -0.362868, -0.682312, 0.289697, 0.469044, -0.654529, -0.0662713, -0.127444, 0.842701, -0.338103, -0.393435, -0.683942, -0.244717, 0.438255, 0.623309, 0.200849, 0.0841477, 0.977454, 0.114795, -0.0682023, -0.976458, -0.12927, 0.20055, -0.563129, -0.451454, -0.185527, 0.595453, -0.453475, -0.273363, 0.592268, 0.407754, -0.00693649, -0.476823, 0.49966, 0.375821, -0.588614, 0.316955, 0.111579, 0.563059, -0.481177, -0.41725, 0.527866, -0.270497, -0.484546, -0.596972, -0.0665097, -0.279747, 0.908561, 0.0533361, -0.250197, -0.880712, 0.205319, 0.263647, -0.902771, -0.127394, 0.293368, 0.871526, -0.157196, 0.373412, -0.526319, -0.328246, 0.499663, 0.476641, -0.00688856, 0.0531056, 0.875001, 0.324703, -0.154543, -0.590854, 0.465879, -0.0972799, -0.782358, -0.398188, -0.387649, -0.498171, 0.31565, -0.30068, -0.587995, -0.388901) + +[sub_resource type="BoxMesh" id="BoxMesh_4flbx"] + +[node name="Player" type="CharacterBody3D"] +visible = false +script = ExtResource("1_4flbx") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.035977, 1.01008, 0.068555) +mesh = SubResource("CapsuleMesh_fj7yv") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.035977, 1.11008, 0.068555) +shape = SubResource("ConvexPolygonShape3D_tlwt5") + +[node name="Head" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00735188, 1.73848, -0.314173) + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="Head"] +transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 1, 0.00688243, 0.00469124, -0.343256) +mesh = SubResource("BoxMesh_4flbx") +skeleton = NodePath("../..") + +[node name="PlayerCamera" type="Camera3D" parent="Head"] + +[node name="PlayerDebug" type="CanvasLayer" parent="Head/PlayerCamera"] +visible = false +script = ExtResource("2_onrkg") + +[node name="PlayerDebugText" type="RichTextLabel" parent="Head/PlayerCamera/PlayerDebug"] +offset_right = 635.0 +offset_bottom = 283.0 + +[node name="DashTimer" type="Timer" parent="."] +one_shot = true diff --git a/game/player_debug.gd b/game/player_debug.gd new file mode 100644 index 0000000..74f9220 --- /dev/null +++ b/game/player_debug.gd @@ -0,0 +1,15 @@ +extends CanvasLayer + +@onready var debug_text = $PlayerDebugText + +var stats: Dictionary = {} + +func add_stat(name: String, value: String): + stats[name] = value + +func _process(delta: float) -> void: + debug_text.clear() + for key in stats: + var value = stats[key] + debug_text.append_text("%s: %s\n" % [key, value]) + diff --git a/game/player_debug.gd.uid b/game/player_debug.gd.uid new file mode 100644 index 0000000..154d18b --- /dev/null +++ b/game/player_debug.gd.uid @@ -0,0 +1 @@ +uid://cad5seggccvp6 diff --git a/game/project.godot b/game/project.godot new file mode 100644 index 0000000..9fe1650 --- /dev/null +++ b/game/project.godot @@ -0,0 +1,54 @@ +; 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="fmm" +run/main_scene="uid://co2f5i23gyp03" +config/features=PackedStringArray("4.4", "Forward Plus") +config/icon="res://icon.svg" + +[input] + +move_left={ +"deadzone": 0.2, +"events": [null, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"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":0,"location":0,"echo":false,"script":null) +] +} +move_right={ +"deadzone": 0.2, +"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) +] +} +move_forward={ +"deadzone": 0.2, +"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) +] +} +move_backward={ +"deadzone": 0.2, +"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) +] +} +jump={ +"deadzone": 0.2, +"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":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null) +] +} +dash={ +"deadzone": 0.2, +"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":4194325,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +debug_overlay={ +"deadzone": 0.2, +"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":4194332,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} diff --git a/game/world.tscn b/game/world.tscn new file mode 100644 index 0000000..b839da9 --- /dev/null +++ b/game/world.tscn @@ -0,0 +1,61 @@ +[gd_scene load_steps=6 format=3 uid="uid://co2f5i23gyp03"] + +[ext_resource type="PackedScene" uid="uid://dkldpdufpl28x" path="res://player.tscn" id="1_f3sb7"] + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_f3sb7"] +sky_horizon_color = Color(0.662243, 0.671743, 0.686743, 1) +ground_horizon_color = Color(0.662243, 0.671743, 0.686743, 1) + +[sub_resource type="Sky" id="Sky_fj7yv"] +sky_material = SubResource("ProceduralSkyMaterial_f3sb7") + +[sub_resource type="Environment" id="Environment_tlwt5"] +background_mode = 2 +sky = SubResource("Sky_fj7yv") +tonemap_mode = 2 +glow_enabled = true + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_f3sb7"] +albedo_color = Color(0.398875, 0.46629, 0.228578, 1) + +[node name="World" type="Node3D"] + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(-0.866023, -0.433016, 0.250001, 0, 0.499998, 0.866027, -0.500003, 0.749999, -0.43301, 0, 14.6596, 0) +shadow_enabled = true + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_tlwt5") + +[node name="Ground" type="CSGBox3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -1, 8.74228e-08, 0, -8.74228e-08, -1, 0, 0, 1) +use_collision = true +size = Vector3(100, 1, 100) +material = SubResource("StandardMaterial3D_f3sb7") + +[node name="Wall1" type="CSGBox3D" parent="Ground"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -4.61707, -49.5431) +size = Vector3(100, 10, 1) + +[node name="Wall2" type="CSGBox3D" parent="Ground"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -4.61706, 49.9496) +size = Vector3(100, 10, 1) + +[node name="Wall3" type="CSGBox3D" parent="Ground"] +transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 49.4113, -4.61706, 0.548481) +size = Vector3(100, 10, 1) + +[node name="Wall4" type="CSGBox3D" parent="Ground"] +transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -48.8424, -4.61706, 0.548481) +size = Vector3(100, 10, 1) + +[node name="CSGBox3D" type="CSGBox3D" parent="Ground"] +transform = Transform3D(1, 0, 0, 0, -1, -8.74228e-08, 0, 8.74228e-08, -1, 0, -0.970131, 27.9382) +size = Vector3(5, 1, 5) + +[node name="CSGBox3D2" type="CSGBox3D" parent="Ground"] +transform = Transform3D(1, 0, 0, 0, -1, -8.74228e-08, 0, 8.74228e-08, -1, 10.554, -2.97013, 27.9382) +size = Vector3(5, 5, 5) + +[node name="Player" parent="." instance=ExtResource("1_f3sb7")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.55964, 0)