mirror of
https://github.com/GDQuest/godot-platformer-2d.git
synced 2026-07-17 16:34:54 +00:00
Merge pull request #12 from guilhermehto/pilot-tutorial-demo
Pilot tutorial demo added
This commit is contained in:
commit
fe5a745d7d
10 changed files with 377 additions and 0 deletions
27
prototypes/3.rigidbody-vs-kinematicbody-movement/Game.gd
Normal file
27
prototypes/3.rigidbody-vs-kinematicbody-movement/Game.gd
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
extends Node
|
||||
|
||||
const PLAYERS := [
|
||||
preload("res://player/kinematic/KinematicPlayer.tscn"),
|
||||
preload("res://player/rigid/RigidPlayer.tscn")
|
||||
]
|
||||
|
||||
var _player : Node2D
|
||||
var _player_index := 0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_player = _spawn_player()
|
||||
|
||||
|
||||
func _unhandled_key_input(event: InputEventKey) -> void:
|
||||
if event.is_action_pressed("switch_player"):
|
||||
_player.queue_free()
|
||||
_player = _spawn_player()
|
||||
|
||||
|
||||
func _spawn_player() -> Node:
|
||||
var player := PLAYERS[_player_index].instance() as Node
|
||||
add_child(player)
|
||||
player.global_position = Vector2(1920 / 2.0, 1080 / 2.0)
|
||||
_player_index = (_player_index + 1) % 2
|
||||
return player
|
||||
35
prototypes/3.rigidbody-vs-kinematicbody-movement/Game.tscn
Normal file
35
prototypes/3.rigidbody-vs-kinematicbody-movement/Game.tscn
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://Game.gd" type="Script" id=1]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 25, 25 )
|
||||
|
||||
[node name="Game" type="Node"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="Map" type="Node2D" parent="."]
|
||||
|
||||
[node name="StaticBody2D" type="StaticBody2D" parent="Map"]
|
||||
editor/display_folded = true
|
||||
|
||||
[node name="CollisionPolygon2D2" type="CollisionPolygon2D" parent="Map/StaticBody2D"]
|
||||
position = Vector2( 320, 256 )
|
||||
polygon = PoolVector2Array( 736, 640, 960, 640, 960, 608, 736, 608 )
|
||||
|
||||
[node name="CollisionPolygon2D3" type="CollisionPolygon2D" parent="Map/StaticBody2D"]
|
||||
polygon = PoolVector2Array( 0, 960, 1920, 960, 1920, 1152, 0, 1152 )
|
||||
|
||||
[node name="CollisionPolygon2D4" type="CollisionPolygon2D" parent="Map/StaticBody2D"]
|
||||
polygon = PoolVector2Array( 128, 960, 128, 128, 1792, 128, 1792, 960, 1920, 960, 1920, 0, 0, 0, 0, 960 )
|
||||
|
||||
[node name="PushBox" type="RigidBody2D" parent="Map"]
|
||||
editor/display_folded = true
|
||||
position = Vector2( 448, 905.6 )
|
||||
__meta__ = {
|
||||
"_edit_group_": true
|
||||
}
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Map/PushBox"]
|
||||
shape = SubResource( 1 )
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
[gd_resource type="Environment" load_steps=2 format=2]
|
||||
|
||||
[sub_resource type="ProceduralSky" id=1]
|
||||
|
||||
[resource]
|
||||
background_mode = 2
|
||||
background_sky = SubResource( 1 )
|
||||
|
||||
BIN
prototypes/3.rigidbody-vs-kinematicbody-movement/icon.png
Normal file
BIN
prototypes/3.rigidbody-vs-kinematicbody-movement/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
|
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icon.png"
|
||||
dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
extends KinematicBody2D
|
||||
|
||||
onready var _transitions := {
|
||||
IDLE: [RUN, AIR],
|
||||
RUN: [IDLE, AIR],
|
||||
AIR: [IDLE, LEDGE],
|
||||
LEDGE: [IDLE],
|
||||
}
|
||||
|
||||
const FLOOR_NORMAL := Vector2.UP
|
||||
|
||||
enum {
|
||||
IDLE,
|
||||
RUN,
|
||||
AIR,
|
||||
LEDGE
|
||||
}
|
||||
|
||||
export var speed_ground := 500.0
|
||||
export var jump_force := 900.0
|
||||
export var gravity := 3000.0
|
||||
|
||||
export var air_acceleration := 3000.0
|
||||
export var air_max_speed := 700.0
|
||||
|
||||
var _velocity := Vector2.ZERO
|
||||
var _state : int = IDLE
|
||||
|
||||
var states_strings := {
|
||||
IDLE: "idle",
|
||||
RUN: "run",
|
||||
AIR: "air",
|
||||
LEDGE: "ledge",
|
||||
}
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("jump") and is_on_floor():
|
||||
_velocity.y -= jump_force
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
var move_direction := get_move_direction()
|
||||
|
||||
# Horizontal movement
|
||||
match _state:
|
||||
IDLE:
|
||||
if move_direction.x:
|
||||
change_state(RUN)
|
||||
|
||||
RUN:
|
||||
if not move_direction.x:
|
||||
change_state(IDLE)
|
||||
_velocity.x = move_direction.x * speed_ground
|
||||
|
||||
AIR:
|
||||
_velocity.x += air_acceleration * move_direction.x * delta
|
||||
if abs(_velocity.x) > air_max_speed:
|
||||
_velocity.x = air_max_speed * sign(_velocity.x)
|
||||
|
||||
_velocity.y += gravity * delta
|
||||
_velocity = move_and_slide(_velocity, Vector2.UP)
|
||||
|
||||
# State updates after movement
|
||||
if is_on_floor() and _state == AIR:
|
||||
change_state(IDLE)
|
||||
if not is_on_floor() and _state in [IDLE, RUN]:
|
||||
change_state(AIR)
|
||||
|
||||
|
||||
func change_state(target_state: int) -> void:
|
||||
if not target_state in _transitions[_state]:
|
||||
return
|
||||
_state = target_state
|
||||
enter_state()
|
||||
|
||||
|
||||
func enter_state() -> void:
|
||||
match _state:
|
||||
IDLE:
|
||||
_velocity.x = 0.0
|
||||
_:
|
||||
return
|
||||
|
||||
|
||||
func get_move_direction() -> Vector2:
|
||||
return Vector2(
|
||||
Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
|
||||
Input.get_action_strength("aim_down") - Input.get_action_strength("aim_up")
|
||||
)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://player/kinematic/KinematicPlayer.gd" type="Script" id=1]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 30, 30 )
|
||||
|
||||
[node name="KinematicPlayer" type="KinematicBody2D"]
|
||||
editor/display_folded = true
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
position = Vector2( 0, -1 )
|
||||
shape = SubResource( 1 )
|
||||
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
extends RigidBody2D
|
||||
|
||||
onready var just_aired_timer : Timer = $JustAiredTimer
|
||||
onready var _transitions: = {
|
||||
IDLE: [RUN, AIR],
|
||||
RUN: [IDLE, AIR],
|
||||
AIR: [IDLE],
|
||||
}
|
||||
|
||||
const FLOOR_NORMAL := Vector2.UP
|
||||
|
||||
enum {
|
||||
IDLE,
|
||||
RUN,
|
||||
AIR,
|
||||
}
|
||||
|
||||
export var move_speed := 400.0
|
||||
export var air_speed := 10.0
|
||||
export var jump_force := 500.0
|
||||
|
||||
var _state: int = IDLE
|
||||
|
||||
var states_strings := {
|
||||
IDLE: "idle",
|
||||
RUN: "run",
|
||||
AIR: "air",
|
||||
}
|
||||
|
||||
var current_hook_target := Vector2()
|
||||
|
||||
|
||||
func _integrate_forces(state: Physics2DDirectBodyState) -> void:
|
||||
var is_on_ground := state.get_contact_count() > 0 and int(state.get_contact_collider_position(0).y) >= int(global_position.y)
|
||||
|
||||
var move_direction := get_move_direction()
|
||||
|
||||
match _state:
|
||||
IDLE:
|
||||
if move_direction.x:
|
||||
change_state(RUN)
|
||||
elif is_on_ground and Input.is_action_just_pressed("jump"):
|
||||
apply_central_impulse(Vector2.UP * jump_force)
|
||||
change_state(AIR)
|
||||
|
||||
RUN:
|
||||
if not move_direction.x:
|
||||
change_state(IDLE)
|
||||
elif state.get_contact_count() == 0:
|
||||
change_state(AIR)
|
||||
elif is_on_ground and Input.is_action_just_pressed("jump"):
|
||||
apply_central_impulse(Vector2.UP * jump_force)
|
||||
change_state(AIR)
|
||||
else:
|
||||
state.linear_velocity.x = move_direction.x * move_speed
|
||||
|
||||
AIR:
|
||||
if move_direction.x:
|
||||
state.linear_velocity.x += move_direction.x * air_speed
|
||||
if is_on_ground and just_aired_timer.is_stopped():
|
||||
change_state(IDLE)
|
||||
|
||||
|
||||
func change_state(target_state: int) -> void:
|
||||
if not target_state in _transitions[_state]:
|
||||
return
|
||||
_state = target_state
|
||||
enter_state()
|
||||
|
||||
|
||||
func enter_state() -> void:
|
||||
match _state:
|
||||
IDLE:
|
||||
linear_velocity.x = 0
|
||||
AIR:
|
||||
# Prevents the state to change back to IDLE as ground is still
|
||||
# detected one to two frames after getting air
|
||||
just_aired_timer.start()
|
||||
_:
|
||||
return
|
||||
|
||||
|
||||
func get_move_direction() -> Vector2:
|
||||
return Vector2(
|
||||
Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
|
||||
Input.get_action_strength("aim_down") - Input.get_action_strength("aim_up")
|
||||
)
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
[gd_scene load_steps=4 format=2]
|
||||
|
||||
[ext_resource path="res://player/rigid/RigidPlayer.gd" type="Script" id=1]
|
||||
|
||||
[sub_resource type="PhysicsMaterial" id=2]
|
||||
friction = 0.5
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 30, 30 )
|
||||
|
||||
[node name="RigidPlayer" type="RigidBody2D"]
|
||||
mode = 2
|
||||
physics_material_override = SubResource( 2 )
|
||||
gravity_scale = 8.5
|
||||
contacts_reported = 1
|
||||
contact_monitor = true
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="JustAiredTimer" type="Timer" parent="."]
|
||||
wait_time = 0.15
|
||||
one_shot = true
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
; 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=4
|
||||
|
||||
_global_script_classes=[ ]
|
||||
_global_script_class_icons={
|
||||
|
||||
}
|
||||
|
||||
[application]
|
||||
|
||||
config/name="RigidBody2D vs KinematicBody2D Character"
|
||||
run/main_scene="res://Game.tscn"
|
||||
config/icon="res://icon.png"
|
||||
|
||||
[display]
|
||||
|
||||
window/size/width=1920
|
||||
window/size/height=1080
|
||||
window/size/test_width=1280
|
||||
window/size/test_height=720
|
||||
window/stretch/mode="2d"
|
||||
window/stretch/aspect="keep"
|
||||
|
||||
[input]
|
||||
|
||||
move_left={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_right={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
jump={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
switch_player={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":82,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[rendering]
|
||||
|
||||
environment/default_environment="res://default_env.tres"
|
||||
Loading…
Add table
Add a link
Reference in a new issue