Skip to content

Instantly share code, notes, and snippets.

@YeOldeDM
Last active November 9, 2017 01:20
Show Gist options
  • Save YeOldeDM/32162a21db1b7994cb5e6e8b4fbb2066 to your computer and use it in GitHub Desktop.
Save YeOldeDM/32162a21db1b7994cb5e6e8b4fbb2066 to your computer and use it in GitHub Desktop.
extends KinematicBody2D
const FLOOR_ANGLE = 0
const WALL_ANGLE = 90
const CEIL_ANGLE = 180
var GRAVITY = 360
var FALL_RATE = 3.0
var FLOOR_MOVE_FORCE = 800
var AIR_MOVE_FORCE = 700
var MAX_SPEED = 200
var FLOOR_STOP_FORCE = 600
var AIR_STOP_FORCE = 250
var JUMP_FORCE = 300
var DOUBLE_JUMP_FORCE = 250
var DOUBLE_JUMP_VERTICAL_DAMP = 0.25
var JUMP_STOP_FORCE = 750
var JUMP_MAX_AIR_TIME = 0.2
var JUMP_MIN_AIR_TIME = 0.05
var WALL_SLIDE_DAMPING = 0.8
# Current actual velocity
var velocity = Vector2()
# Time spent airborne in sec
var airtime = 0
var jump_count = 0
# States
var can_move = true # D-pad input registers for movement
var facing = 1 setget _set_facing
var on_wall = false
var pressed = {
"JUMP": false,
"SHOOT": false,
}
var sliding_on = {
"FLOOR": false,
"WALL": false,
"CEILING": false,
}
func is_in_air():
return self.airtime >= JUMP_MIN_AIR_TIME
func _ready():
set_fixed_process(true)
func _fixed_process(delta):
### SETUP ###
var new_facing = self.facing
# Create force
var G = GRAVITY
if velocity.y > 5: G *= FALL_RATE
var force = Vector2(0, G * int( is_in_air() ) )
### INPUT ###
# Grab input
var LEFT = Input.is_action_pressed("LEFT")
var RIGHT = Input.is_action_pressed("RIGHT")
var UP = Input.is_action_pressed("UP")
var DOWN = Input.is_action_pressed("DOWN")
var JUMP = Input.is_action_pressed("JUMP")
var SHOOT = Input.is_action_pressed("SHOOT")
# Covert directional input into a Vector
var INPUT = Vector2( RIGHT - LEFT, DOWN - UP )
var vsign = sign(velocity.x)
var vlen = abs(velocity.x)
### FORCES ###
# Define Aceleration/Deceleration to use
var A = AIR_MOVE_FORCE if is_in_air() else FLOOR_MOVE_FORCE
var D = AIR_STOP_FORCE if is_in_air() else FLOOR_STOP_FORCE
# If we can move and horizontal input is positive
if can_move and abs(INPUT.x) == 1:
# Acelerate up to max speed or change direction
if vlen < MAX_SPEED or sign(INPUT.x) != sign(velocity.x):
# Integrate horizontal input into force
force.x += INPUT.x * A
# Define new facing if needed
if INPUT.x != 0: new_facing = INPUT.x
else:
# decelerate toward zero speed
vlen = max( 0, vlen - ( D * delta ) )
velocity.x = vlen * vsign
# Jump, and Double-Jump
if !on_wall and jump_count < 2 and JUMP and !pressed.JUMP:
jump_count += 1
var F = [JUMP_FORCE, DOUBLE_JUMP_FORCE][jump_count-1]
velocity.y = -F
if jump_count == 2:
velocity.x *= DOUBLE_JUMP_VERTICAL_DAMP
# Kill vertical movement if JUMP control is let go
if velocity.y < 0 and is_in_air() and !JUMP:
velocity.y = min( 0, velocity.y + JUMP_STOP_FORCE )
### DIRECT MOTION ###
# Integrate force into velocity
velocity += force * delta
# Turn velocity into motion
var motion = move( velocity * delta )
### COLLISION HANDLING ###
if is_colliding():
var N = get_collision_normal()
var on_floor = rad2deg(acos(N.dot(Vector2(0, -1))))
if on_floor <= FLOOR_ANGLE:
airtime = 0
jump_count = 0
# Wall Slide
# elif on_floor <= WALL_ANGLE and !JUMP:
# velocity.x = 0
# velocity.y *= WALL_SLIDE_DAMPING
elif on_floor <= CEIL_ANGLE:
velocity.y = 0
self.on_wall = on_floor == WALL_ANGLE
motion = N.slide( motion )
move(motion)
if new_facing != self.facing:
self.facing = new_facing
airtime += delta
pressed.JUMP = JUMP
pressed.SHOOT = SHOOT
func _set_facing( what ):
facing = what
get_node("Sprite").set_scale( Vector2( facing, 1 ) )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment