mirror of
https://github.com/godotengine/godot.git
synced 2024-12-15 10:12:40 +08:00
8f4b6ff870
Deleted the var GRAVITY because it is unused. The gravity is used at line 237, but it's gotten from the Physics2DDirectBodyState parameter.
262 lines
5.8 KiB
GDScript
262 lines
5.8 KiB
GDScript
extends RigidBody2D
|
|
|
|
# Character Demo, written by Juan Linietsky.
|
|
#
|
|
# Implementation of a 2D Character controller.
|
|
# This implementation uses the physics engine for
|
|
# controlling a character, in a very similar way
|
|
# than a 3D character controller would be implemented.
|
|
#
|
|
# Using the physics engine for this has the main
|
|
# advantages:
|
|
# -Easy to write.
|
|
# -Interaction with other physics-based objects is free
|
|
# -Only have to deal with the object linear velocity, not position
|
|
# -All collision/area framework available
|
|
#
|
|
# But also has the following disadvantages:
|
|
#
|
|
# -Objects may bounce a little bit sometimes
|
|
# -Going up ramps sends the chracter flying up, small hack is needed.
|
|
# -A ray collider is needed to avoid sliding down on ramps and
|
|
# undesiderd bumps, small steps and rare numerical precision errors.
|
|
# (another alternative may be to turn on friction when the character is not moving).
|
|
# -Friction cant be used, so floor velocity must be considered
|
|
# for moving platforms.
|
|
|
|
var anim=""
|
|
var siding_left=false
|
|
var jumping=false
|
|
var stopping_jump=false
|
|
var shooting=false
|
|
|
|
var WALK_ACCEL = 800.0
|
|
var WALK_DEACCEL= 800.0
|
|
var WALK_MAX_VELOCITY= 200.0
|
|
var AIR_ACCEL = 200.0
|
|
var AIR_DEACCEL= 200.0
|
|
var JUMP_VELOCITY=460
|
|
var STOP_JUMP_FORCE=900.0
|
|
|
|
var MAX_FLOOR_AIRBORNE_TIME = 0.15
|
|
|
|
var airborne_time=1e20
|
|
var shoot_time=1e20
|
|
|
|
var MAX_SHOOT_POSE_TIME = 0.3
|
|
|
|
var bullet = preload("res://bullet.xml")
|
|
|
|
var floor_h_velocity=0.0
|
|
var enemy
|
|
|
|
func _integrate_forces(s):
|
|
|
|
|
|
|
|
var lv = s.get_linear_velocity()
|
|
var step = s.get_step()
|
|
|
|
var new_anim=anim
|
|
var new_siding_left=siding_left
|
|
|
|
|
|
# Get the controls
|
|
var move_left = Input.is_action_pressed("move_left")
|
|
var move_right = Input.is_action_pressed("move_right")
|
|
var jump = Input.is_action_pressed("jump")
|
|
var shoot = Input.is_action_pressed("shoot")
|
|
var spawn = Input.is_action_pressed("spawn")
|
|
|
|
if spawn:
|
|
var e = enemy.instance()
|
|
var p = get_pos()
|
|
p.y = p.y - 100
|
|
e.set_pos(p)
|
|
get_parent().add_child(e)
|
|
|
|
|
|
#deapply prev floor velocity
|
|
lv.x-=floor_h_velocity
|
|
floor_h_velocity=0.0
|
|
|
|
|
|
# Find the floor (a contact with upwards facing collision normal)
|
|
var found_floor=false
|
|
var floor_index=-1
|
|
|
|
for x in range(s.get_contact_count()):
|
|
|
|
var ci = s.get_contact_local_normal(x)
|
|
if (ci.dot(Vector2(0,-1))>0.6):
|
|
found_floor=true
|
|
floor_index=x
|
|
|
|
# A good idea when impementing characters of all kinds,
|
|
# Compensates for physics imprecission, as well as human
|
|
# reaction delay.
|
|
|
|
if (shoot and not shooting):
|
|
shoot_time=0
|
|
var bi = bullet.instance()
|
|
var ss
|
|
if (siding_left):
|
|
ss=-1.0
|
|
else:
|
|
ss=1.0
|
|
var pos = get_pos() + get_node("bullet_shoot").get_pos()*Vector2(ss,1.0)
|
|
|
|
bi.set_pos(pos)
|
|
get_parent().add_child(bi)
|
|
|
|
bi.set_linear_velocity( Vector2(800.0*ss,-80) )
|
|
get_node("sprite/smoke").set_emitting(true)
|
|
get_node("sound").play("shoot")
|
|
PS2D.body_add_collision_exception(bi.get_rid(),get_rid()) # make bullet and this not collide
|
|
|
|
|
|
else:
|
|
shoot_time+=step
|
|
|
|
|
|
if (found_floor):
|
|
airborne_time=0.0
|
|
else:
|
|
airborne_time+=step #time it spent in the air
|
|
|
|
var on_floor = airborne_time < MAX_FLOOR_AIRBORNE_TIME
|
|
|
|
# Process jump
|
|
if (jumping):
|
|
if (lv.y>0):
|
|
#set off the jumping flag if going down
|
|
jumping=false
|
|
elif (not jump):
|
|
stopping_jump=true
|
|
|
|
if (stopping_jump):
|
|
lv.y+=STOP_JUMP_FORCE*step
|
|
|
|
if (on_floor):
|
|
|
|
# Process logic when character is on floor
|
|
|
|
if (move_left and not move_right):
|
|
if (lv.x > -WALK_MAX_VELOCITY):
|
|
lv.x-=WALK_ACCEL*step
|
|
elif (move_right and not move_left):
|
|
if (lv.x < WALK_MAX_VELOCITY):
|
|
lv.x+=WALK_ACCEL*step
|
|
else:
|
|
var xv = abs(lv.x)
|
|
xv-=WALK_DEACCEL*step
|
|
if (xv<0):
|
|
xv=0
|
|
lv.x=sign(lv.x)*xv
|
|
|
|
#Check jump
|
|
if (not jumping and jump):
|
|
lv.y=-JUMP_VELOCITY
|
|
jumping=true
|
|
stopping_jump=false
|
|
get_node("sound").play("jump")
|
|
|
|
#check siding
|
|
|
|
if (lv.x < 0 and move_left):
|
|
new_siding_left=true
|
|
elif (lv.x > 0 and move_right):
|
|
new_siding_left=false
|
|
if (jumping):
|
|
new_anim="jumping"
|
|
elif (abs(lv.x)<0.1):
|
|
if (shoot_time<MAX_SHOOT_POSE_TIME):
|
|
new_anim="idle_weapon"
|
|
else:
|
|
new_anim="idle"
|
|
else:
|
|
if (shoot_time<MAX_SHOOT_POSE_TIME):
|
|
new_anim="run_weapon"
|
|
else:
|
|
new_anim="run"
|
|
else:
|
|
|
|
# Process logic when the character is in the air
|
|
|
|
if (move_left and not move_right):
|
|
if (lv.x > -WALK_MAX_VELOCITY):
|
|
lv.x-=AIR_ACCEL*step
|
|
elif (move_right and not move_left):
|
|
if (lv.x < WALK_MAX_VELOCITY):
|
|
lv.x+=AIR_ACCEL*step
|
|
else:
|
|
var xv = abs(lv.x)
|
|
xv-=AIR_DEACCEL*step
|
|
if (xv<0):
|
|
xv=0
|
|
lv.x=sign(lv.x)*xv
|
|
|
|
if (lv.y<0):
|
|
if (shoot_time<MAX_SHOOT_POSE_TIME):
|
|
new_anim="jumping_weapon"
|
|
else:
|
|
new_anim="jumping"
|
|
else:
|
|
if (shoot_time<MAX_SHOOT_POSE_TIME):
|
|
new_anim="falling_weapon"
|
|
else:
|
|
new_anim="falling"
|
|
|
|
|
|
#Update siding
|
|
|
|
if (new_siding_left!=siding_left):
|
|
if (new_siding_left):
|
|
get_node("sprite").set_scale( Vector2(-1,1) )
|
|
else:
|
|
get_node("sprite").set_scale( Vector2(1,1) )
|
|
|
|
siding_left=new_siding_left
|
|
|
|
#Change animation
|
|
if (new_anim!=anim):
|
|
anim=new_anim
|
|
get_node("anim").play(anim)
|
|
|
|
shooting=shoot
|
|
|
|
# Apply floor velocity
|
|
if (found_floor):
|
|
floor_h_velocity=s.get_contact_collider_velocity_at_pos(floor_index).x
|
|
lv.x+=floor_h_velocity
|
|
|
|
|
|
|
|
|
|
#Finally, apply gravity and set back the linear velocity
|
|
lv+=s.get_total_gravity()*step
|
|
s.set_linear_velocity(lv)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _ready():
|
|
# Initalization here
|
|
|
|
# if !Globals.has_singleton("Facebook"):
|
|
# return
|
|
# var Facebook = Globals.get_singleton("Facebook")
|
|
# var link = Globals.get("facebook/link")
|
|
# var icon = Globals.get("facebook/icon")
|
|
# var msg = "I just sneezed on your wall! Beat my score and Stop the Running nose!"
|
|
# var title = "I just sneezed on your wall!"
|
|
# Facebook.post("feed", msg, title, link, icon)
|
|
enemy = ResourceLoader.load("res://enemy.xml")
|
|
pass
|
|
|
|
|
|
|