Merge pull request #445 from aaronfranke/kc2d

Organize and simplify the Kinematic Character 2D demo
This commit is contained in:
Aaron Franke
2020-03-15 12:04:51 -04:00
committed by GitHub
19 changed files with 70 additions and 91 deletions

View File

@@ -1,4 +1,4 @@
# Kinematic Character
# Kinematic Character 2D
Example of how to make a kinematic character controller in 2D using
[`KinematicBody2D`](https://docs.godotengine.org/en/latest/classes/class_kinematicbody2d.html).

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/circle.png-10953cad44a8947fbdd4128a631e9e52.stex"
path="res://.import/circle.png-65a28e998f412b3cddff971e28b7d768.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://circle.png"
dest_files=[ "res://.import/circle.png-10953cad44a8947fbdd4128a631e9e52.stex" ]
source_file="res://level/circle.png"
dest_files=[ "res://.import/circle.png-65a28e998f412b3cddff971e28b7d768.stex" ]
[params]

View File

Before

Width:  |  Height:  |  Size: 480 B

After

Width:  |  Height:  |  Size: 480 B

View File

@@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/long_obstacle.png-1b33440a15b4db156b2a9ec7e9a2a80e.stex"
path="res://.import/long_obstacle.png-d70ee394f796e1de9a423783aa84ec5d.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://long_obstacle.png"
dest_files=[ "res://.import/long_obstacle.png-1b33440a15b4db156b2a9ec7e9a2a80e.stex" ]
source_file="res://level/long_obstacle.png"
dest_files=[ "res://.import/long_obstacle.png-d70ee394f796e1de9a423783aa84ec5d.stex" ]
[params]

View File

Before

Width:  |  Height:  |  Size: 468 B

After

Width:  |  Height:  |  Size: 468 B

View File

@@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/obstacle.png-dfb3e99d3af573251007cdf5e1c252b9.stex"
path="res://.import/obstacle.png-06287f6b2d26dd03335fd87ab78c2cc2.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://obstacle.png"
dest_files=[ "res://.import/obstacle.png-dfb3e99d3af573251007cdf5e1c252b9.stex" ]
source_file="res://level/obstacle.png"
dest_files=[ "res://.import/obstacle.png-06287f6b2d26dd03335fd87ab78c2cc2.stex" ]
[params]

View File

@@ -0,0 +1,5 @@
extends Node
func _on_body_entered(body):
if body.name == "Player":
$"../WinText".show()

View File

Before

Width:  |  Height:  |  Size: 495 B

After

Width:  |  Height:  |  Size: 495 B

View File

@@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/princess.png-9b4caf2cfe324ae3734249d5b559d39d.stex"
path="res://.import/princess.png-359cb1d8a4fd115119b22ac7899e2787.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://princess.png"
dest_files=[ "res://.import/princess.png-9b4caf2cfe324ae3734249d5b559d39d.stex" ]
source_file="res://level/princess.png"
dest_files=[ "res://.import/princess.png-359cb1d8a4fd115119b22ac7899e2787.stex" ]
[params]

View File

@@ -1,57 +0,0 @@
extends KinematicBody2D
# Angle in degrees towards either side that the player can consider "floor".
const FLOOR_ANGLE_TOLERANCE = 40
const WALK_FORCE = 600
const WALK_MIN_SPEED = 10
const WALK_MAX_SPEED = 200
const STOP_FORCE = 1300
const JUMP_SPEED = 200
const JUMP_MAX_AIRBORNE_TIME = 0.2
const SLIDE_STOP_VELOCITY = 1.0 # Pixels/second
const SLIDE_STOP_MIN_TRAVEL = 1.0 # Pixels
var velocity = Vector2()
var on_air_time = 100
var jumping = false
var prev_jump_pressed = false
onready var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
func _physics_process(delta):
var force = Vector2(0, gravity)
var walk = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
var jump = Input.is_action_pressed("jump")
if (velocity.x <= WALK_MIN_SPEED and velocity.x > -WALK_MAX_SPEED) or (velocity.x >= -WALK_MIN_SPEED and velocity.x < WALK_MAX_SPEED):
force.x += WALK_FORCE * walk
if abs(walk) < 0.5:
var vsign = sign(velocity.x)
var vlen = abs(velocity.x)
vlen -= STOP_FORCE * delta
if vlen < 0:
vlen = 0
velocity.x = vlen * vsign
# Integrate forces to velocity.
velocity += force * delta
# Integrate velocity into motion and move.
velocity = move_and_slide(velocity, Vector2.UP)
if is_on_floor():
on_air_time = 0
if jumping and velocity.y > 0:
# If falling, no longer jumping.
jumping = false
if on_air_time < JUMP_MAX_AIRBORNE_TIME and jump and not prev_jump_pressed and not jumping:
# Jump must also be allowed to happen if the character left the floor a little bit ago.
# Makes controls more snappy.
velocity.y = -JUMP_SPEED
jumping = true
on_air_time += delta
prev_jump_pressed = jump

View File

@@ -0,0 +1,32 @@
extends KinematicBody2D
const WALK_FORCE = 600
const WALK_MAX_SPEED = 200
const STOP_FORCE = 1300
const JUMP_SPEED = 200
var velocity = Vector2()
onready var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
func _physics_process(delta):
# Horizontal movement code. First, get the player's input.
var walk = WALK_FORCE * (Input.get_action_strength("move_right") - Input.get_action_strength("move_left"))
# Slow down the player if they're not trying to move.
if abs(walk) < WALK_FORCE * 0.2:
# The velocity, slowed down a bit, and then reassigned.
velocity.x = move_toward(velocity.x, 0, STOP_FORCE * delta)
else:
velocity.x += walk * delta
# Clamp to the maximum horizontal movement speed.
velocity.x = clamp(velocity.x, -WALK_MAX_SPEED, WALK_MAX_SPEED)
# Vertical movement code. Apply gravity.
velocity.y += gravity * delta
# Move based on the velocity and snap to the ground.
velocity = move_and_slide_with_snap(velocity, Vector2.DOWN, Vector2.UP)
# Check for jumping. is_on_floor() must be called after movement code.
if is_on_floor() and Input.is_action_just_pressed("jump"):
velocity.y = -JUMP_SPEED

View File

Before

Width:  |  Height:  |  Size: 502 B

After

Width:  |  Height:  |  Size: 502 B

View File

@@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/player.png-2dd0af52de4b213777cd8c9df94c0978.stex"
path="res://.import/player.png-1ad27fc2a62fa126eae918723933dd6f.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://player.png"
dest_files=[ "res://.import/player.png-2dd0af52de4b213777cd8c9df94c0978.stex" ]
source_file="res://player/player.png"
dest_files=[ "res://.import/player.png-1ad27fc2a62fa126eae918723933dd6f.stex" ]
[params]

View File

@@ -1,7 +1,7 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://player.gd" type="Script" id=1]
[ext_resource path="res://player.png" type="Texture" id=2]
[ext_resource path="res://player/player.gd" type="Script" id=1]
[ext_resource path="res://player/player.png" type="Texture" id=2]
[sub_resource type="RectangleShape2D" id=1]
extents = Vector2( 7, 7 )

View File

@@ -15,7 +15,7 @@ _global_script_class_icons={
[application]
config/name="Kinematic Character"
config/name="Kinematic Character 2D"
run/main_scene="res://world.tscn"
config/icon="res://icon.png"

View File

@@ -1,6 +0,0 @@
extends Node2D
func _on_princess_body_enter(body):
# The name of this editor-generated callback is unfortunate.
if body.get_name() == "Player":
$WinText.show()

View File

@@ -1,11 +1,11 @@
[gd_scene load_steps=19 format=2]
[ext_resource path="res://world.gd" type="Script" id=1]
[ext_resource path="res://obstacle.png" type="Texture" id=2]
[ext_resource path="res://player.tscn" type="PackedScene" id=3]
[ext_resource path="res://princess.png" type="Texture" id=4]
[ext_resource path="res://circle.png" type="Texture" id=5]
[ext_resource path="res://long_obstacle.png" type="Texture" id=6]
[ext_resource path="res://level/obstacle.png" type="Texture" id=2]
[ext_resource path="res://player/player.tscn" type="PackedScene" id=3]
[ext_resource path="res://level/princess.png" type="Texture" id=4]
[ext_resource path="res://level/circle.png" type="Texture" id=5]
[ext_resource path="res://level/long_obstacle.png" type="Texture" id=6]
[ext_resource path="res://level/princess.gd" type="Script" id=7]
[sub_resource type="RectangleShape2D" id=1]
extents = Vector2( 8, 8 )
@@ -19,6 +19,11 @@ extents = Vector2( 8, 8 )
0/tile_mode = 0
0/occluder_offset = Vector2( 0, 0 )
0/navigation_offset = Vector2( 0, 0 )
0/shape_offset = Vector2( 8, 8 )
0/shape_transform = Transform2D( 1, 0, 0, 1, 8, 8 )
0/shape = SubResource( 1 )
0/shape_one_way = false
0/shape_one_way_margin = 1.0
0/shapes = [ {
"autotile_coord": Vector2( 0, 0 ),
"one_way": false,
@@ -112,7 +117,6 @@ extents = Vector2( 8, 8 )
extents = Vector2( 32, 8 )
[node name="World" type="Node2D"]
script = ExtResource( 1 )
[node name="TileMap" type="TileMap" parent="."]
tile_set = SubResource( 2 )
@@ -154,6 +158,7 @@ anims/updown = SubResource( 6 )
[node name="Princess" type="Area2D" parent="."]
position = Vector2( 97, 72 )
script = ExtResource( 7 )
[node name="Collision" type="CollisionShape2D" parent="Princess"]
shape = SubResource( 7 )
@@ -261,4 +266,4 @@ shape = SubResource( 12 )
[node name="Camera2D" type="Camera2D" parent="."]
offset = Vector2( 265, 247 )
current = true
[connection signal="body_entered" from="Princess" to="." method="_on_princess_body_enter"]
[connection signal="body_entered" from="Princess" to="Princess" method="_on_body_entered"]

View File

@@ -14,7 +14,7 @@ onready var gun = $Sprite/Gun
func _ready():
# Static types are necessary to avoid
# Static types are necessary here to avoid warnings.
var camera: Camera2D = $Camera
if action_suffix == "_p1":
camera.custom_viewport = $"../.."