From 582b2c43cb637d882966ce7b743bfc98f4e71821 Mon Sep 17 00:00:00 2001 From: hz Date: Wed, 21 Jan 2026 17:59:14 -0600 Subject: [PATCH 1/2] Adding basic car --- game/assets/audio/jump.ogg.import | 38 +++--- .../audio/silly-menu-hover-test.ogg.import | 38 +++--- game/assets/audio/silly-test.ogg.import | 38 +++--- ...ayfairDisplay-VariableFont_wght.ttf.import | 72 +++++------ game/assets/images/pp_start_bg.png.import | 80 ++++++------ game/assets/models/human.blend.import | 118 +++++++++--------- game/icon.svg.import | 86 ++++++------- game/project.godot | 15 ++- game/scenes/Levels/level.tscn | 30 +++-- game/scenes/Levels/menu.gd | 21 ++-- game/scenes/Vehicles/car.gd | 81 ++++++++++++ game/scenes/Vehicles/car.gd.uid | 1 + game/scenes/Vehicles/car.tscn | 43 +++++++ game/scenes/player.gd | 70 ++++++++--- 14 files changed, 452 insertions(+), 279 deletions(-) create mode 100644 game/scenes/Vehicles/car.gd create mode 100644 game/scenes/Vehicles/car.gd.uid create mode 100644 game/scenes/Vehicles/car.tscn diff --git a/game/assets/audio/jump.ogg.import b/game/assets/audio/jump.ogg.import index d0a637d..1e15ee3 100644 --- a/game/assets/audio/jump.ogg.import +++ b/game/assets/audio/jump.ogg.import @@ -1,19 +1,19 @@ -[remap] - -importer="oggvorbisstr" -type="AudioStreamOggVorbis" -uid="uid://de2e8sy4x724m" -path="res://.godot/imported/jump.ogg-09aff86a6f79a8fce2febb69902962cf.oggvorbisstr" - -[deps] - -source_file="res://assets/audio/jump.ogg" -dest_files=["res://.godot/imported/jump.ogg-09aff86a6f79a8fce2febb69902962cf.oggvorbisstr"] - -[params] - -loop=false -loop_offset=0 -bpm=0 -beat_count=0 -bar_beats=4 +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://de2e8sy4x724m" +path="res://.godot/imported/jump.ogg-09aff86a6f79a8fce2febb69902962cf.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/jump.ogg" +dest_files=["res://.godot/imported/jump.ogg-09aff86a6f79a8fce2febb69902962cf.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/game/assets/audio/silly-menu-hover-test.ogg.import b/game/assets/audio/silly-menu-hover-test.ogg.import index 018ec64..0a47544 100644 --- a/game/assets/audio/silly-menu-hover-test.ogg.import +++ b/game/assets/audio/silly-menu-hover-test.ogg.import @@ -1,19 +1,19 @@ -[remap] - -importer="oggvorbisstr" -type="AudioStreamOggVorbis" -uid="uid://64dplcgx2icb" -path="res://.godot/imported/silly-menu-hover-test.ogg-101de051c9810c756b28483653a4c618.oggvorbisstr" - -[deps] - -source_file="res://assets/audio/silly-menu-hover-test.ogg" -dest_files=["res://.godot/imported/silly-menu-hover-test.ogg-101de051c9810c756b28483653a4c618.oggvorbisstr"] - -[params] - -loop=false -loop_offset=0 -bpm=0 -beat_count=0 -bar_beats=4 +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://64dplcgx2icb" +path="res://.godot/imported/silly-menu-hover-test.ogg-101de051c9810c756b28483653a4c618.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/silly-menu-hover-test.ogg" +dest_files=["res://.godot/imported/silly-menu-hover-test.ogg-101de051c9810c756b28483653a4c618.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/game/assets/audio/silly-test.ogg.import b/game/assets/audio/silly-test.ogg.import index da1cc68..db3d768 100644 --- a/game/assets/audio/silly-test.ogg.import +++ b/game/assets/audio/silly-test.ogg.import @@ -1,19 +1,19 @@ -[remap] - -importer="oggvorbisstr" -type="AudioStreamOggVorbis" -uid="uid://txgki0ijeuud" -path="res://.godot/imported/silly-test.ogg-4a08df8a26b9ee1e5d13235e013c7cfc.oggvorbisstr" - -[deps] - -source_file="res://assets/audio/silly-test.ogg" -dest_files=["res://.godot/imported/silly-test.ogg-4a08df8a26b9ee1e5d13235e013c7cfc.oggvorbisstr"] - -[params] - -loop=false -loop_offset=0 -bpm=0 -beat_count=0 -bar_beats=4 +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://txgki0ijeuud" +path="res://.godot/imported/silly-test.ogg-4a08df8a26b9ee1e5d13235e013c7cfc.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/silly-test.ogg" +dest_files=["res://.godot/imported/silly-test.ogg-4a08df8a26b9ee1e5d13235e013c7cfc.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/game/assets/fonts/PlayfairDisplay-VariableFont_wght.ttf.import b/game/assets/fonts/PlayfairDisplay-VariableFont_wght.ttf.import index f1dc51a..ad2f4cf 100644 --- a/game/assets/fonts/PlayfairDisplay-VariableFont_wght.ttf.import +++ b/game/assets/fonts/PlayfairDisplay-VariableFont_wght.ttf.import @@ -1,36 +1,36 @@ -[remap] - -importer="font_data_dynamic" -type="FontFile" -uid="uid://m5ceou0rk6j6" -path="res://.godot/imported/PlayfairDisplay-VariableFont_wght.ttf-fbc765a7962e1c71b0eb2c53d6eb2a10.fontdata" - -[deps] - -source_file="res://assets/fonts/PlayfairDisplay-VariableFont_wght.ttf" -dest_files=["res://.godot/imported/PlayfairDisplay-VariableFont_wght.ttf-fbc765a7962e1c71b0eb2c53d6eb2a10.fontdata"] - -[params] - -Rendering=null -antialiasing=1 -generate_mipmaps=false -disable_embedded_bitmaps=true -multichannel_signed_distance_field=false -msdf_pixel_range=8 -msdf_size=48 -allow_system_fallback=true -force_autohinter=false -modulate_color_glyphs=false -hinting=1 -subpixel_positioning=4 -keep_rounding_remainders=true -oversampling=0.0 -Fallbacks=null -fallbacks=[] -Compress=null -compress=true -preload=[] -language_support={} -script_support={} -opentype_features={} +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://m5ceou0rk6j6" +path="res://.godot/imported/PlayfairDisplay-VariableFont_wght.ttf-fbc765a7962e1c71b0eb2c53d6eb2a10.fontdata" + +[deps] + +source_file="res://assets/fonts/PlayfairDisplay-VariableFont_wght.ttf" +dest_files=["res://.godot/imported/PlayfairDisplay-VariableFont_wght.ttf-fbc765a7962e1c71b0eb2c53d6eb2a10.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +modulate_color_glyphs=false +hinting=1 +subpixel_positioning=4 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/game/assets/images/pp_start_bg.png.import b/game/assets/images/pp_start_bg.png.import index 17419c6..64da61e 100644 --- a/game/assets/images/pp_start_bg.png.import +++ b/game/assets/images/pp_start_bg.png.import @@ -1,40 +1,40 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://dhuosr0p605gj" -path="res://.godot/imported/pp_start_bg.png-8fb0f850edd45e79935f992c58fa8ca2.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://assets/images/pp_start_bg.png" -dest_files=["res://.godot/imported/pp_start_bg.png-8fb0f850edd45e79935f992c58fa8ca2.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/uastc_level=0 -compress/rdo_quality_loss=0.0 -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/channel_remap/red=0 -process/channel_remap/green=1 -process/channel_remap/blue=2 -process/channel_remap/alpha=3 -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 +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dhuosr0p605gj" +path="res://.godot/imported/pp_start_bg.png-8fb0f850edd45e79935f992c58fa8ca2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/images/pp_start_bg.png" +dest_files=["res://.godot/imported/pp_start_bg.png-8fb0f850edd45e79935f992c58fa8ca2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/game/assets/models/human.blend.import b/game/assets/models/human.blend.import index 070e247..d05a2b2 100644 --- a/game/assets/models/human.blend.import +++ b/game/assets/models/human.blend.import @@ -1,59 +1,59 @@ -[remap] - -importer="scene" -importer_version=1 -type="PackedScene" -uid="uid://bb6hj6l23043x" -path="res://.godot/imported/human.blend-738fbf7b85a13f54d00c9db65cf59296.scn" - -[deps] - -source_file="res://assets/models/human.blend" -dest_files=["res://.godot/imported/human.blend-738fbf7b85a13f54d00c9db65cf59296.scn"] - -[params] - -nodes/root_type="" -nodes/root_name="" -nodes/root_script=null -nodes/apply_root_scale=true -nodes/root_scale=1.0 -nodes/import_as_skeleton_bones=false -nodes/use_name_suffixes=true -nodes/use_node_type_suffixes=true -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="" -materials/extract=0 -materials/extract_format=0 -materials/extract_path="" -_subresources={} -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/export_geometry_nodes_instances=false -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 -gltf/naming_version=2 +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bb6hj6l23043x" +path="res://.godot/imported/human.blend-738fbf7b85a13f54d00c9db65cf59296.scn" + +[deps] + +source_file="res://assets/models/human.blend" +dest_files=["res://.godot/imported/human.blend-738fbf7b85a13f54d00c9db65cf59296.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +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="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +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/export_geometry_nodes_instances=false +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 +gltf/naming_version=2 diff --git a/game/icon.svg.import b/game/icon.svg.import index 41c7dda..a53bccb 100644 --- a/game/icon.svg.import +++ b/game/icon.svg.import @@ -1,43 +1,43 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://f2g3tvryiodc" -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/uastc_level=0 -compress/rdo_quality_loss=0.0 -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/channel_remap/red=0 -process/channel_remap/green=1 -process/channel_remap/blue=2 -process/channel_remap/alpha=3 -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 +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://f2g3tvryiodc" +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/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/project.godot b/game/project.godot index e2cdff6..90f9bbf 100644 --- a/game/project.godot +++ b/game/project.godot @@ -69,8 +69,13 @@ player_light={ "events": [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":70,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) ] } -player_phone={ -"deadzone": 0.2, -"events": [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":4194306,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) -] -} +player_phone={ +"deadzone": 0.2, +"events": [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":4194306,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +interact={ +"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":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null) +] +} diff --git a/game/scenes/Levels/level.tscn b/game/scenes/Levels/level.tscn index e9f7d93..777f49a 100644 --- a/game/scenes/Levels/level.tscn +++ b/game/scenes/Levels/level.tscn @@ -1,11 +1,12 @@ -[gd_scene load_steps=17 format=3 uid="uid://dchj6g2i8ebph"] +[gd_scene load_steps=18 format=3 uid="uid://dchj6g2i8ebph"] [ext_resource type="Script" uid="uid://brgmxhhhtakja" path="res://scenes/Levels/level.gd" id="1_a4mo8"] [ext_resource type="PackedScene" uid="uid://bb6hj6l23043x" path="res://assets/models/human.blend" id="1_eg4yq"] [ext_resource type="Script" uid="uid://bpxggc8nr6tf6" path="res://scenes/player.gd" id="1_muv8p"] -[ext_resource type="PackedScene" uid="uid://c5of6aaxop1hl" path="res://scenes/block.tscn" id="2_tc7dm"] -[ext_resource type="Script" uid="uid://b7fopt7sx74g8" path="res://scenes/Levels/menu.gd" id="3_tc7dm"] -[ext_resource type="PackedScene" path="res://scenes/Characters/repo_bot.tscn" id="4_repo"] +[ext_resource type="PackedScene" uid="uid://c5of6aaxop1hl" path="res://scenes/block.tscn" id="2_tc7dm"] +[ext_resource type="Script" uid="uid://b7fopt7sx74g8" path="res://scenes/Levels/menu.gd" id="3_tc7dm"] +[ext_resource type="PackedScene" path="res://scenes/Characters/repo_bot.tscn" id="4_repo"] +[ext_resource type="PackedScene" path="res://scenes/Vehicles/car.tscn" id="5_car"] [sub_resource type="PhysicsMaterial" id="PhysicsMaterial_2q6dc"] bounce = 0.5 @@ -58,11 +59,11 @@ debug_color = Color(0.29772994, 0.6216631, 0.28140613, 0.41960785) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) mesh = SubResource("SphereMesh_w7c3h") -[node name="Player" type="RigidBody3D" parent="."] -physics_material_override = SubResource("PhysicsMaterial_w8frs") -script = ExtResource("1_muv8p") -camera_path = NodePath("Camera3D") -phone_path = NodePath("../PhoneUI") +[node name="Player" type="RigidBody3D" parent="."] +physics_material_override = SubResource("PhysicsMaterial_w8frs") +script = ExtResource("1_muv8p") +camera_path = NodePath("Camera3D") +phone_path = NodePath("../PhoneUI") [node name="CollisionShape3D" type="CollisionShape3D" parent="Player"] shape = SubResource("SphereShape3D_mx8sn") @@ -71,10 +72,13 @@ shape = SubResource("SphereShape3D_mx8sn") transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.31670225, 0) current = true -[node name="SpotLight3D" type="SpotLight3D" parent="Player"] - -[node name="Ground" type="StaticBody3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) +[node name="SpotLight3D" type="SpotLight3D" parent="Player"] + +[node name="Car" parent="." instance=ExtResource("5_car")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6, 0, -3) + +[node name="Ground" type="StaticBody3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) [node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"] shape = SubResource("BoxShape3D_2q6dc") diff --git a/game/scenes/Levels/menu.gd b/game/scenes/Levels/menu.gd index 1d7e852..006e870 100644 --- a/game/scenes/Levels/menu.gd +++ b/game/scenes/Levels/menu.gd @@ -14,13 +14,15 @@ func _input(event): else: pause_game() -func pause_game(): - get_tree().paused = true - visible = true +func pause_game(): + get_tree().paused = true + visible = true + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) -func resume_game(): - get_tree().paused = false - visible = false +func resume_game(): + get_tree().paused = false + visible = false + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) func _on_quit_button_pressed(): get_tree().quit() @@ -28,9 +30,10 @@ func _on_quit_button_pressed(): func _on_continue_button_pressed(): resume_game() -func _on_main_menu_button_pressed(): - resume_game() - get_tree().change_scene_to_file(START_SCREEN_SCENE) +func _on_main_menu_button_pressed(): + resume_game() + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + get_tree().change_scene_to_file(START_SCREEN_SCENE) func _register_focus_sounds() -> void: if pause_menu == null: diff --git a/game/scenes/Vehicles/car.gd b/game/scenes/Vehicles/car.gd new file mode 100644 index 0000000..9d92881 --- /dev/null +++ b/game/scenes/Vehicles/car.gd @@ -0,0 +1,81 @@ +extends RigidBody3D + +@export var drive_speed := 18.0 +@export var drive_accel := 20.0 +@export var brake_strength := 28.0 +@export var turn_speed := 2.0 +@export var turn_accel := 8.0 +@export var lateral_damp := 10.0 +@export var seat_path: NodePath +@export var exit_path: NodePath +@export var camera_path: NodePath +@export var interact_area_path: NodePath + +@onready var seat: Node3D = get_node(seat_path) if seat_path != NodePath("") else null +@onready var exit_point: Node3D = get_node(exit_path) if exit_path != NodePath("") else null +@onready var car_camera: Camera3D = get_node(camera_path) if camera_path != NodePath("") else null +@onready var interact_area: Area3D = get_node(interact_area_path) if interact_area_path != NodePath("") else null + +var _nearby_driver: Node = null +var _driver: Node = null + +func _ready() -> void: + if interact_area: + interact_area.collision_layer = 2 + interact_area.collision_mask = 1 + interact_area.body_entered.connect(_on_interact_body_entered) + interact_area.body_exited.connect(_on_interact_body_exited) + if car_camera: + car_camera.current = false + +func _process(_delta: float) -> void: + if _driver == null and _nearby_driver != null and Input.is_action_just_pressed("interact"): + _enter_vehicle(_nearby_driver) + elif _driver != null and Input.is_action_just_pressed("interact"): + _exit_vehicle() + +func _integrate_forces(state: PhysicsDirectBodyState3D) -> void: + if _driver == null: + return + + var input2v := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") + var forward := global_transform.basis.z + forward.y = 0.0 + forward = forward.normalized() + + var current_speed := linear_velocity.dot(forward) + var target_speed := input2v.y * drive_speed + var accel := drive_accel if abs(input2v.y) > 0.01 else brake_strength + var new_forward_speed := move_toward(current_speed, target_speed, accel * state.step) + var forward_vel := forward * new_forward_speed + var lateral_vel := linear_velocity - (forward * current_speed) + lateral_vel = lateral_vel.move_toward(Vector3.ZERO, lateral_damp * state.step) + linear_velocity = forward_vel + lateral_vel + + var speed_factor: float = clamp(abs(new_forward_speed) / drive_speed, 0.0, 1.0) + var target_turn: float = -input2v.x * turn_speed * speed_factor + angular_velocity.y = move_toward(angular_velocity.y, target_turn, turn_accel * state.step) + +func _enter_vehicle(player: Node) -> void: + if seat == null: + return + _driver = player + player.call("enter_vehicle", self, seat, car_camera) + if car_camera: + car_camera.current = true + +func _exit_vehicle() -> void: + if _driver == null: + return + _driver.call("exit_vehicle", exit_point, car_camera) + _driver = null + if car_camera: + car_camera.current = false + +func _on_interact_body_entered(body: Node) -> void: + if body.has_method("enter_vehicle"): + _nearby_driver = body + +func _on_interact_body_exited(body: Node) -> void: + if body == _nearby_driver: + _nearby_driver = null diff --git a/game/scenes/Vehicles/car.gd.uid b/game/scenes/Vehicles/car.gd.uid new file mode 100644 index 0000000..d1fac37 --- /dev/null +++ b/game/scenes/Vehicles/car.gd.uid @@ -0,0 +1 @@ +uid://4qf5yinepytc diff --git a/game/scenes/Vehicles/car.tscn b/game/scenes/Vehicles/car.tscn new file mode 100644 index 0000000..9d1fd51 --- /dev/null +++ b/game/scenes/Vehicles/car.tscn @@ -0,0 +1,43 @@ +[gd_scene load_steps=6 format=3] + +[ext_resource type="Script" path="res://scenes/Vehicles/car.gd" id="1_kbd20"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_7r1j6"] +size = Vector3(1.4, 0.9, 2.6) + +[sub_resource type="BoxShape3D" id="BoxShape3D_jk0m1"] +size = Vector3(2.2, 2.0, 3.8) + +[sub_resource type="BoxMesh" id="BoxMesh_4y8xk"] +size = Vector3(1.4, 0.9, 2.6) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_red"] +albedo_color = Color(0.85, 0.1, 0.1, 1) + +[node name="Car" type="RigidBody3D"] +script = ExtResource("1_kbd20") +seat_path = NodePath("Seat") +exit_path = NodePath("Exit") +camera_path = NodePath("CarCamera") +interact_area_path = NodePath("InteractArea") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("BoxShape3D_7r1j6") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("BoxMesh_4y8xk") +surface_material_override/0 = SubResource("StandardMaterial3D_red") + +[node name="InteractArea" type="Area3D" parent="."] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="InteractArea"] +shape = SubResource("BoxShape3D_jk0m1") + +[node name="Seat" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0, 0.6, 0.0) + +[node name="Exit" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.3, 0.0, 0.0) + +[node name="CarCamera" type="Camera3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0, 2.0, 4.2) diff --git a/game/scenes/player.gd b/game/scenes/player.gd index 6036e9f..cc6e206 100644 --- a/game/scenes/player.gd +++ b/game/scenes/player.gd @@ -20,11 +20,14 @@ var current_number_of_jumps := 0 var _pending_mouse_delta := Vector2.ZERO var _last_move_forward := Vector3(0, 0, 1) var _last_move_right := Vector3(1, 0, 0) -var _camera_offset_local := Vector3.ZERO -var _camera_yaw := 0.0 -var _camera_pitch := 0.0 - -@export var camera_follow_speed := 10.0 +var _camera_offset_local := Vector3.ZERO +var _camera_yaw := 0.0 +var _camera_pitch := 0.0 +var _in_vehicle := false +var _vehicle_collision_layer := 0 +var _vehicle_collision_mask := 0 + +@export var camera_follow_speed := 10.0 var jump_sound = preload("res://assets/audio/jump.ogg") var audio_player = AudioStreamPlayer.new() @@ -35,7 +38,7 @@ var audio_player = AudioStreamPlayer.new() @onready var phone: CanvasLayer = get_node(phone_path) if phone_path != NodePath("") else null var phone_visible := false -func _ready() -> void: +func _ready() -> void: axis_lock_angular_x = true axis_lock_angular_z = true angular_damp = 6.0 @@ -44,7 +47,7 @@ func _ready() -> void: add_child(audio_player) audio_player.stream = jump_sound audio_player.volume_db = -20 - if cam: + if cam: _camera_offset_local = cam.transform.origin _camera_pitch = cam.rotation.x _camera_yaw = global_transform.basis.get_euler().y @@ -58,11 +61,16 @@ func _ready() -> void: right.y = 0.0 if forward.length() > 0.0001: _last_move_forward = forward.normalized() - if right.length() > 0.0001: - _last_move_right = right.normalized() - -func _integrate_forces(state): - if cameraMoveMode and _pending_mouse_delta != Vector2.ZERO: + if right.length() > 0.0001: + _last_move_right = right.normalized() + _vehicle_collision_layer = collision_layer + _vehicle_collision_mask = collision_mask + +func _integrate_forces(state): + if _in_vehicle: + linear_velocity = Vector3.ZERO + return + if cameraMoveMode and _pending_mouse_delta != Vector2.ZERO: rotation_x -= _pending_mouse_delta.y * mouse_sensitivity rotation_y -= _pending_mouse_delta.x * mouse_sensitivity rotation_x = clamp(rotation_x, deg_to_rad(-90), deg_to_rad(90)) # Prevent flipping @@ -126,8 +134,10 @@ func _integrate_forces(state): cam.global_position = cam.global_position.lerp(target_pos, camera_follow_speed * state.step) cam.global_rotation = Vector3(_camera_pitch, _camera_yaw, 0.0) -func _input(event): - if event is InputEventMouseButton: +func _input(event): + if _in_vehicle: + return + if event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_MIDDLE: if event.pressed: cameraMoveMode = true @@ -148,7 +158,33 @@ func _input(event): if event.is_action_pressed("player_light"): $SpotLight3D.visible = !$SpotLight3D.visible -func zoom_camera(factor): - var new_fov = cam.fov * factor - cam.fov = clamp(new_fov, MIN_FOV, MAX_FOV) +func zoom_camera(factor): + var new_fov = cam.fov * factor + cam.fov = clamp(new_fov, MIN_FOV, MAX_FOV) + +func enter_vehicle(_vehicle: Node, seat: Node3D, vehicle_camera: Camera3D) -> void: + _in_vehicle = true + freeze = true + sleeping = true + collision_layer = 0 + collision_mask = 0 + if seat: + global_transform = seat.global_transform + if cam: + cam.current = false + if vehicle_camera: + vehicle_camera.current = true + +func exit_vehicle(exit_point: Node3D, vehicle_camera: Camera3D) -> void: + _in_vehicle = false + freeze = false + sleeping = false + collision_layer = _vehicle_collision_layer + collision_mask = _vehicle_collision_mask + if exit_point: + global_transform = exit_point.global_transform + if vehicle_camera: + vehicle_camera.current = false + if cam: + cam.current = true From aef117bcf99b704a8b9e550bb5f9d6b6a85591f2 Mon Sep 17 00:00:00 2001 From: hz Date: Wed, 21 Jan 2026 18:16:04 -0600 Subject: [PATCH 2/2] enhancing car behavior --- README.md | 8 + game/scenes/Characters/repo_bot.gd | 41 ++-- game/scenes/Characters/repo_bot.tscn | 7 +- game/scenes/Levels/level.tscn | 316 ++++++++++++++------------- game/scenes/Vehicles/car.gd | 21 ++ game/scenes/player.gd | 15 +- 6 files changed, 232 insertions(+), 176 deletions(-) diff --git a/README.md b/README.md index 7da274e..43c7c04 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,12 @@ - `SUPER/SUPER` - Super User - `test1/test1` - Super User - `test3/test3` - User + +## Controls +- Move: WASD +- Jump: Space +- Interact (enter/exit car): E +- Flashlight: F +- Phone: Tab +- Pause menu: Esc diff --git a/game/scenes/Characters/repo_bot.gd b/game/scenes/Characters/repo_bot.gd index 7d0dd39..e789b09 100644 --- a/game/scenes/Characters/repo_bot.gd +++ b/game/scenes/Characters/repo_bot.gd @@ -3,8 +3,9 @@ extends Node3D @export var left_pupil_path: NodePath = NodePath("Body/HeadPivot/EyeLeft/Pupil") @export var right_pupil_path: NodePath = NodePath("Body/HeadPivot/EyeRight/Pupil") @export var camera_path: NodePath -@export var look_origin_path: NodePath = NodePath("Body/HeadPivot") -@export var look_reference_path: NodePath = NodePath("Body") +@export var look_origin_path: NodePath = NodePath("Body/HeadPivot") +@export var look_reference_path: NodePath = NodePath("Body") +@export var look_target_path: NodePath = NodePath("") @export var lock_vertical: bool = true @export var vertical_unlock_height: float = 0.6 @export var vertical_lock_smooth_speed: float = 6.0 @@ -28,10 +29,11 @@ var _head: Node3D var _head_base_rot: Vector3 var _vertical_lock_factor: float = 1.0 var _vertical_hold_timer: float = 0.0 -var _look_reference: Node3D +var _look_reference: Node3D +var _look_target: Node3D -func _ready() -> void: +func _ready() -> void: _left_pupil = get_node_or_null(left_pupil_path) as Node3D _right_pupil = get_node_or_null(right_pupil_path) as Node3D if _left_pupil: @@ -39,9 +41,10 @@ func _ready() -> void: if _right_pupil: _right_base = _right_pupil.position _camera = _resolve_camera() - _look_origin = get_node_or_null(look_origin_path) as Node3D - _look_reference = get_node_or_null(look_reference_path) as Node3D - _head = get_node_or_null(head_path) as Node3D + _look_origin = get_node_or_null(look_origin_path) as Node3D + _look_reference = get_node_or_null(look_reference_path) as Node3D + _look_target = get_node_or_null(look_target_path) as Node3D + _head = get_node_or_null(head_path) as Node3D if _head: _head_base_rot = _head.rotation @@ -54,15 +57,21 @@ func _process(_delta: float) -> void: _update_pupils() -func _update_pupils() -> void: - if _camera == null or not _camera.is_inside_tree(): - _camera = _resolve_camera() - if _camera == null: - return - var origin := _look_origin - if origin == null: - origin = self - var target := _camera.global_position +func _update_pupils() -> void: + if _look_target == null and look_target_path != NodePath(""): + _look_target = get_node_or_null(look_target_path) as Node3D + if _look_target == null: + var viewport_cam := get_viewport().get_camera_3d() + if viewport_cam != null and viewport_cam != _camera: + _camera = viewport_cam + elif _camera == null or not _camera.is_inside_tree(): + _camera = _resolve_camera() + if _look_target == null and _camera == null: + return + var origin := _look_origin + if origin == null: + origin = self + var target := _look_target.global_position if _look_target != null else _camera.global_position var dir_world := target - origin.global_position if dir_world.length_squared() <= 0.0001: return diff --git a/game/scenes/Characters/repo_bot.tscn b/game/scenes/Characters/repo_bot.tscn index a0e09a1..af9475a 100644 --- a/game/scenes/Characters/repo_bot.tscn +++ b/game/scenes/Characters/repo_bot.tscn @@ -57,7 +57,12 @@ height = 1.1 [node name="RepoBot" type="Node3D"] script = ExtResource("1_repo_bot") -[node name="Body" type="StaticBody3D" parent="."] +[node name="Body" type="RigidBody3D" parent="."] +mass = 1.5 +axis_lock_angular_x = true +axis_lock_angular_z = true +angular_damp = 8.0 +linear_damp = 0.5 [node name="CollisionShape3D" type="CollisionShape3D" parent="Body"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.55, 0) diff --git a/game/scenes/Levels/level.tscn b/game/scenes/Levels/level.tscn index 777f49a..73cf7bc 100644 --- a/game/scenes/Levels/level.tscn +++ b/game/scenes/Levels/level.tscn @@ -1,77 +1,78 @@ [gd_scene load_steps=18 format=3 uid="uid://dchj6g2i8ebph"] - -[ext_resource type="Script" uid="uid://brgmxhhhtakja" path="res://scenes/Levels/level.gd" id="1_a4mo8"] -[ext_resource type="PackedScene" uid="uid://bb6hj6l23043x" path="res://assets/models/human.blend" id="1_eg4yq"] -[ext_resource type="Script" uid="uid://bpxggc8nr6tf6" path="res://scenes/player.gd" id="1_muv8p"] + +[ext_resource type="Script" uid="uid://brgmxhhhtakja" path="res://scenes/Levels/level.gd" id="1_a4mo8"] +[ext_resource type="PackedScene" uid="uid://bb6hj6l23043x" path="res://assets/models/human.blend" id="1_eg4yq"] +[ext_resource type="Script" uid="uid://bpxggc8nr6tf6" path="res://scenes/player.gd" id="1_muv8p"] [ext_resource type="PackedScene" uid="uid://c5of6aaxop1hl" path="res://scenes/block.tscn" id="2_tc7dm"] [ext_resource type="Script" uid="uid://b7fopt7sx74g8" path="res://scenes/Levels/menu.gd" id="3_tc7dm"] [ext_resource type="PackedScene" path="res://scenes/Characters/repo_bot.tscn" id="4_repo"] [ext_resource type="PackedScene" path="res://scenes/Vehicles/car.tscn" id="5_car"] - -[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_2q6dc"] -bounce = 0.5 - -[sub_resource type="SphereShape3D" id="SphereShape3D_2q6dc"] - -[sub_resource type="SphereMesh" id="SphereMesh_w7c3h"] - -[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_w8frs"] -bounce = 0.5 - -[sub_resource type="SphereShape3D" id="SphereShape3D_mx8sn"] - -[sub_resource type="BoxShape3D" id="BoxShape3D_2q6dc"] -size = Vector3(1080, 2, 1080) - -[sub_resource type="BoxMesh" id="BoxMesh_w7c3h"] -size = Vector3(1080, 2, 1080) - -[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_fi66n"] - -[sub_resource type="Sky" id="Sky_a4mo8"] -sky_material = SubResource("ProceduralSkyMaterial_fi66n") - -[sub_resource type="Environment" id="Environment_a4mo8"] -background_mode = 2 -sky = SubResource("Sky_a4mo8") -ambient_light_source = 3 - -[node name="Node3D" type="Node3D"] -script = ExtResource("1_a4mo8") - -[node name="human" parent="." instance=ExtResource("1_eg4yq")] - -[node name="RepoBot" parent="." instance=ExtResource("4_repo")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.9426608, 0, -4.4451966) - -[node name="Thing" type="RigidBody3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -3.7986288) -physics_material_override = SubResource("PhysicsMaterial_2q6dc") -gravity_scale = 0.0 -contact_monitor = true -max_contacts_reported = 5 - -[node name="CollisionShape3D" type="CollisionShape3D" parent="Thing"] -shape = SubResource("SphereShape3D_2q6dc") -debug_color = Color(0.29772994, 0.6216631, 0.28140613, 0.41960785) - -[node name="MeshInstance3D" type="MeshInstance3D" parent="Thing"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) -mesh = SubResource("SphereMesh_w7c3h") - + +[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_2q6dc"] +bounce = 0.5 + +[sub_resource type="SphereShape3D" id="SphereShape3D_2q6dc"] + +[sub_resource type="SphereMesh" id="SphereMesh_w7c3h"] + +[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_w8frs"] +bounce = 0.5 + +[sub_resource type="SphereShape3D" id="SphereShape3D_mx8sn"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_2q6dc"] +size = Vector3(1080, 2, 1080) + +[sub_resource type="BoxMesh" id="BoxMesh_w7c3h"] +size = Vector3(1080, 2, 1080) + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_fi66n"] + +[sub_resource type="Sky" id="Sky_a4mo8"] +sky_material = SubResource("ProceduralSkyMaterial_fi66n") + +[sub_resource type="Environment" id="Environment_a4mo8"] +background_mode = 2 +sky = SubResource("Sky_a4mo8") +ambient_light_source = 3 + +[node name="Node3D" type="Node3D"] +script = ExtResource("1_a4mo8") + +[node name="human" parent="." instance=ExtResource("1_eg4yq")] + +[node name="RepoBot" parent="." instance=ExtResource("4_repo")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.9426608, 0, -4.4451966) +look_target_path = NodePath("../Player") + +[node name="Thing" type="RigidBody3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -3.7986288) +physics_material_override = SubResource("PhysicsMaterial_2q6dc") +gravity_scale = 0.0 +contact_monitor = true +max_contacts_reported = 5 + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Thing"] +shape = SubResource("SphereShape3D_2q6dc") +debug_color = Color(0.29772994, 0.6216631, 0.28140613, 0.41960785) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Thing"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) +mesh = SubResource("SphereMesh_w7c3h") + [node name="Player" type="RigidBody3D" parent="."] physics_material_override = SubResource("PhysicsMaterial_w8frs") script = ExtResource("1_muv8p") camera_path = NodePath("Camera3D") phone_path = NodePath("../PhoneUI") - -[node name="CollisionShape3D" type="CollisionShape3D" parent="Player"] -shape = SubResource("SphereShape3D_mx8sn") - -[node name="Camera3D" type="Camera3D" parent="Player"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.31670225, 0) -current = true - + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Player"] +shape = SubResource("SphereShape3D_mx8sn") + +[node name="Camera3D" type="Camera3D" parent="Player"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.31670225, 0) +current = true + [node name="SpotLight3D" type="SpotLight3D" parent="Player"] [node name="Car" parent="." instance=ExtResource("5_car")] @@ -79,96 +80,97 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6, 0, -3) [node name="Ground" type="StaticBody3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) - -[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"] -shape = SubResource("BoxShape3D_2q6dc") - -[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground"] -mesh = SubResource("BoxMesh_w7c3h") - -[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 0.5, 0.8660253, 0, -0.8660253, 0.5, 0, 34, 0) -shadow_enabled = true - -[node name="Starter Blocks" type="Node3D" parent="."] - -[node name="Block" parent="Starter Blocks" instance=ExtResource("2_tc7dm")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.298158, -7.0724635) - -[node name="Block2" parent="Starter Blocks" instance=ExtResource("2_tc7dm")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.63255787, 2.596316, -6.980046) - -[node name="Menu" type="CanvasLayer" parent="."] -process_mode = 3 -visible = false -script = ExtResource("3_tc7dm") - -[node name="PhoneUI" type="CanvasLayer" parent="."] -layer = 5 -visible = false - -[node name="Control" type="Control" parent="PhoneUI"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 - -[node name="PhoneFrame" type="ColorRect" parent="PhoneUI/Control"] -layout_mode = 1 -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -180.0 -offset_top = -320.0 -offset_right = 180.0 -offset_bottom = 320.0 -grow_horizontal = 2 -grow_vertical = 2 -color = Color(0.08, 0.08, 0.1, 1) - -[node name="Control" type="Control" parent="Menu"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 4 -size_flags_vertical = 4 - -[node name="VBoxContainer" type="VBoxContainer" parent="Menu/Control"] -layout_mode = 1 -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -39.5 -offset_top = -33.0 -offset_right = 39.5 -offset_bottom = 33.0 -grow_horizontal = 2 -grow_vertical = 2 - -[node name="ContinueButton" type="Button" parent="Menu/Control/VBoxContainer"] -layout_mode = 2 -text = "Continue" - -[node name="MainMenuButton" type="Button" parent="Menu/Control/VBoxContainer"] -layout_mode = 2 -text = "Main Menu" - -[node name="QuitButton" type="Button" parent="Menu/Control/VBoxContainer"] -layout_mode = 2 -text = "Quit" - -[node name="WorldEnvironment" type="WorldEnvironment" parent="."] -environment = SubResource("Environment_a4mo8") - -[connection signal="pressed" from="Menu/Control/VBoxContainer/ContinueButton" to="Menu" method="_on_continue_button_pressed"] -[connection signal="pressed" from="Menu/Control/VBoxContainer/MainMenuButton" to="Menu" method="_on_main_menu_button_pressed"] -[connection signal="pressed" from="Menu/Control/VBoxContainer/QuitButton" to="Menu" method="_on_quit_button_pressed"] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"] +shape = SubResource("BoxShape3D_2q6dc") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00053596497, 0.0075991154, -0.0019865036) +mesh = SubResource("BoxMesh_w7c3h") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 0.5, 0.8660253, 0, -0.8660253, 0.5, 0, 34, 0) +shadow_enabled = true + +[node name="Starter Blocks" type="Node3D" parent="."] + +[node name="Block" parent="Starter Blocks" instance=ExtResource("2_tc7dm")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.298158, -7.0724635) + +[node name="Block2" parent="Starter Blocks" instance=ExtResource("2_tc7dm")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.63255787, 2.596316, -6.980046) + +[node name="Menu" type="CanvasLayer" parent="."] +process_mode = 3 +visible = false +script = ExtResource("3_tc7dm") + +[node name="Control" type="Control" parent="Menu"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 + +[node name="VBoxContainer" type="VBoxContainer" parent="Menu/Control"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -39.5 +offset_top = -33.0 +offset_right = 39.5 +offset_bottom = 33.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="ContinueButton" type="Button" parent="Menu/Control/VBoxContainer"] +layout_mode = 2 +text = "Continue" + +[node name="MainMenuButton" type="Button" parent="Menu/Control/VBoxContainer"] +layout_mode = 2 +text = "Main Menu" + +[node name="QuitButton" type="Button" parent="Menu/Control/VBoxContainer"] +layout_mode = 2 +text = "Quit" + +[node name="PhoneUI" type="CanvasLayer" parent="."] +layer = 5 +visible = false + +[node name="Control" type="Control" parent="PhoneUI"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="PhoneFrame" type="ColorRect" parent="PhoneUI/Control"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -180.0 +offset_top = -320.0 +offset_right = 180.0 +offset_bottom = 320.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0.08, 0.08, 0.1, 1) + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_a4mo8") + +[connection signal="pressed" from="Menu/Control/VBoxContainer/ContinueButton" to="Menu" method="_on_continue_button_pressed"] +[connection signal="pressed" from="Menu/Control/VBoxContainer/MainMenuButton" to="Menu" method="_on_main_menu_button_pressed"] +[connection signal="pressed" from="Menu/Control/VBoxContainer/QuitButton" to="Menu" method="_on_quit_button_pressed"] diff --git a/game/scenes/Vehicles/car.gd b/game/scenes/Vehicles/car.gd index 9d92881..6a8c0eb 100644 --- a/game/scenes/Vehicles/car.gd +++ b/game/scenes/Vehicles/car.gd @@ -6,6 +6,8 @@ extends RigidBody3D @export var turn_speed := 2.0 @export var turn_accel := 8.0 @export var lateral_damp := 10.0 +@export var launch_impulse := 28.0 +@export var launch_up_impulse := 6.0 @export var seat_path: NodePath @export var exit_path: NodePath @export var camera_path: NodePath @@ -27,6 +29,8 @@ func _ready() -> void: interact_area.body_exited.connect(_on_interact_body_exited) if car_camera: car_camera.current = false + contact_monitor = true + max_contacts_reported = 8 func _process(_delta: float) -> void: if _driver == null and _nearby_driver != null and Input.is_action_just_pressed("interact"): @@ -56,6 +60,23 @@ func _integrate_forces(state: PhysicsDirectBodyState3D) -> void: var target_turn: float = -input2v.x * turn_speed * speed_factor angular_velocity.y = move_toward(angular_velocity.y, target_turn, turn_accel * state.step) + if speed_factor > 0.2: + var hit_ids := {} + for i in state.get_contact_count(): + var collider := state.get_contact_collider_object(i) + if collider is RigidBody3D and collider != self: + var collider_id := (collider as Node).get_instance_id() + if hit_ids.has(collider_id): + continue + hit_ids[collider_id] = true + var contact_pos := state.get_contact_collider_position(i) + var launch_dir := (contact_pos - global_position).normalized() + if launch_dir.length() <= 0.001: + var normal_world := (global_transform.basis * state.get_contact_local_normal(i)).normalized() + launch_dir = normal_world if normal_world.length() > 0.001 else forward.normalized() + var impulse := launch_dir * (launch_impulse * speed_factor) + Vector3.UP * launch_up_impulse + (collider as RigidBody3D).apply_central_impulse(impulse) + func _enter_vehicle(player: Node) -> void: if seat == null: return diff --git a/game/scenes/player.gd b/game/scenes/player.gd index cc6e206..7daecf0 100644 --- a/game/scenes/player.gd +++ b/game/scenes/player.gd @@ -26,6 +26,9 @@ var _camera_pitch := 0.0 var _in_vehicle := false var _vehicle_collision_layer := 0 var _vehicle_collision_mask := 0 +var _vehicle_original_parent: Node = null +var _light_was_on := false +@onready var _flashlight: SpotLight3D = $SpotLight3D @export var camera_follow_speed := 10.0 @@ -155,8 +158,8 @@ func _input(event): elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN: zoom_camera(ZOOM_FACTOR) # Zoom out - if event.is_action_pressed("player_light"): - $SpotLight3D.visible = !$SpotLight3D.visible + if event.is_action_pressed("player_light"): + _flashlight.visible = !_flashlight.visible func zoom_camera(factor): var new_fov = cam.fov * factor @@ -168,7 +171,11 @@ func enter_vehicle(_vehicle: Node, seat: Node3D, vehicle_camera: Camera3D) -> vo sleeping = true collision_layer = 0 collision_mask = 0 + _vehicle_original_parent = get_parent() + _light_was_on = _flashlight.visible + _flashlight.visible = false if seat: + reparent(seat, true) global_transform = seat.global_transform if cam: cam.current = false @@ -181,6 +188,10 @@ func exit_vehicle(exit_point: Node3D, vehicle_camera: Camera3D) -> void: sleeping = false collision_layer = _vehicle_collision_layer collision_mask = _vehicle_collision_mask + if _vehicle_original_parent: + reparent(_vehicle_original_parent, true) + _vehicle_original_parent = null + _flashlight.visible = _light_was_on if exit_point: global_transform = exit_point.global_transform if vehicle_camera: