Compare commits

...

5 Commits

Author SHA1 Message Date
Ervan Lefevre 3edebcef32 💄 Player's orientation now follows its state (climb etc) 2 years ago
Ervan Lefevre c88c71ff29 🔧 Adds export config 2 years ago
Ervan Lefevre f2aa44de97 You can now grab obstacles 2 years ago
Ervan Lefevre e1855c4719 NPC now dies when reaching rising level 2 years ago
Ervan Lefevre 478b5b9c60 Adds NPCFactory that populates the level 2 years ago
  1. 242
      export_presets.cfg
  2. 15
      nodes/npc/npc.gd
  3. 6
      nodes/npc/npc.tscn
  4. 20
      nodes/npc_factory/npc_factory.gd
  5. 9
      nodes/npc_factory/npc_factory.tscn
  6. 14
      nodes/obstacle/obstacle.gd
  7. 6
      nodes/obstacle/obstacle.tscn
  8. 98
      nodes/player/player.gd
  9. 11
      nodes/player/player.tscn
  10. 38
      project.godot
  11. 46
      scenes/poc.tscn
  12. 3
      scripts/gameplay/rising_level.gd

@ -0,0 +1,242 @@
[preset.0]
name="Linux/X11"
platform="Linux/X11"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="../exports/ld54_Ant_Underwater_Odyssey/unix/ld54.x86_64"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
[preset.0.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
binary_format/embed_pck=true
texture_format/bptc=true
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
binary_format/architecture="x86_64"
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="#!/usr/bin/env bash
export DISPLAY=:0
unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
\"{temp_dir}/{exe_name}\" {cmd_args}"
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")
rm -rf \"{temp_dir}\""
[preset.1]
name="macOS"
platform="macOS"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="../exports/ld54_Ant_Underwater_Odyssey/macos/ld54.dmg"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
[preset.1.options]
export/distribution_type=0
binary_format/architecture="universal"
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
application/icon=""
application/icon_interpolation=4
application/bundle_identifier="com.redgems.ld54"
application/signature=""
application/app_category="Games"
application/short_version="1.0"
application/version="1.0"
application/copyright=""
application/copyright_localized={}
application/min_macos_version="10.12"
display/high_res=true
xcode/platform_build="14C18"
xcode/sdk_version="13.1"
xcode/sdk_build="22C55"
xcode/sdk_name="macosx13.1"
xcode/xcode_version="1420"
xcode/xcode_build="14C18"
codesign/codesign=3
codesign/installer_identity=""
codesign/apple_team_id=""
codesign/identity=""
codesign/entitlements/custom_file=""
codesign/entitlements/allow_jit_code_execution=false
codesign/entitlements/allow_unsigned_executable_memory=false
codesign/entitlements/allow_dyld_environment_variables=false
codesign/entitlements/disable_library_validation=false
codesign/entitlements/audio_input=false
codesign/entitlements/camera=false
codesign/entitlements/location=false
codesign/entitlements/address_book=false
codesign/entitlements/calendars=false
codesign/entitlements/photos_library=false
codesign/entitlements/apple_events=false
codesign/entitlements/debugging=false
codesign/entitlements/app_sandbox/enabled=false
codesign/entitlements/app_sandbox/network_server=false
codesign/entitlements/app_sandbox/network_client=false
codesign/entitlements/app_sandbox/device_usb=false
codesign/entitlements/app_sandbox/device_bluetooth=false
codesign/entitlements/app_sandbox/files_downloads=0
codesign/entitlements/app_sandbox/files_pictures=0
codesign/entitlements/app_sandbox/files_music=0
codesign/entitlements/app_sandbox/files_movies=0
codesign/entitlements/app_sandbox/helper_executables=[]
codesign/custom_options=PackedStringArray()
notarization/notarization=0
privacy/microphone_usage_description=""
privacy/microphone_usage_description_localized={}
privacy/camera_usage_description=""
privacy/camera_usage_description_localized={}
privacy/location_usage_description=""
privacy/location_usage_description_localized={}
privacy/address_book_usage_description=""
privacy/address_book_usage_description_localized={}
privacy/calendar_usage_description=""
privacy/calendar_usage_description_localized={}
privacy/photos_library_usage_description=""
privacy/photos_library_usage_description_localized={}
privacy/desktop_folder_usage_description=""
privacy/desktop_folder_usage_description_localized={}
privacy/documents_folder_usage_description=""
privacy/documents_folder_usage_description_localized={}
privacy/downloads_folder_usage_description=""
privacy/downloads_folder_usage_description_localized={}
privacy/network_volumes_usage_description=""
privacy/network_volumes_usage_description_localized={}
privacy/removable_volumes_usage_description=""
privacy/removable_volumes_usage_description_localized={}
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="#!/usr/bin/env bash
unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
open \"{temp_dir}/{exe_name}.app\" --args {cmd_args}"
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
kill $(pgrep -x -f \"{temp_dir}/{exe_name}.app/Contents/MacOS/{exe_name} {cmd_args}\")
rm -rf \"{temp_dir}\""
[preset.2]
name="Windows Desktop"
platform="Windows Desktop"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="../exports/ld54_Ant_Underwater_Odyssey/win/ld54.exe"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
[preset.2.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
binary_format/embed_pck=true
texture_format/bptc=true
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
binary_format/architecture="x86_64"
codesign/enable=false
codesign/timestamp=true
codesign/timestamp_server_url=""
codesign/digest_algorithm=1
codesign/description=""
codesign/custom_options=PackedStringArray()
application/modify_resources=true
application/icon=""
application/console_wrapper_icon=""
application/icon_interpolation=4
application/file_version=""
application/product_version=""
application/company_name=""
application/product_name=""
application/file_description=""
application/copyright=""
application/trademarks=""
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}'
$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}'
$trigger = New-ScheduledTaskTrigger -Once -At 00:00
$settings = New-ScheduledTaskSettingsSet
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings
Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true
Start-ScheduledTask -TaskName godot_remote_debug
while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 }
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue"
ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
Remove-Item -Recurse -Force '{temp_dir}'"
[preset.3]
name="Web"
platform="Web"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="../exports/ld54_Ant_Underwater_Odyssey/web/ld54.html"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
[preset.3.options]
custom_template/debug=""
custom_template/release=""
variant/extensions_support=false
vram_texture_compression/for_desktop=true
vram_texture_compression/for_mobile=false
html/export_icon=true
html/custom_html_shell=""
html/head_include=""
html/canvas_resize_policy=2
html/focus_canvas_on_start=true
html/experimental_virtual_keyboard=false
progressive_web_app/enabled=false
progressive_web_app/offline_page=""
progressive_web_app/display=1
progressive_web_app/orientation=0
progressive_web_app/icon_144x144=""
progressive_web_app/icon_180x180=""
progressive_web_app/icon_512x512=""
progressive_web_app/background_color=Color(0, 0, 0, 1)

@ -5,10 +5,11 @@ class_name Npc
const SPEED = 100
const MINIMUM_STATE_DURATION = 3
const STATES = ['panic']
const STATES = ['panic', 'dead']
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var direction = 0
var rising_speed = 0
func _ready():
pick_new_direction()
@ -31,5 +32,17 @@ func panic_state(delta):
velocity.y += gravity * delta
move_and_slide()
func on_enter_dead_state():
$shape.queue_free()
func dead_state(_delta):
velocity = Vector2(0, -rising_speed * (randf_range(0.9,1)))
move_and_slide()
func die(level_speed):
$fsm.set_next_state('dead')
rising_speed = level_speed
func pick_new_direction():
direction = [1,-1][randi_range(0,1)] * SPEED

@ -5,10 +5,10 @@
[ext_resource type="Script" path="res://scripts/ia/fsm.gd" id="3_vhp64"]
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_f223n"]
radius = 4.0
height = 14.0
radius = 1.0
height = 4.0
[node name="npc" type="CharacterBody2D"]
[node name="npc" type="CharacterBody2D" groups=["npc"]]
script = ExtResource("1_38jh5")
[node name="shape" type="CollisionShape2D" parent="."]

@ -0,0 +1,20 @@
extends Node2D
class_name NpcFactory
@export var NPC_SCENE: PackedScene
@export var SPAWN_DELAY: float = 0.5
var current_spawn_duration = 0
func _ready():
if !NPC_SCENE:
push_error("npc scene is null")
func _physics_process(delta):
current_spawn_duration += delta
if current_spawn_duration > SPAWN_DELAY:
current_spawn_duration = 0
var npc = NPC_SCENE.instantiate()
add_child(npc)

@ -0,0 +1,9 @@
[gd_scene load_steps=3 format=3 uid="uid://b2hu7kxvxvgc1"]
[ext_resource type="Script" path="res://nodes/npc_factory/npc_factory.gd" id="1_p5cuf"]
[ext_resource type="PackedScene" uid="uid://dvx48q5ecyxjs" path="res://nodes/npc/npc.tscn" id="2_exj6u"]
[node name="npc_factory" type="Node2D"]
script = ExtResource("1_p5cuf")
NPC_SCENE = ExtResource("2_exj6u")
SPAWN_DELAY = 2.0

@ -0,0 +1,14 @@
extends RigidBody2D
class_name Obstacle
@onready var original_parent = get_parent()
func grabbed(by):
$shape.disabled = true
gravity_scale = 0
reparent(by)
func dropped():
$shape.disabled = false
gravity_scale = 1
reparent(original_parent)

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://clclsblongqty"]
[ext_resource type="Script" path="res://nodes/obstacle/obstacle.gd" id="1_g75rs"]
[node name="obstacle" type="RigidBody2D" groups=["obstacle"]]
script = ExtResource("1_g75rs")

@ -6,12 +6,12 @@ const SPEED = 100.0
const JUMP_VELOCITY = 200.0
const STATES= [
"spawn",
"idle",
"walk",
"climb",
"die",
"idle",
"jump",
"die"
"spawn",
"walk"
]
var use_gravity = {
@ -23,9 +23,24 @@ var use_gravity = {
"walk": true
}
var can_grab_obstacles = {
"climb": false,
"die": false,
"idle": true,
"jump": false,
"spawn": false,
"walk": true
}
@onready var grab_ray = get_node('oriented_container/grab_ray')
@onready var sprite = get_node('oriented_container/sprite')
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var grabbed_obstacle = null
func _ready():
$fsm.set_states(STATES)
add_to_group("player")
@ -37,18 +52,18 @@ func on_enter_idle_state():
pass
func idle_state(_delta):
var direction = Input.get_axis("ui_left", "ui_right")
var direction = Input.get_axis("player_left", "player_right")
if is_on_floor():
velocity.x = 0
if direction:
$fsm.set_next_state("walk")
elif Input.is_action_just_pressed("ui_accept") and is_on_floor():
elif Input.is_action_just_pressed("player_jump") and is_on_floor():
$fsm.set_next_state("jump")
func walk_state(_delta):
var direction = Input.get_axis("ui_left", "ui_right")
var direction = Input.get_axis("player_left", "player_right")
if direction != 0:
velocity.x = direction * SPEED
@ -56,10 +71,10 @@ func walk_state(_delta):
velocity.x = 0
$fsm.set_next_state("idle")
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
if Input.is_action_just_pressed("player_jump") and is_on_floor():
$fsm.set_next_state("jump")
if is_on_wall() or (Input.is_action_pressed('ui_up') && is_on_ceiling()):
if is_on_wall() or (Input.is_action_pressed('player_up') && is_on_ceiling()):
velocity.y = 0
$fsm.set_next_state("climb")
@ -68,7 +83,7 @@ func on_enter_jump_state():
velocity.y = -JUMP_VELOCITY
func jump_state(_delta):
var direction = Input.get_axis("ui_left", "ui_right")
var direction = Input.get_axis("player_left", "player_right")
if(direction):
velocity.x = move_toward(velocity.x, direction * SPEED, SPEED)
@ -80,32 +95,32 @@ func jump_state(_delta):
velocity.x = 0
$fsm.set_next_state("idle")
if is_on_wall() || (is_on_ceiling() and Input.is_action_pressed("ui_up")):
if is_on_wall() || (is_on_ceiling() and Input.is_action_pressed("player_up")):
$fsm.set_next_state("climb")
func on_enter_climb_state():
$sprite.modulate = Color(1, 0, 0)
sprite.modulate = Color(1, 0, 0)
velocity = Vector2(0, 0)
func on_exit_climb_state():
$sprite.modulate = Color(1, 1, 1)
sprite.modulate = Color(1, 1, 1)
func climb_state(_delta):
if is_on_wall():
var direction = Input.get_axis("ui_up", "ui_down")
var direction = Input.get_axis("player_up", "player_down")
velocity = Vector2(0, direction * SPEED)
if is_on_ceiling():
var direction = Input.get_axis("ui_left", "ui_right")
var direction = Input.get_axis("player_left", "player_right")
velocity = Vector2(direction * SPEED, 0)
if Input.is_action_just_pressed("ui_accept") and is_on_wall():
if Input.is_action_just_pressed("player_jump") and is_on_wall():
var wall_position = get_slide_collision(0).get_normal().x
var jump_normal = Vector2(wall_position, -0.5).normalized()
velocity = jump_normal * JUMP_VELOCITY
$fsm.set_next_state("jump")
if is_on_ceiling() && Input.is_action_just_pressed("ui_down"):
if is_on_ceiling() && Input.is_action_just_pressed("player_down"):
velocity.y = 0
$fsm.set_next_state("idle")
@ -119,6 +134,55 @@ func after_state(delta):
if use_gravity[$fsm.current_state] == true:
velocity.y += gravity * delta
if can_grab_obstacles[$fsm.current_state] == true:
handle_grab()
handle_sprite_orientation()
func handle_grab():
if Input.is_action_just_pressed('player_action'):
if grabbed_obstacle == null:
var collision = grab_ray.get_collider()
print('collision', collision)
if collision:
var obstacle = collision
print('obstacle', obstacle)
if obstacle.is_in_group("obstacle"):
do_grab(obstacle)
else:
drop_obstacle()
func do_grab(obstacle):
grabbed_obstacle = obstacle
obstacle.grabbed($oriented_container)
func drop_obstacle():
grabbed_obstacle.dropped()
grabbed_obstacle = null
func handle_sprite_orientation():
# rotates oriented_container to face
# the direction of the velocity
# if is_on_wall, rotated regarding velocity.y, with up by default
# if is_on_ceiling, rotated regarding velocity.x, with right by default
if is_on_wall_only():
if velocity.y != 0:
$oriented_container.rotation = PI/2 if (velocity.y > 0) else - PI / 2
var wall_position = get_slide_collision(0).get_position().x
var player_position = $oriented_container.get_global_position().x
var should_flip_with_wall_left = (wall_position > player_position) && (velocity.y > 0)
var should_flip_with_wall_right = (wall_position < player_position) && (velocity.y < 0)
sprite.flip_v = should_flip_with_wall_left || should_flip_with_wall_right
elif is_on_ceiling():
if velocity.x != 0:
$oriented_container.rotation = PI if (velocity.x > 0) else -PI
else:
if velocity.x != 0:
$oriented_container.rotation = 0 if (velocity.x > 0) else PI
sprite.flip_v = velocity.x < 0
func die():
$fsm.set_next_state("die")

@ -15,9 +15,6 @@ script = ExtResource("1_exx2i")
script = ExtResource("2_ix1o4")
root = NodePath("..")
[node name="sprite" type="Sprite2D" parent="."]
texture = ExtResource("1_s33dc")
[node name="shape" type="CollisionShape2D" parent="."]
rotation = 1.5708
shape = SubResource("CapsuleShape2D_w17ly")
@ -25,3 +22,11 @@ metadata/_edit_group_ = true
[node name="camera" type="Camera2D" parent="."]
zoom = Vector2(5, 5)
[node name="oriented_container" type="Node2D" parent="."]
[node name="grab_ray" type="RayCast2D" parent="oriented_container"]
target_position = Vector2(24, 0)
[node name="sprite" type="Sprite2D" parent="oriented_container"]
texture = ExtResource("1_s33dc")

@ -23,6 +23,44 @@ window/size/mode=2
window/size/initial_screen=1
window/stretch/mode="viewport"
[input]
player_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":4194319,"key_label":0,"unicode":0,"echo":false,"script":null)
, 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":113,"echo":false,"script":null)
]
}
player_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,"echo":false,"script":null)
, 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":4194321,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
player_up={
"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":4194320,"key_label":0,"unicode":0,"echo":false,"script":null)
, 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":122,"echo":false,"script":null)
]
}
player_down={
"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,"echo":false,"script":null)
, 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":4194322,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
player_action={
"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":69,"key_label":0,"unicode":101,"echo":false,"script":null)
, 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":4194326,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
player_jump={
"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":32,"key_label":0,"unicode":32,"echo":false,"script":null)
]
}
[rendering]
renderer/rendering_method="gl_compatibility"

File diff suppressed because one or more lines are too long

@ -14,3 +14,6 @@ func _physics_process(delta):
func _body_entered(body):
if body.is_in_group("player"):
body.die()
if body.is_in_group("npc"):
body.die(RISING_SPEED)

Loading…
Cancel
Save