From 742b79db5208fd5d116762cbc2d6fe0f2faca740 Mon Sep 17 00:00:00 2001 From: Jakob Feldmann Date: Tue, 30 Mar 2021 22:57:34 +0200 Subject: [PATCH] Inertia based movement(broken jumps) --- src/Actor/Actor.gd | 6 ++- src/Actor/Blobby.gd | 76 +++++++++++++++++++++--------- src/Actor/Blobby.tscn.tmp | 74 +++++++++++++++++++++++++++++ src/Actor/PlayerStateMachine.gd | 54 ++++++++++++++++++++-- src/Levels/Level03.tscn.tmp | 82 +++++++++++++++++++++++++++++++++ src/Screens/MainScreen.tscn | 6 +-- 6 files changed, 267 insertions(+), 31 deletions(-) create mode 100644 src/Actor/Blobby.tscn.tmp create mode 100644 src/Levels/Level03.tscn.tmp diff --git a/src/Actor/Actor.gd b/src/Actor/Actor.gd index c857aac..e108a43 100644 --- a/src/Actor/Actor.gd +++ b/src/Actor/Actor.gd @@ -4,6 +4,10 @@ class_name Actor const FLOOR_NORMAL := Vector2.UP export var speed := Vector2(300, 1000) -export var gravity := 9800.0 +# newtonmeters is the unit +export var acceleration_force := Vector2(5000, -2000) +export var gravity := 9810.0 +# Kilograms +export var mass := 5 var _velocity := Vector2.ZERO diff --git a/src/Actor/Blobby.gd b/src/Actor/Blobby.gd index f4569bd..733bd7a 100644 --- a/src/Actor/Blobby.gd +++ b/src/Actor/Blobby.gd @@ -12,22 +12,16 @@ func _on_EnemyDetector_body_entered(body: Node) -> void: die() -func apply_movement(delta: float) -> void: - var is_jump_interrupted := Input.is_action_just_released("jump") and _velocity.y < 0.0 - var direction := get_direction() - _velocity = calculate_move_velocity(_velocity, speed, direction, is_jump_interrupted) - _velocity = move_and_slide(_velocity, FLOOR_NORMAL) +func handle_grounded_movement(delta: float, direction: Vector2) -> Vector2: + return calculate_grounded_velocity(_velocity, delta, speed, direction) -func get_direction() -> Vector2: - return Vector2( - Input.get_action_strength("move_right") - Input.get_action_strength("move_left"), - -1.0 if Input.is_action_just_pressed("jump") and is_on_floor() else 1.0 - ) +func handle_jump_movement(delta: float, direction: Vector2) -> Vector2: + return calculate_jump_velocity(_velocity, delta, speed, direction) -func handle_move_input(): - return null +func handle_fall_movement(delta: float, direction: Vector2) -> Vector2: + return calculate_fall_velocity(_velocity, delta, speed, direction) func apply_gravity(delta, velocity: Vector2): @@ -35,17 +29,51 @@ func apply_gravity(delta, velocity: Vector2): return velocity -func calculate_move_velocity( - linear_velocity: Vector2, speed: Vector2, direction: Vector2, is_jump_interrupted: bool +func calculate_grounded_velocity( + linear_velocity: Vector2, delta: float, speed: Vector2, direction: Vector2 ) -> Vector2: - var out := linear_velocity - out.x = speed.x * direction.x - out = apply_gravity(get_physics_process_delta_time(), out) - if direction.y == -1: - out.y = speed.y * direction.y - if is_jump_interrupted: - out.y = 0 - return out + var out_vel := linear_velocity + # TODO Comments + if direction.x == 0.0: + var deceleration_force = get_ground_friction() * gravity * mass * delta + var velocity_direction = 1.0 + if _velocity.x < 0: + velocity_direction = -1.0 + # Translates velocity back to force and subtracts deceleration force + var result_force = ( + (abs(_velocity.x) * mass) / delta + - deceleration_force + ) + if result_force <= 0: + out_vel.x = 0 + else: + out_vel.x = result_force / mass * delta * velocity_direction + else: + out_vel.x += (delta * ((acceleration_force.x / mass) * direction.x)) + # TODO Is this the right place to determine this? + if is_on_floor(): + var additive_jump_force = -0.1 * abs(_velocity.x) * mass + # The one signals, that I calculated the velocity resulting from 1 second of force applied + out_vel.y = 1 * ((acceleration_force.y + additive_jump_force) / mass) + return out_vel + + +func get_ground_friction() -> float: + return 10.0 + + +func calculate_jump_velocity( + linear_velocity: Vector2, delta: float, speed: Vector2, direction: Vector2 +) -> Vector2: + linear_velocity.y = gravity * delta + return linear_velocity + + +func calculate_fall_velocity( + linear_velocity: Vector2, delta: float, speed: Vector2, direction: Vector2 +) -> Vector2: + linear_velocity.y = gravity * delta + return linear_velocity func calculate_stomp_velocity(linear_velocity: Vector2, impulse: float) -> Vector2: @@ -54,6 +82,10 @@ func calculate_stomp_velocity(linear_velocity: Vector2, impulse: float) -> Vecto return out +func execute_movement() -> void: + _velocity = move_and_slide(_velocity, FLOOR_NORMAL) + + func die() -> void: queue_free() PlayerData.deaths += 1 diff --git a/src/Actor/Blobby.tscn.tmp b/src/Actor/Blobby.tscn.tmp new file mode 100644 index 0000000..7e591b5 --- /dev/null +++ b/src/Actor/Blobby.tscn.tmp @@ -0,0 +1,74 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://start-assets/player.png" type="Texture" id=1] +[ext_resource path="res://src/Actor/PlayerStateMachine.gd" type="Script" id=2] +[ext_resource path="res://src/RayCasters/RayCaster.gd" type="Script" id=3] +[ext_resource path="res://src/RayCasters/RayCastDebugLines.gd" type="Script" id=4] +[ext_resource path="res://src/Actor/Blobby.gd" type="Script" id=5] + +[sub_resource type="RectangleShape2D" id=1] +extents = Vector2( 30.8418, 32 ) + +[sub_resource type="RectangleShape2D" id=2] +extents = Vector2( 30.9321, 24.5597 ) + +[node name="Blobby" type="KinematicBody2D"] +collision_mask = 8 +script = ExtResource( 5 ) +speed = null +gravity = null +stomp_impulse = null + +[node name="Player" type="Sprite" parent="."] +position = Vector2( 0, -32 ) +scale = Vector2( 0.64, 0.64 ) +texture = ExtResource( 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2( 0, -32.2102 ) +shape = SubResource( 1 ) + +[node name="RayCaster" type="Node2D" parent="CollisionShape2D"] +script = ExtResource( 3 ) + +[node name="RayCastDebugLines" type="Line2D" parent="CollisionShape2D/RayCaster"] +script = ExtResource( 4 ) + +[node name="Camera2D" type="Camera2D" parent="."] +visible = false +position = Vector2( 0, -181 ) +current = true +limit_left = 0 +limit_top = 0 +limit_smoothed = true +drag_margin_h_enabled = true +drag_margin_v_enabled = true +smoothing_enabled = true +drag_margin_left = 0.0 +drag_margin_right = 0.0 + +[node name="EnemyDetector" type="Area2D" parent="."] +monitorable = false +collision_mask = 2 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="EnemyDetector"] +modulate = Color( 0.2, 0, 0.494118, 1 ) +position = Vector2( 0, -32.2102 ) +shape = SubResource( 2 ) + +[node name="StateMachine" type="Node" parent="."] +script = ExtResource( 2 ) + +[node name="StateLable" type="Label" parent="."] +margin_left = -31.0 +margin_top = -80.0 +margin_right = 31.0 +margin_bottom = -64.0 +text = "Coochie" +align = 1 +valign = 1 +__meta__ = { +"_edit_use_anchors_": false +} +[connection signal="area_entered" from="EnemyDetector" to="." method="_on_EnemyDetector_area_entered"] +[connection signal="body_entered" from="EnemyDetector" to="." method="_on_EnemyDetector_body_entered"] diff --git a/src/Actor/PlayerStateMachine.gd b/src/Actor/PlayerStateMachine.gd index 2aae43b..3f2b733 100644 --- a/src/Actor/PlayerStateMachine.gd +++ b/src/Actor/PlayerStateMachine.gd @@ -22,20 +22,66 @@ func _state_logic(delta): parent.collision_mask ) + var handle_input_ref + match self.state: "idle": - parent.apply_movement(delta) + handle_input_ref = funcref(self, 'handle_idle_input') "run": - parent.apply_movement(delta) + handle_input_ref = funcref(self, 'handle_run_input') "jump": - parent.apply_movement(delta) + handle_input_ref = funcref(self, 'handle_jump_input') "fall": - parent.apply_movement(delta) + handle_input_ref = funcref(self, 'handle_fall_input') + _: + print("don't panik") + + parent._velocity = handle_input_ref.call_func(delta) + parent.execute_movement() + + +func handle_idle_input(delta, direction := get_direction()) -> Vector2: + return parent.handle_grounded_movement(delta, direction) + + +func handle_run_input(delta, direction := get_direction()) -> Vector2: + return parent.handle_grounded_movement(delta, direction) + + +func handle_jump_input(delta, direction := get_direction()) -> Vector2: + return parent.handle_jump_movement(delta, direction) + + +func handle_fall_input(delta, direction := get_direction()) -> Vector2: + return parent.handle_fall_movement(delta, direction) + + +func get_direction() -> Vector2: + return Vector2( + ( + Input.get_action_strength("move_right") + - Input.get_action_strength("move_left") + ), + -1.0 if Input.is_action_pressed("jump") else 1.0 + ) # Determines which state should be active at the moment func _get_transition(delta): parent.get_node("StateLable").text = self.state + var new_state + if ! parent.is_on_floor(): + if parent._velocity.y < 0: + new_state = states.jump + if parent._velocity.y > 0: + new_state = states.fall + elif parent._velocity.x != 0: + new_state = states.run + else: + # TODO How does this apply to enviornment induced movement? + new_state = states.idle + if new_state != self.state: + return new_state return null diff --git a/src/Levels/Level03.tscn.tmp b/src/Levels/Level03.tscn.tmp new file mode 100644 index 0000000..6468e0e --- /dev/null +++ b/src/Levels/Level03.tscn.tmp @@ -0,0 +1,82 @@ +[gd_scene load_steps=9 format=2] + +[ext_resource path="res://src/Actor/Blobby.tscn" type="PackedScene" id=1] +[ext_resource path="res://start-assets/tileset.tres" type="TileSet" id=2] +[ext_resource path="res://src/Actor/Enemy.tscn" type="PackedScene" id=3] +[ext_resource path="res://start-assets/background.png" type="Texture" id=4] +[ext_resource path="res://src/Objects/Coin.tscn" type="PackedScene" id=5] +[ext_resource path="res://src/UserInterface/UserInterface.tscn" type="PackedScene" id=6] +[ext_resource path="res://src/UserInterface/EndsScreen.tscn" type="PackedScene" id=7] +[ext_resource path="res://src/Objects/Portal.tscn" type="PackedScene" id=8] + +[node name="Level03" type="Node2D"] + +[node name="UserInterface" type="CanvasLayer" parent="."] + +[node name="UserInterface" parent="UserInterface" instance=ExtResource( 6 )] + +[node name="BackgroundLayer" type="CanvasLayer" parent="."] +layer = -1 + +[node name="background" type="TextureRect" parent="BackgroundLayer"] +anchor_right = 1.016 +anchor_bottom = 1.0 +margin_right = -0.384033 +texture = ExtResource( 4 ) +expand = true +stretch_mode = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource( 2 ) +cell_size = Vector2( 80, 80 ) +collision_layer = 8 +collision_mask = 0 +format = 1 +tile_data = PoolIntArray( -1048576, 0, 0, -1048564, 0, 0, -983040, 0, 0, -983028, 0, 0, -917504, 0, 0, -917492, 0, 0, -851968, 0, 0, -851956, 0, 0, -786432, 0, 0, -786420, 0, 0, -720896, 0, 0, -720884, 0, 0, -655360, 0, 0, -655348, 0, 0, -589824, 0, 0, -589812, 0, 0, -524288, 0, 0, -524276, 0, 0, -458752, 0, 0, -458740, 0, 0, -393216, 0, 0, -393215, 0, 0, -393214, 0, 0, -393213, 0, 0, -393204, 0, 0, -327680, 0, 0, -327668, 0, 0, -262144, 0, 0, -262132, 0, 0, -196608, 0, 0, -196607, 0, 0, -196606, 0, 0, -196605, 0, 0, -196596, 0, 0, -131072, 0, 0, -131060, 0, 0, -65536, 0, 0, -65524, 0, 0, 0, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 12, 0, 0, 65536, 0, 0, 65544, 0, 0, 65548, 0, 0, 131072, 0, 0, 131084, 0, 0, 196608, 0, 0, 196620, 0, 0, 262144, 0, 0, 262149, 0, 0, 262154, 0, 0, 262155, 0, 0, 262156, 0, 0, 327680, 0, 0, 327681, 0, 0, 327692, 0, 0, 393216, 0, 0, 393228, 0, 0, 458752, 0, 0, 458753, 0, 0, 458754, 0, 0, 458755, 0, 0, 458756, 0, 0, 458757, 0, 0, 458758, 0, 0, 458759, 0, 0, 458760, 0, 0, 458761, 0, 0, 458762, 0, 0, 458763, 0, 0, 458764, 0, 0, 524288, 0, 0, 524289, 0, 0, 524290, 0, 0, 524291, 0, 0, 524292, 0, 0, 524293, 0, 0, 524294, 0, 0, 524295, 0, 0, 524296, 0, 0, 524297, 0, 0, 524298, 0, 0, 524299, 0, 0, 524300, 0, 0, 589824, 0, 0, 589825, 0, 0, 589826, 0, 0, 589827, 0, 0, 589828, 0, 0, 589829, 0, 0, 589830, 0, 0, 589831, 0, 0, 589832, 0, 0, 589833, 0, 0, 589834, 0, 0, 589835, 0, 0, 589836, 0, 0 ) + +[node name="Blobby" parent="." instance=ExtResource( 1 )] +position = Vector2( 300, 560 ) + +[node name="CollisionShape2D" parent="Blobby" index="1"] +position = Vector2( 0.224487, -32.0436 ) + +[node name="Camera2D" parent="Blobby" index="2"] +position = Vector2( 390.714, -75 ) +limit_top = -10000 +limit_right = 1040 +limit_bottom = 700 +drag_margin_h_enabled = false +smoothing_enabled = false +editor_draw_limits = true + +[node name="EnemyDetector" parent="Blobby" index="3"] +position = Vector2( 14.6832, -44.0497 ) + +[node name="CollisionShape2D" parent="Blobby/EnemyDetector" index="0"] +position = Vector2( -14.4587, 12.8269 ) + +[node name="Enemy" parent="." instance=ExtResource( 3 )] +position = Vector2( 715.5, 560 ) + +[node name="Coin" parent="." instance=ExtResource( 5 )] +position = Vector2( 592, 352 ) + +[node name="coin" parent="Coin" index="0"] +position = Vector2( 0, 3 ) + +[node name="CollisionShape2D" parent="Coin" index="1"] +position = Vector2( 0, 3 ) + +[node name="Coin2" parent="." instance=ExtResource( 5 )] +position = Vector2( 749, 274 ) + +[node name="Portal" parent="." instance=ExtResource( 8 )] +position = Vector2( 130.332, -461.479 ) +next_scene = ExtResource( 7 ) + +[editable path="Blobby"] + +[editable path="Coin"] diff --git a/src/Screens/MainScreen.tscn b/src/Screens/MainScreen.tscn index c824d0b..d0a3c2f 100644 --- a/src/Screens/MainScreen.tscn +++ b/src/Screens/MainScreen.tscn @@ -7,10 +7,8 @@ [ext_resource path="res://start-assets/ui_theme.tres" type="Theme" id=5] [node name="MainScreen" type="Control"] -anchor_right = 1.25 -anchor_bottom = 1.2 -margin_right = -256.0 -margin_bottom = -120.0 +anchor_right = 1.0 +anchor_bottom = 1.0 theme = ExtResource( 5 ) __meta__ = { "_edit_use_anchors_": false