def kick_raytest(cont, own): ''' p = own.worldPosition y = own.getAxisVect([0,1,0]) # just return the object return own.rayCastTo([p[0]+y[0], p[1]+y[1], p[2]+y[2]], 1.2, 'kickable') ''' hit_ob = cont.sensors['kick_radar'].hitObject # Cant kick a dead enimy if hit_ob == None or hit_ob.get('life', 1) <= 0: return None if hit_ob and own.getDistanceTo(hit_ob) > 0.7: return # Pitty but radar is buggy- test angle here ang = AngleBetweenVecs( \ ( Vector(own.getAxisVect((0.0, 1.0, 0.0))) ), \ ( Vector(hit_ob.worldPosition) - Vector(own.worldPosition) ) \ ) if ang > 33.0: return None return hit_ob
def angle_target(own, cont, own_pos): # Head towards our target direction = target_direction(own, cont, own_pos) # own_mat = Matrix(*own.localOrientation).transpose() own_y = Vector(own.getAxisVect((0.0, 1.0, 0.0))) own_y.z = 0.0 ang = AngleBetweenVecs(own_y, direction) if direction.cross(own_y).z < 0.0: ang = -ang return ang
def side_of_other(own, other): ''' What side of the sheep are we standing on? (2D function) ''' relative_vec = Vector(own.worldPosition) - Vector(other.worldPosition) other_y_vec = Vector(other.getAxisVect((0.0, 1.0, 0.0))) relative_vec.z = other_y_vec.z = 0.0 if other_y_vec.cross(relative_vec).z > 0.0: return True else: return False
def do_clamp_speed(own, cont, velocity): ''' Clamp the x/y velocity, we can do speedups etc here but for now just clamping at around run speed is fine. ''' velocity_vec = Vector(velocity[0], velocity[1]) l = velocity_vec.length if own['boosted']: MAX_SPEED = 3.0 else: MAX_SPEED = 6.0 if l < MAX_SPEED: return velocity_vec.length = MAX_SPEED velocity[0] = velocity_vec[0] velocity[1] = velocity_vec[1] own.setLinearVelocity(velocity)
def main(cont): own = cont.owner sens_wall_ray = cont.sensors['wall_ray'] sens_wall_time = cont.sensors['wall_run_time'] actu_motion = cont.actuators['wall_run_motion'] if not sens_wall_time.positive: # We must turn off this actuator once the time limit sensor # is false, otherwise it will keep benig applied # This will happen when first touching the wall which is not needed # but there is no harm in it either. # There is a small chance the time will run out but the ray will be hitting somthing. # so just to be sure, always remove motion when the wall timer is false. cont.deactivate(actu_motion) if not sens_wall_ray.positive: return # when to apply the rebound force from the wall and turn frankie # make sure its lower then the wall_run_time sensor maximum LIMIT_REBOUND_TIME = 0.25 REBOUND_LINV = 1.0 #if not sens_wall_ray.positive: #if 1: if not sens_wall_time.positive and sens_wall_ray.positive: # Either initialize a rebound, of if the angle is low, just run paralelle to the wall wall_nor = Vector(sens_wall_ray.hitNormal) wall_nor.z = 0.0 own_neg_y = Vector(own.getAxisVect((0.0, -1.0, 0.0))) own_neg_y.z = 0.0 ang = AngleBetweenVecs(own_neg_y, wall_nor) if ang > 22.5: cross = wall_nor.cross(own_neg_y) if cross.z > 0.0: paralelle_dir = wall_nor * RotationMatrix(-90.0, 3, 'z') else: paralelle_dir = wall_nor * RotationMatrix(90.0, 3, 'z') own.alignAxisToVect(paralelle_dir, 1, 0.1) return else: # Rebount! - we're running directly into it own['wall_run_timer'] = 0.0 # Set the direction velocity, apply this later ''' # Simple direct off wall, not that fun wall_nor = sens_wall_ray.hitNormal actu_motion.linV = (wall_nor[0]*REBOUND_LINV, wall_nor[1]*REBOUND_LINV, 0.0) ''' # Nicer to reflect wall_nor.normalize() ref = own_neg_y.reflect(wall_nor) actu_motion.linV = (ref[0] * REBOUND_LINV, ref[1] * REBOUND_LINV, 0.0) # global linV cont.activate('run_wall') else: ## We are not facing the wall anymore, just orient to the reflection vector # Apply rebound and face that direction if own['wall_run_timer'] > LIMIT_REBOUND_TIME: vel = actu_motion.linV own.alignAxisToVect(vel, 1, 0.2) cont.activate(actu_motion)
def frankTestLedge(own, cont, hit_object, CORRECTION_RAY): ''' hit_object is the ledge we are colliding, if its None then just look for all objects with 'ledge' property Return: ray_hit, ray_nor, z_pos ''' if own['carrying'] or own['carried']: print("cant grab - carry!") return None, None, None own_pos = own.worldPosition ''' own_pos = own.worldPosition own_pos_ofs = own_pos[:] [2] += RAY_CAST_Z_OFFSET ''' # Ok we are colliding and pressing up y_axis = own.getAxisVect((0.0, 1.0, 0.0)) ray_dir = own_pos[:] ray_dir[0] += y_axis[0] ray_dir[1] += y_axis[1] if hit_object: # print("HITUP!!!") #ob_ledge, hit_first, nor_first = own.rayCast(ray_dir, hit_object, RAY_LENGTH) ob_ledge, hit_first, nor_first = own.rayCast(ray_dir, own_pos, RAY_LENGTH) if ob_ledge and ob_ledge != hit_object: print("Hit Wrong Object, was %s should be %s" % (ob_ledge.name, hit_object.name)) # should never happen return None, None, None else: # print("NO HITOB!!!") ob_ledge, hit_first, nor_first = own.rayCast(ray_dir, own_pos, RAY_LENGTH, 'ledge') if not hit_first: print("FirstLedgeRay Missed!", ray_dir, y_axis) return None, None, None # debug.setpos( hit_first ) # Not strictly needed but makes for better results, shoot a ray allong the normal of the ray ray you just hit # This prevents moving too far when latching onto a ledge. y_axis_corrected = [-nor_first[0], -nor_first[1], 0.0] ray_dir_first = ray_dir[:] # Should we re-shoot a ray that is corrected based on the normal from the surface of what we hit? if CORRECTION_RAY: ray_dir_closer = own_pos[:] ray_dir_closer[0] += y_axis_corrected[0] ray_dir_closer[1] += y_axis_corrected[1] if hit_object: ob_closer, hit_closer, nor_closer = own.rayCast( ray_dir_closer, hit_object, RAY_LENGTH, 'ledge') else: ob_closer, hit_closer, nor_closer = own.rayCast( ray_dir_closer, None, RAY_LENGTH, 'ledge') if ob_closer: ### print("CAST !!!!!!!!2nd ray") AXIS = ((hit_closer, y_axis_corrected, nor_closer), (hit_first, y_axis, nor_first)) else: ### print("Can only castr 1 ray") AXIS = ((hit_first, y_axis, nor_first), ) else: # Simple, dont pradict best second ray ob_closer = None AXIS = ((hit_first, y_axis, nor_first), ) # Do Z Ray Down. Y_OFFSET = 0.6 # length of the Y ray forward. Z_OFFSET = 0.6 # length of the Z ray up. for hit_new, y_axis_new, nor_new in AXIS: # Set the 2D length of this vector to Y_OFFSET y_axis_new = Vector(y_axis_new[0], y_axis_new[1]) y_axis_new.length = Y_OFFSET # Now cast a new ray down too see the Z posuition of the ledge above us new_ray_pos = [ own_pos[0] + y_axis_new[0], own_pos[1] + y_axis_new[1], own_pos[2] + Z_OFFSET ] new_ray_pos_target = new_ray_pos[:] new_ray_pos_target[2] -= 0.5 # This dosnt matter, just lower is fine ### debug.setpos( new_ray_pos ) ### debug.setpos( new_ray_pos_target ) ob_ledge, hit_down, nor_down = own.rayCast( new_ray_pos_target, new_ray_pos, 0.5 ) # Can hit objects of any property, MAYBE should choose ground. if ob_ledge: own['can_climb'] = 1 ###print("Round nice RAY at pt", hit_down[2]) # debug.setpos( hit_down ) return hit_new, nor_new, hit_down[2] # Could not hit it vertically... # Ok we will try to find the bugger! # Cast multiple rays, this is not pretty ### print("BUGGER, cant climb", ob_closer) own['can_climb'] = 0 new_ray_pos = own_pos[:] # we only need to adjust its z value if ob_closer: # print("Closer") new_ray_pos_target = ray_dir_closer[:] else: # print("NotCloser") new_ray_pos_target = ray_dir_first[:] target_z = own_pos[2] - CLIMB_HANG_Z_OFFSET inc = 0.05 # Watch this, some numbers may cause jitter # z_ray_search_origin sss = z_ray_search_origin = own_pos[ 2] - 0.2 # Tested this to be a good and correct starting location for searching the ray. z_ray_search_limit = own_pos[2] - (CLIMB_HANG_Z_OFFSET * 1.8) test_ok = None # False i = 0 # Ray cast with an increasingly higher Z origin to find the top of the ledge while z_ray_search_origin < z_ray_search_limit: i += 1 # print(i, z_ray_search_origin, (own_pos[2]-(CLIMB_HANG_Z_OFFSET*1.8))-z_ray_search_origin) z_ray_search_origin += inc new_ray_pos[2] = new_ray_pos_target[2] = z_ray_search_origin test = own.rayCast( new_ray_pos_target, new_ray_pos, RAY_LENGTH, 'ledge' ) # Can hit objects of any property, MAYBE should choose ground. if test[0]: test_ok = test elif test[0] == None and test_ok: # If we have hit # no hit, return the last hit # print("Found", i) ''' crap = test_ok[1][:] crap[2] = z_ray_search_limit debug.setpos( crap ) ''' return test_ok[1], test_ok[2], z_ray_search_origin print("Missed VRAY") # crap = hit_first[:] # crap[2] = own_pos[2]-CLIMB_HANG_Z_OFFSET # debug.setpos( crap ) return hit_first, nor_first, own_pos[2] - CLIMB_HANG_Z_OFFSET
def reset_target(own, cont, own_pos, predator_ob): # print('RESET TARGET...') TARGET_DIST_MIN = 2.0 TARGET_DIST_MAX = 8.0 own['target_time'] = 0.0 L = TARGET_DIST_MIN + (Rand() * (TARGET_DIST_MAX - TARGET_DIST_MIN)) own_front = own.getAxisVect((0.0, L, 0.0)) # Should we run toward or away? # we need a random angle between 90 and 270 if predator_ob: if own['revive_time'] < 4.0: # print("recover, escape!") ATTACK = False elif own['type'] == 'ram': ATTACK = True elif own['type'] == 'shp': ATTACK = False elif own['type'] == 'rat': # attack only when frankie is facing away - Sneaky! pred_front = Vector(predator_ob.getAxisVect((0.0, 1.0, 0.0))) pred_front.z = 0.0 pos = Vector(predator_ob.worldPosition) new_dir = own_pos - pos if new_dir.dot(pred_front) > 0.0: ATTACK = False else: ATTACK = True # print('ATTACK', ATTACK) # Attack done #if predator_ob and Rand() > 0.33: pos = Vector(predator_ob.worldPosition) new_dir = own_pos - pos if ATTACK: # ATTACK! ### print('ATTACK') #own['target_x'] = pos[0] #own['target_y'] = pos[1] new_dir.z = 0 new_dir.length = 3 # set target to be 5 past the character. own['target_x'] = pos[0] - new_dir.x own['target_y'] = pos[1] - new_dir.y else: ### print('FLEE') new_dir.z = 0.0 new_dir.length = L # new_dir = Vector(own_front) * RotationMatrix(ang, 3, 'z') ang = (Rand() * 45) - (45 / 2.0) new_dir = new_dir * RotationMatrix(ang, 3, 'z') own['target_x'] = new_dir.x + own_pos[0] own['target_y'] = new_dir.y + own_pos[1] else: ### print('RANDOM') # Random target ang = 90 + (Rand() * 180) new_dir = Vector(own_front) * RotationMatrix(ang, 3, 'z') own['target_x'] = new_dir.x + own_pos[0] own['target_y'] = new_dir.y + own_pos[1]
def main(cont): WALL_LIMIT = 0.1 TURN_TIME = 0.5 # we are touching somthing and will always turn the same way out. # If ray sensors measure this close TOO_CLOSE = 0.55 DIRECTION[ 0] = 0 # just incase, multiple animals will use this module so must initialize own = cont.owner # print(own['type']) actu_motion = cont.actuators['motion_py'] # print(own['target_time']) ### setpos([own['target_x'], own['target_y'], 0.0]) cont_name = cont.name #print(cont_name, 'cont_name') if cont_name.startswith('walk_normal'): ROTATE_SPEED = 0.02 RUN_SPEED = 0.02 TIME_LIMIT = 6.0 ESCAPE = False predator_ob = None else: ROTATE_SPEED = 0.1 if own['type'] == 'rat': RUN_SPEED = 0.05 else: RUN_SPEED = 0.03 TIME_LIMIT = 4.0 ESCAPE = True predator_ob = [ ob for ob in cont.sensors['predator_sensor'].hitObjectList if ob.get('life', 1) != 0 ] if predator_ob: predator_ob = predator_ob[0] else: # EXIT ESCAPE STATE predator_ob = None cont.activate('walk_state') own_pos = Vector(own.worldPosition) ''' sens_l= cont.sensors['RayLeft'] sens_r = cont.sensors['RayRight'] sens_l_hitob = sens_l.hitObject sens_r_hitob = sens_r.hitObject ''' # use python to get rays instead # ray should be ray_pos = own_pos.copy() ray_pos[ 2] += 0.18 # cast the ray from slightly above, be sure they dont hit objects children # see objects "reference_only", these are the raydirections we are casting in python right_ray = Vector(own.getAxisVect([0.41, 0.74, -0.53])) left_ray = Vector(own.getAxisVect([-0.41, 0.74, -0.53])) sens_l_hitob, lpos, lnor = own.rayCast(ray_pos + left_ray, ray_pos, 1.8) sens_r_hitob, rpos, rnor = own.rayCast(ray_pos + right_ray, ray_pos, 1.8) # ob_ledge, hit_down, nor_down # If it has a barrier, respect it if sens_l_hitob and ('barrier' in sens_l_hitob or 'water' in sens_l_hitob or 'lava' in sens_l_hitob): sens_l_hitob = None if sens_r_hitob and ('barrier' in sens_r_hitob or 'water' in sens_r_hitob or 'lava' in sens_r_hitob): sens_r_hitob = None #if sens_l_hitob: # print(str(sens_l_hitob.name), 'hitob') # print('TETS', type(sens_l_hitob), type(sens_r_hitob)) # Check if we are running into frankie while he is reviving, if so turn away. # Do this because otherwise we keep running into frankie after hitting him. for ob in (sens_l_hitob, sens_r_hitob): if ob and 'predator' in ob and ob.get('revive_time', 100.0) < 1.0: # would be nice to alternate but no big deal DIRECTION[0] = 1 RUN_SPEED = 0.0 # sets a too close value that is checked above # this means the sheep will turn for a while so it will never jitter own['target_time'] = -TURN_TIME break if own['target_time'] < 0.0: # Should this be a state rather then abusing a timer? # This is a bit of a hack. oh well :/ # print('ROTATING!', own['target_time']) DIRECTION[0] = 1 RUN_SPEED = 0.0 elif sens_l_hitob and sens_r_hitob: # print("BOTH OK") # Both collide, so do somtething ####lpos = sens_l.hitPosition ldist = own.getDistanceTo(lpos) ####lnor = sens_l.hitNormal ####rpos = sens_r.hitPosition rdist = own.getDistanceTo(rpos) ####rnor = sens_r.hitNormal # print(ldist, rdist, 'DIST') # Not really an angle, but we can treat it a bit like one ang = ldist - rdist # Cheap trick, so flat surfaces give low angles # Maybe we should deal with flat surfaces differently # but we are really looking for walls, so flat'ish ground can be ignored. # # zl and zr both have a range of -1.0 to 1.0, so if teh surface is totally flat, # the 'ang' will be unchanged # ''' zl = lnor[2] zr = rnor[2] if zl < 0.0: lz = 0.0 if zr < 0.0: rz = 0.0 ang = ang * (2.0 - (zl + zr)) # ''' # Done with cheap trick, remove if it causes problems # Do we need to agoid a wall? # IF we are really close to a corner we can get stuck and jitter # in this case just turn 1 way if ldist < TOO_CLOSE and rdist < TOO_CLOSE: # print("\tchar navigation: ray casts both too close", ldist, rdist) # would be nice to alternate but no big deal DIRECTION[0] = 1 RUN_SPEED = 0.0 # sets a too close value that is checked above # this means the sheep will turn for a while so it will never jitter own['target_time'] = -TURN_TIME elif abs(ang) > WALL_LIMIT: #print("GO WALL") if ang < 0 or (ldist < TOO_CLOSE and rdist < TOO_CLOSE): DIRECTION[0] = 1 else: DIRECTION[0] = 2 else: # print("GO TARGET") go_target(own, cont, own_pos, predator_ob, TIME_LIMIT) if not (sens_l_hitob and sens_r_hitob): RUN_SPEED = 0.0 elif (not sens_l_hitob) and (not sens_r_hitob): # We are on a ledge # print("EMPTY CLOSE" #, ldist, rdist) # would be nice to alternate but no big deal DIRECTION[0] = 1 RUN_SPEED = 0.0 # sets a too close value that is checked above # this means the sheep will turn for a while so it will never jitter own['target_time'] = -TURN_TIME elif not sens_l_hitob or not sens_r_hitob: if abs(angle_target(own, cont, own_pos)) < 90 and own['target_time'] > TIME_LIMIT: reset_target(own, cont, own_pos, predator_ob) go_target(own, cont, own_pos, predator_ob, TIME_LIMIT) # Dont do anything RUN_SPEED = 0.0 # Apply direction # print('DIRECTION', DIRECTION, ldist, rdist) if DIRECTION[0] == 0: # print('NotTurning') actu_motion.dRot = (0.0, 0.0, 0.0) # cont.deactivate(actu_turn) else: if DIRECTION[0] == 1: # print('Turning Left') rot = -ROTATE_SPEED elif DIRECTION[0] == 2: # print('Turning Right') rot = ROTATE_SPEED actu_motion.dRot = (0.0, 0.0, rot) # This is a bit weired, use negative z dloc to stick him to the ground. actu_motion.dLoc = (0.0, RUN_SPEED, -0.01) cont.activate(actu_motion)
def main(cont): HANG_COUNTER_GRAVITY = 0.17 # HANG_TIMEOFFSET = 20.0 own = cont.owner # 3rd arg gets a corrected ray when its thr first ray for the state # This can only run the first time otherwise it makes shimmy jitter baddly. # since correcting the axis can rotate frankie back and fourth. if cont.sensors['true_init_pulse_ledge'].positive: ledge_hit, ledge_nor, zpos = frankTestLedge(own, cont, None, False) else: # Drop on purpose sens_keyDown = cont.sensors['key_down'] if sens_keyDown.positive and sens_keyDown.triggered: do_fall_state(own, cont) return ledge_hit, ledge_nor, zpos = frankTestLedge(own, cont, None, True) # set the timeoffset so hanging gets nice smooth movement for free. # cont.sensors['rig_linkonly'].owner.timeOffset = HANG_TIMEOFFSET if not ledge_hit: do_fall_state(own, cont) return sens_up = cont.sensors['key_up'] if sens_up.positive and sens_up.triggered and own['can_climb']: # own.suspendDynamics() do_reset_timeofs(cont) cont.activate('climb_state') return own.setLinearVelocity((0.0, 0.0, HANG_COUNTER_GRAVITY)) # Make sure frankie is upright. especially if he was just gliding this can happen! own.alignAxisToVect((0.0, 0.0, 1.0), 2) # We need to do somthing a bit extra tricky here, move the position of frankie around the ray intersect pivot, # This avoids jittering new_dir = Vector(-ledge_nor[0], -ledge_nor[1], 0.0) new_z = zpos + CLIMB_HANG_Z_OFFSET own_y = Vector(own.getAxisVect((0.0, 1.0, 0.0))) ledge_hit = Vector(ledge_hit) cross = own_y.cross(new_dir) ang = AngleBetweenVecs(own_y, new_dir) # Set Frankies distance from the hit position if ang > 0.1: if cross.z < 0: ang = -ang pos_orig = Vector(own.worldPosition) ####pos_new = ((pos_orig-ledge_hit) * rot) + ledge_hit # Do this instead. d = (pos_orig - ledge_hit) d.z = 0.0 d.length = -CLIMB_HANG_Y_OFFSET pos_new = (d * RotationMatrix(ang, 3, 'z')) + ledge_hit else: # Simple but not good enough # own.localPosition = (pos_orig-ledge_hit) + ledge_hit # Location, use CLIMB_HANG_Y_OFFSET to offset ourselves from the ledges hit point d = Vector(ledge_nor) d.z = 0.0 d.length = -CLIMB_HANG_Y_OFFSET pos_new = d + ledge_hit own.alignAxisToVect([-ledge_nor[0], -ledge_nor[1], 0.0], 1) pos_new.z = new_z own.localPosition = pos_new
def reset_target(own, cont, own_pos, predator_ob): # print('RESET TARGET...') TARGET_DIST_MIN = 2.0 TARGET_DIST_MAX = 8.0 own['target_time'] = 0.0 L = TARGET_DIST_MIN + (Rand() * (TARGET_DIST_MAX-TARGET_DIST_MIN)) own_front= own.getAxisVect((0.0, L, 0.0)) # Should we run toward or away? # we need a random angle between 90 and 270 if predator_ob: if own['revive_time'] < 4.0: # print("recover, escape!") ATTACK = False elif own['type'] == 'ram': ATTACK = True elif own['type'] == 'shp': ATTACK = False elif own['type'] == 'rat': # attack only when frankie is facing away - Sneaky! pred_front = Vector(predator_ob.getAxisVect((0.0, 1.0, 0.0))) pred_front.z = 0.0 pos = Vector(predator_ob.worldPosition) new_dir = own_pos - pos if new_dir.dot(pred_front) > 0.0: ATTACK = False else: ATTACK = True # print('ATTACK', ATTACK) # Attack done #if predator_ob and Rand() > 0.33: pos = Vector(predator_ob.worldPosition) new_dir = own_pos - pos if ATTACK: # ATTACK! ### print('ATTACK') #own['target_x'] = pos[0] #own['target_y'] = pos[1] new_dir.z = 0 new_dir.length = 3 # set target to be 5 past the character. own['target_x'] = pos[0] - new_dir.x own['target_y'] = pos[1] - new_dir.y else: ### print('FLEE') new_dir.z = 0.0 new_dir.length = L # new_dir = Vector(own_front) * RotationMatrix(ang, 3, 'z') ang = (Rand()*45) - (45/2.0) new_dir = new_dir * RotationMatrix(ang, 3, 'z') own['target_x'] = new_dir.x + own_pos[0] own['target_y'] = new_dir.y + own_pos[1] else: ### print('RANDOM') # Random target ang = 90 + (Rand()*180) new_dir = Vector(own_front) * RotationMatrix(ang, 3, 'z') own['target_x'] = new_dir.x + own_pos[0] own['target_y'] = new_dir.y + own_pos[1]
def main(cont): WALL_LIMIT = 0.1 TURN_TIME = 0.5 # we are touching somthing and will always turn the same way out. # If ray sensors measure this close TOO_CLOSE = 0.55 DIRECTION[0] = 0 # just incase, multiple animals will use this module so must initialize own = cont.owner # print(own['type']) actu_motion = cont.actuators['motion_py'] # print(own['target_time']) ### setpos([own['target_x'], own['target_y'], 0.0]) cont_name = cont.name #print(cont_name, 'cont_name') if cont_name.startswith('walk_normal'): ROTATE_SPEED = 0.02 RUN_SPEED = 0.02 TIME_LIMIT = 6.0 ESCAPE = False predator_ob = None else: ROTATE_SPEED = 0.1 if own['type'] == 'rat': RUN_SPEED = 0.05 else: RUN_SPEED = 0.03 TIME_LIMIT = 4.0 ESCAPE = True predator_ob = [ob for ob in cont.sensors['predator_sensor'].hitObjectList if ob.get('life', 1) != 0] if predator_ob: predator_ob = predator_ob[0] else: # EXIT ESCAPE STATE predator_ob = None cont.activate('walk_state') own_pos = Vector(own.worldPosition) ''' sens_l= cont.sensors['RayLeft'] sens_r = cont.sensors['RayRight'] sens_l_hitob = sens_l.hitObject sens_r_hitob = sens_r.hitObject ''' # use python to get rays instead # ray should be ray_pos = own_pos.copy() ray_pos[2] += 0.18 # cast the ray from slightly above, be sure they dont hit objects children # see objects "reference_only", these are the raydirections we are casting in python right_ray = Vector(own.getAxisVect([ 0.41, 0.74, -0.53 ])) left_ray = Vector(own.getAxisVect([ -0.41, 0.74, -0.53 ])) sens_l_hitob, lpos, lnor = own.rayCast(ray_pos + left_ray, ray_pos, 1.8) sens_r_hitob, rpos, rnor = own.rayCast(ray_pos + right_ray, ray_pos, 1.8) # ob_ledge, hit_down, nor_down # If it has a barrier, respect it if sens_l_hitob and ('barrier' in sens_l_hitob or 'water' in sens_l_hitob or 'lava' in sens_l_hitob): sens_l_hitob = None if sens_r_hitob and ('barrier' in sens_r_hitob or 'water' in sens_r_hitob or 'lava' in sens_r_hitob): sens_r_hitob = None #if sens_l_hitob: # print(str(sens_l_hitob.name), 'hitob') # print('TETS', type(sens_l_hitob), type(sens_r_hitob)) # Check if we are running into frankie while he is reviving, if so turn away. # Do this because otherwise we keep running into frankie after hitting him. for ob in (sens_l_hitob, sens_r_hitob): if ob and 'predator' in ob and ob.get('revive_time', 100.0) < 1.0: # would be nice to alternate but no big deal DIRECTION[0] = 1 RUN_SPEED = 0.0 # sets a too close value that is checked above # this means the sheep will turn for a while so it will never jitter own['target_time'] = -TURN_TIME break if own['target_time'] < 0.0: # Should this be a state rather then abusing a timer? # This is a bit of a hack. oh well :/ # print('ROTATING!', own['target_time']) DIRECTION[0] = 1 RUN_SPEED = 0.0 elif sens_l_hitob and sens_r_hitob: # print("BOTH OK") # Both collide, so do somtething ####lpos = sens_l.hitPosition ldist = own.getDistanceTo(lpos) ####lnor = sens_l.hitNormal ####rpos = sens_r.hitPosition rdist = own.getDistanceTo(rpos) ####rnor = sens_r.hitNormal # print(ldist, rdist, 'DIST') # Not really an angle, but we can treat it a bit like one ang = ldist-rdist # Cheap trick, so flat surfaces give low angles # Maybe we should deal with flat surfaces differently # but we are really looking for walls, so flat'ish ground can be ignored. # # zl and zr both have a range of -1.0 to 1.0, so if teh surface is totally flat, # the 'ang' will be unchanged # ''' zl = lnor[2] zr = rnor[2] if zl < 0.0: lz = 0.0 if zr < 0.0: rz = 0.0 ang = ang * (2.0-(zl+zr)) # ''' # Done with cheap trick, remove if it causes problems # Do we need to agoid a wall? # IF we are really close to a corner we can get stuck and jitter # in this case just turn 1 way if ldist<TOO_CLOSE and rdist<TOO_CLOSE: # print("\tchar navigation: ray casts both too close", ldist, rdist) # would be nice to alternate but no big deal DIRECTION[0] = 1 RUN_SPEED = 0.0 # sets a too close value that is checked above # this means the sheep will turn for a while so it will never jitter own['target_time'] = -TURN_TIME elif abs(ang) > WALL_LIMIT: #print("GO WALL") if ang < 0 or (ldist<TOO_CLOSE and rdist<TOO_CLOSE): DIRECTION[0] = 1 else: DIRECTION[0] = 2 else: # print("GO TARGET") go_target(own, cont, own_pos, predator_ob, TIME_LIMIT) if not (sens_l_hitob and sens_r_hitob): RUN_SPEED = 0.0 elif (not sens_l_hitob) and (not sens_r_hitob): # We are on a ledge # print("EMPTY CLOSE" #, ldist, rdist) # would be nice to alternate but no big deal DIRECTION[0] = 1 RUN_SPEED = 0.0 # sets a too close value that is checked above # this means the sheep will turn for a while so it will never jitter own['target_time'] = -TURN_TIME elif not sens_l_hitob or not sens_r_hitob: if abs(angle_target(own, cont, own_pos)) < 90 and own['target_time'] > TIME_LIMIT: reset_target(own, cont, own_pos, predator_ob) go_target(own, cont, own_pos, predator_ob, TIME_LIMIT) # Dont do anything RUN_SPEED = 0.0 # Apply direction # print('DIRECTION', DIRECTION, ldist, rdist) if DIRECTION[0] == 0: # print('NotTurning') actu_motion.dRot = (0.0, 0.0, 0.0) # cont.deactivate(actu_turn) else: if DIRECTION[0] == 1: # print('Turning Left') rot = -ROTATE_SPEED elif DIRECTION[0] == 2: # print('Turning Right') rot = ROTATE_SPEED actu_motion.dRot = (0.0, 0.0, rot) # This is a bit weired, use negative z dloc to stick him to the ground. actu_motion.dLoc = (0.0, RUN_SPEED, -0.01) cont.activate(actu_motion)
def frankTestLedge(own, cont, hit_object, CORRECTION_RAY): ''' hit_object is the ledge we are colliding, if its None then just look for all objects with 'ledge' property Return: ray_hit, ray_nor, z_pos ''' if own['carrying'] or own['carried']: print("cant grab - carry!") return None, None, None own_pos = own.worldPosition ''' own_pos = own.worldPosition own_pos_ofs = own_pos[:] [2] += RAY_CAST_Z_OFFSET ''' # Ok we are colliding and pressing up y_axis = own.getAxisVect( (0.0, 1.0, 0.0) ) ray_dir = own_pos[:] ray_dir[0] += y_axis[0] ray_dir[1] += y_axis[1] if hit_object: # print("HITUP!!!") #ob_ledge, hit_first, nor_first = own.rayCast(ray_dir, hit_object, RAY_LENGTH) ob_ledge, hit_first, nor_first = own.rayCast(ray_dir, own_pos, RAY_LENGTH) if ob_ledge and ob_ledge != hit_object: print("Hit Wrong Object, was %s should be %s" % (ob_ledge.name, hit_object.name)) # should never happen return None, None, None else: # print("NO HITOB!!!") ob_ledge, hit_first, nor_first = own.rayCast(ray_dir, own_pos, RAY_LENGTH, 'ledge') if not hit_first: print("FirstLedgeRay Missed!", ray_dir, y_axis) return None, None, None # debug.setpos( hit_first ) # Not strictly needed but makes for better results, shoot a ray allong the normal of the ray ray you just hit # This prevents moving too far when latching onto a ledge. y_axis_corrected = [-nor_first[0], -nor_first[1], 0.0] ray_dir_first = ray_dir[:] # Should we re-shoot a ray that is corrected based on the normal from the surface of what we hit? if CORRECTION_RAY: ray_dir_closer = own_pos[:] ray_dir_closer[0] += y_axis_corrected[0] ray_dir_closer[1] += y_axis_corrected[1] if hit_object: ob_closer, hit_closer, nor_closer = own.rayCast(ray_dir_closer, hit_object, RAY_LENGTH, 'ledge') else: ob_closer, hit_closer, nor_closer = own.rayCast(ray_dir_closer, None, RAY_LENGTH, 'ledge') if ob_closer: ### print("CAST !!!!!!!!2nd ray") AXIS = ((hit_closer, y_axis_corrected, nor_closer), (hit_first, y_axis, nor_first)) else: ### print("Can only castr 1 ray") AXIS = ((hit_first, y_axis, nor_first),) else: # Simple, dont pradict best second ray ob_closer = None AXIS = ((hit_first, y_axis, nor_first),) # Do Z Ray Down. Y_OFFSET = 0.6 # length of the Y ray forward. Z_OFFSET = 0.6 # length of the Z ray up. for hit_new, y_axis_new, nor_new in AXIS: # Set the 2D length of this vector to Y_OFFSET y_axis_new = Vector(y_axis_new[0],y_axis_new[1]) y_axis_new.length = Y_OFFSET # Now cast a new ray down too see the Z posuition of the ledge above us new_ray_pos= [own_pos[0]+y_axis_new[0], own_pos[1]+y_axis_new[1], own_pos[2]+Z_OFFSET] new_ray_pos_target = new_ray_pos[:] new_ray_pos_target[2] -= 0.5 # This dosnt matter, just lower is fine ### debug.setpos( new_ray_pos ) ### debug.setpos( new_ray_pos_target ) ob_ledge, hit_down, nor_down = own.rayCast(new_ray_pos_target, new_ray_pos, 0.5) # Can hit objects of any property, MAYBE should choose ground. if ob_ledge: own['can_climb'] = 1 ###print("Round nice RAY at pt", hit_down[2]) # debug.setpos( hit_down ) return hit_new, nor_new, hit_down[2] # Could not hit it vertically... # Ok we will try to find the bugger! # Cast multiple rays, this is not pretty ### print("BUGGER, cant climb", ob_closer) own['can_climb'] = 0 new_ray_pos = own_pos[:] # we only need to adjust its z value if ob_closer: # print("Closer") new_ray_pos_target = ray_dir_closer[:] else: # print("NotCloser") new_ray_pos_target = ray_dir_first[:] target_z = own_pos[2]-CLIMB_HANG_Z_OFFSET inc = 0.05 # Watch this, some numbers may cause jitter # z_ray_search_origin sss = z_ray_search_origin = own_pos[2]-0.2 # Tested this to be a good and correct starting location for searching the ray. z_ray_search_limit = own_pos[2]-(CLIMB_HANG_Z_OFFSET*1.8) test_ok = None # False i = 0 # Ray cast with an increasingly higher Z origin to find the top of the ledge while z_ray_search_origin < z_ray_search_limit: i+=1 # print(i, z_ray_search_origin, (own_pos[2]-(CLIMB_HANG_Z_OFFSET*1.8))-z_ray_search_origin) z_ray_search_origin += inc new_ray_pos[2] = new_ray_pos_target[2] = z_ray_search_origin test = own.rayCast(new_ray_pos_target, new_ray_pos, RAY_LENGTH, 'ledge') # Can hit objects of any property, MAYBE should choose ground. if test[0]: test_ok = test elif test[0]==None and test_ok: # If we have hit # no hit, return the last hit # print("Found", i) ''' crap = test_ok[1][:] crap[2] = z_ray_search_limit debug.setpos( crap ) ''' return test_ok[1], test_ok[2], z_ray_search_origin print("Missed VRAY") # crap = hit_first[:] # crap[2] = own_pos[2]-CLIMB_HANG_Z_OFFSET # debug.setpos( crap ) return hit_first, nor_first, own_pos[2]-CLIMB_HANG_Z_OFFSET
def main(cont): HANG_COUNTER_GRAVITY = 0.17 # HANG_TIMEOFFSET = 20.0 own = cont.owner # 3rd arg gets a corrected ray when its thr first ray for the state # This can only run the first time otherwise it makes shimmy jitter baddly. # since correcting the axis can rotate frankie back and fourth. if cont.sensors['true_init_pulse_ledge'].positive: ledge_hit, ledge_nor, zpos = frankTestLedge(own, cont, None, False) else: # Drop on purpose sens_keyDown = cont.sensors['key_down'] if sens_keyDown.positive and sens_keyDown.triggered: do_fall_state(own, cont) return ledge_hit, ledge_nor, zpos = frankTestLedge(own, cont, None, True) # set the timeoffset so hanging gets nice smooth movement for free. # cont.sensors['rig_linkonly'].owner.timeOffset = HANG_TIMEOFFSET if not ledge_hit: do_fall_state(own, cont) return sens_up = cont.sensors['key_up'] if sens_up.positive and sens_up.triggered and own['can_climb']: # own.suspendDynamics() do_reset_timeofs(cont) cont.activate('climb_state') return own.setLinearVelocity((0.0, 0.0, HANG_COUNTER_GRAVITY)) # Make sure frankie is upright. especially if he was just gliding this can happen! own.alignAxisToVect((0.0, 0.0, 1.0), 2) # We need to do somthing a bit extra tricky here, move the position of frankie around the ray intersect pivot, # This avoids jittering new_dir = Vector(-ledge_nor[0], -ledge_nor[1], 0.0) new_z = zpos + CLIMB_HANG_Z_OFFSET own_y = Vector( own.getAxisVect((0.0, 1.0, 0.0)) ) ledge_hit = Vector(ledge_hit) cross =own_y.cross(new_dir) ang = AngleBetweenVecs(own_y, new_dir) # Set Frankies distance from the hit position if ang > 0.1: if cross.z < 0: ang = -ang pos_orig = Vector(own.worldPosition) ####pos_new = ((pos_orig-ledge_hit) * rot) + ledge_hit # Do this instead. d = (pos_orig-ledge_hit) d.z = 0.0 d.length = -CLIMB_HANG_Y_OFFSET pos_new = (d*RotationMatrix(ang, 3, 'z')) + ledge_hit else: # Simple but not good enough # own.localPosition = (pos_orig-ledge_hit) + ledge_hit # Location, use CLIMB_HANG_Y_OFFSET to offset ourselves from the ledges hit point d = Vector(ledge_nor) d.z = 0.0 d.length = -CLIMB_HANG_Y_OFFSET pos_new = d + ledge_hit own.alignAxisToVect([-ledge_nor[0], -ledge_nor[1], 0.0], 1) pos_new.z = new_z own.localPosition = pos_new
def main(cont): if not cont.sensors['trigger_warp_script'].positive: return own = cont.owner own_pos = Vector(own.worldPosition) sce = GameLogic.getCurrentScene() #for ob in sce.objects: # print(ob.name) actu_add_object = cont.actuators['add_dyn_portal'] # Incase we are called from the main menu blendFiles = GameLogic.getBlendFileList('//') blendFiles += GameLogic.getBlendFileList('//levels') blendFiles += GameLogic.getBlendFileList('//../levels') blendFiles += GameLogic.getBlendFileList('//../../../levels') # Remove doubles # blendFiles = list(set(blendFiles)) # breaks py2.3 blendFiles = dict([(b, None) for b in blendFiles]).keys() blendFiles = list(blendFiles) # py3 has its own dict_keys type blendFiles.sort() if own['mini_level']: # Mini level selector for b in blendFiles[:]: if not ('minilevel_' in b or 'level_selector.blend' in b): blendFiles.remove(b) else: # normal level selector for b in blendFiles[:]: # get rid or start_menu, this blend, and any blends not containing minilevel_ if 'minilevel_' in b or \ 'ending.blend' in b or \ 'library.blend' in b or \ 'level_selector.blend' in b or \ '_backup.blend' in b: blendFiles.remove(b) print(blendFiles) totFiles = len(blendFiles) if not totFiles: print("No Levels Found!") return # Some vars for positioning the portals start = Vector( 7, 0, 0) # rotate this point around to place the portals to new levels totFiles = float(totFiles) # print('PLACING') for i, f in enumerate(blendFiles): ang = 360 * (i / totFiles) # print(i,f,ang) mat = RotationMatrix(ang, 3, 'z') pos_xy = list((start * mat) + own_pos) # rotate and center around the gamelogic object ray_down = pos_xy[:] ray_down[2] -= 1.0 print(pos_xy) pos_xy[2] = 500 # cast down from on high #pos_xy[2] = 16 # cast down from on high ob_hit, hit_first, nor_first = own.rayCast(ray_down, pos_xy, 1000) # 'ground') if ob_hit: pos_xy[2] = hit_first[2] else: # Rary a ray would ,iss the ground but could happen. pos_xy[2] = own_pos[2] #own.setPosition(pos_xy) actu_add_object.instantAddObject() new_portal = actu_add_object.objectLastCreated #new_portal.setPosition(hit_first) new_portal.worldPosition = pos_xy new_portal.worldOrientation = mat.transpose() if nor_first: new_portal.alignAxisToVect(nor_first, 2) new_portal['portal_blend'] = '//' + f # BUG THIS SHOULD WORK!!!! ''' new_portal_text = new_portal.children new_portal_text.Text = f.replace('_', ' ').split('.')[0] ''' # Since we use instantAddObject(), there is no need to activate the actuator # GameLogic.addActiveActuator(actu_add_object, 1) own.endObject() # may as well distroy, wont use anymore
def do_kick(cont, own): ''' Kick anything infront of you ''' ob_kick = kick_raytest(cont, own) if not ob_kick: return ''' if not ob_kick.get('grounded', 1): print('cant kick airbourne objects') return ''' if ob_kick.get('carried', 0): print('\tkick: cant kick object being carried') return kick_dir = Vector(ob_kick.worldPosition) - Vector(own.worldPosition) # Tell the object we kicked it. so we cant hurt ourselves if 'projectile_id' in ob_kick: ob_kick['projectile_id'] = own['id'] if 'type' in ob_kick: ob_kick_type = ob_kick['type'] else: if 'predator' in ob_kick: ob_kick_type = 'frank' else: ob_kick_type = 'unknown' # print('ObKick_Type', ob_kick_type) if ob_kick_type == 'rat': # rats are like footballs ''' kick_dir = own.getAxisVect([0,6,0]) kick_dir[2] = 5 ob_kick.setLinearVelocity(kick_dir, 0) ''' # This is a bit nicer, use relative pos # rather then franks direction above kick_dir.z = 0 kick_dir.length = 3.0 kick_dir.z = 4.0 ob_kick.setLinearVelocity(kick_dir, 0) ob_kick.setAngularVelocity((0.0, -10.0, 0.0), 1) # We are carrying sideways elif ob_kick_type == 'shp': # We need to do some complicated crap to make sure they land on our head. kick_dir.z = 0.0 kick_dir.negate() if own['carrying']: # So we can kick a sheep into frankies arms kick_dir.length = 0.4 kick_dir.z = 5.0 # we negate next line else: kick_dir.length = 0.8 kick_dir.z = 4.0 ob_kick.setLinearVelocity(kick_dir, 0) if side_of_other(own, ob_kick): ang = -5.0 else: ang = 5.0 ob_kick.setAngularVelocity((0.0, ang, 0.0), 1) # We are carrying sideways elif ob_kick_type == 'frank': # This is a bit nicer, use relative pos # rather then franks direction above kick_dir.z = 0.0 kick_dir.length = 2.0 kick_dir.z = 6.0 ob_kick.setLinearVelocity(kick_dir, False) # dont really need this but nice not to always turn the same way if side_of_other(own, ob_kick): ang_vel_z = 18 else: ang_vel_z = -18 ob_kick.setAngularVelocity((0.0, 0.0, 18.0), ang_vel_z) # We are carrying sideways ob_kick['hit'] = 1 else: kick_dir.z = 0 kick_dir.length = 0.5 kick_dir.negate() kick_dir.z = 5.0 ob_kick.setLinearVelocity(kick_dir, 0) # do nothing or rams? just play animations print('unknown kick type...', ob_kick_type)
def target_direction(own, cont, own_pos): return Vector(own['target_x'] - own_pos[0], own['target_y'] - own_pos[1], 0.0)
def do_throw(cont, own): ''' Throw objects in your inventory, object names are madeup from the property so you must make sure there is an object in a hidden layer that exists with this name. ''' # Ok We can throw now, throw_item_ob = own['throw_item'] if not throw_item_ob: return # nothing to throw if not throw_item_ob.startswith('item_'): print('\twarning: throw item inavlid, must "item_" prefix -', throw_item_ob) own['throw_item'] = '' return throw_actu = cont.actuators['throw_create'] try: throw_actu.object = throw_item_ob except: print('\twarning: could not find object to throw') print('\tmissing from scene. Add it to a background layer:', throw_item_ob) return # just aim ahead # we tried auto aim but it ended up not working well for moving objects own_y_throw = own.getAxisVect((0.0, 8.0, 0.0)) own_y_throw[2] += 2.0 throw_actu.instantAddObject() ob_throw = throw_actu.objectLastCreated # Position the object since its at friankies middle # you can place the 3D cursor to double check these values ob_throw.localPosition = Vector(own.worldPosition) + Vector( own.getAxisVect([0.2, 0.422, 0.455])) if 'projectile_id' in ob_throw: ob_throw['projectile_id'] = own['id'] # so we dont let it his us. ob_throw.setLinearVelocity(own_y_throw) # Decrement the number of items we have item_count = own[throw_item_ob] - 1 if item_count <= 0: # No Items? - Set to zero # own['throw_item'] = '' # Next available item propVal = 0 for propName in own.getPropertyNames(): if propName != throw_item_ob and propName.startswith('item_'): propVal = own[propName] if propVal: # We have some items in our inventory own['throw_item'] = propName break # No Items Left if not propVal: own['throw_item'] = '' own[throw_item_ob] = 0 else: # Decrement own[throw_item_ob] = item_count
def main(cont): own = cont.owner own_zpos = own.worldPosition[2] # If we touch ANYTHING, fall out of glide mode. except for a ledge. collide_any = cont.sensors['collide_any'] if collide_any.positive: # If any of these are a bounce object, dont detect a hit. if not [ ob_hit for ob_hit in cont.sensors['collide_any'].hitObjectList if ('bounce' in ob_hit) ]: if own['grounded']: cont.activate('glide_stop_ground') else: cont.activate('glide_stop_air') return own_rig = cont.sensors[ 'rig_linkonly'].owner # The rig owns this! - cheating way ti get the rig/ # print(own.getLinearVelocity()) # First check if we should quit gliding if cont.sensors['key_jump_off'].positive or own['grounded']: if own['grounded']: cont.activate('glide_stop_ground') else: cont.activate('glide_stop_air') own_rig.timeOffset = own_rig['defTimeOffset'] return KEY_UP = cont.sensors['key_up'].positive if not KEY_UP: KEY_DOWN = cont.sensors['key_down'].positive else: KEY_DOWN = False # Initialize the height, so we can disallow ever getting higher if cont.sensors['true_init_pulse_rep'].positive: own['glide_z_init'] = own_zpos #### own.glide_swooped = 0 jump_time = 0.0 own['jump_time'] = TIME_OFFSET # Reuse this for timing our glide since we cant jump once gliding anyway own_rig.timeOffset = GLIDE_SLOWPARENT_TIMEOFS else: jump_time = own['jump_time'] - TIME_OFFSET if KEY_UP and jump_time > 1.0: jump_time = ((jump_time - 1) * 0.5) + 1 own['jump_time'] = jump_time + TIME_OFFSET # Scale down the timeoffset ### own_rig.timeOffset *= 0.9 # pprint(jump_time, 'jump_time') glide = cont.actuators['glide_py'] # Rotation and aligning are now handled in actuators vel = own.getLinearVelocity() own_y = own.getAxisVect((0.0, 1.0, 0.0)) # ------------------------- # own_y[2] MUST BE BETWEEN GLIDE_PITCH_LIMIT_MIN and GLIDE_PITCH_LIMIT_MAX # not hard to ensure, but if adjusting the rotate constraint from 45d make sure these change too. speed = -(own_y[2] - GLIDE_PITCH_LIMIT_MIN) / (GLIDE_PITCH_LIMIT_MIN - GLIDE_PITCH_LIMIT_MAX) speed_inv = 1.0 - speed if KEY_UP: drot_x = -GLIDE_SPEED_PITCH elif KEY_DOWN: drot_x = GLIDE_SPEED_PITCH else: drot_x = 0.0 # Set the rotation to tilt forward or back glide.dRot = (drot_x, 0.0, 0.0) # set to local on the actuator # -------------------------- # We COULD just use own_y, but better compensate for the existing # Calculate XY! orig_xy_speed = Vector(vel[0], vel[1]).length fac = speed_inv * GLIDE_ACCEL orig_xy_speed += fac * fac if orig_xy_speed > GLIDE_SPEED_LIMIT: orig_xy_speed = GLIDE_SPEED_LIMIT # normalize and scale to original speed, use verbose python own_y_length = Vector(own_y[0], own_y[1]).length new_x = (own_y[0] / own_y_length) * orig_xy_speed new_y = (own_y[1] / own_y_length) * orig_xy_speed #new_xy = Vector(own_y[0], own_y[1]) #new_xy.length = orig_xy_speed # Calculate Z, Heres the logic, # tilting down makes you go faster but also fall quicker # tiltin up makes fall slower but slows you down X/Y motion. # if your not moving fast and tilting back, you fall. # Calculate Z Offset fac = GLIDE_SPEED_FALL_TIME_FAC * jump_time zoffset = GLIDE_SPEED_FALL + fac * fac # jump time means start for gliding here # print(zoffset) if zoffset > 10.0: zoffset = 10.0 if speed > 0.5: # slow down but go up fac = (speed - 0.5) * (1800.0 / (1 + jump_time / 20.0)) zoffset -= (orig_xy_speed / GLIDE_SPEED_LIMIT) * fac fac = 1 + (0.5 - speed) # Raising above 0.5 is bad juju #if own.glide_swooped==2: fac = (fac*fac) new_x *= fac new_y *= fac else: # Falling fac = (speed) * 30 zoffset -= (orig_xy_speed / GLIDE_SPEED_LIMIT) * fac # This 0.98 dampens the forward speed, use the time stuff also fac = 0.98 / (1 + (GLIDE_SPEED_FALL_TIME_FAC * jump_time)) new_x *= fac new_y *= fac new_z = vel[2] - GLIDE_SPEED_FALL_ACCEL * zoffset z_over = own_zpos - own['glide_z_init'] if z_over > 0.0: scaler = (1 + (z_over * 0.2)) new_x = new_x / scaler new_y = new_y / scaler if new_z > 0.0: # only scale down if were riseing new_z = new_z / scaler # # Interpolate velocity if just started jumping! if jump_time < GLIDE_EASE_IN_TIME: fac = jump_time / GLIDE_EASE_IN_TIME faci = 1.0 - fac new_x = new_x * fac + vel[0] * faci new_y = new_y * fac + vel[1] * faci new_z = new_z * fac + vel[2] * faci # print("Interpolate",fac) glide.linV = new_x, new_y, new_z # set to global on the actuator cont.activate(glide)