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 GRAVITY = 700.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 -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