public void stay_block(BlockCollision collision) { if (on_block_stay.exists) { on_block_stay.data(collision); } }
public void exit_block(BlockCollision collision) { if (on_block_exit.exists) { on_block_exit.data(collision); } }
public void exit_block(BlockCollision collision) { if (OnBlockExit.exists) { OnBlockExit.data(collision); } }
public void enter_block(BlockCollision collision) { if (on_block_enter.exists) { on_block_enter.data(collision); } }
public void enter_block(BlockCollision collision) { if (OnBlockEnter.exists) { OnBlockEnter.data(collision); } }
public void stay_block(BlockCollision collision) { if (OnBlockStay.exists) { OnBlockStay.data(collision); } }
internal void notify_all_block() { if (collision_candidates.Count > 0) { BlockCollision next_collision = collision_candidates.Aggregate( (closest, next_candidate) => closest.distance < next_candidate.distance ? closest : next_candidate); if (current_collisions.Count > 1) { Debug.LogError("This should never happen."); } while (current_collisions.Count > 0) { BlockCollision collision = current_collisions[current_collisions.Count - 1]; collision.self.get_observer().notify_exit_block(collision); collision.other.get_observer().notify_exit_block(collision); } next_collision.self.get_observer().notify_enter_block(next_collision); next_collision.other.get_observer().notify_enter_block(next_collision); collision_candidates.Clear(); } notify_stay_block(); }
internal void notify_enter_block(BlockCollision collision) { current_collisions.Add(collision); foreach (PlanetariaMonoBehaviour observer in observers) { observer.enter_block(collision); } }
public void clear_block_collision() { while (current_collisions.Count > 0) { BlockCollision collision = current_collisions[current_collisions.Count - 1]; collision.self.get_observer().notify_exit_block(collision); collision.other.get_observer().notify_exit_block(collision); current_collisions.Remove(collision); } collision_candidates.Clear(); }
internal void notify_exit_block(BlockCollision collision) { foreach (PlanetariaMonoBehaviour observer in observers) { observer.exit_block(collision); } //Debug.LogError(collision.GetHashCode() + " vs " + (current_collisions.Count > 0 ? current_collisions[0].GetHashCode().ToString() : "")); int before_count = current_collisions.Count; current_collisions.Remove(collision); int after_count = current_collisions.Count; Debug.Assert(before_count > after_count || after_count == 0, before_count + " should be greater than " + after_count + " for " + collision.GetHashCode() + " vs " + (after_count > 0 ? current_collisions[0].GetHashCode().ToString() : "")); }
public void potential_block_collision(Arc arc, PlanetariaCollider collider) { if (planetaria_rigidbody.exists) { if (current_collisions.Count == 0 || current_collisions[0].other != collider) { optional <BlockCollision> collision = BlockCollision.block_collision(this, arc, collider, planetaria_transformation, planetaria_rigidbody.data); if (collision.exists) { if (planetaria_rigidbody.exists) { if (planetaria_rigidbody.data.collide(collision.data, this)) { collision_candidates.Add(collision.data); } } } } } }
public void derail(float x_velocity, float y_velocity) { if (observer.exists && observer.data.colliding()) { BlockCollision collision = observer.data.collisions()[0]; collision.geometry_visitor.move_position(0, transform.scale / 2 * (1 + 1e-3f)); // extrude the player so they do not accidentally re-collide (immediately) // FIXME: magic number, move to Precision.* x_velocity += horizontal_velocity; //y_velocity += vertical_velocity; planetaria_transform.position = collision.geometry_visitor.position(); Vector3 normal = collision.geometry_visitor.normal(); Vector3 right = Bearing.right(planetaria_transform.position, normal); velocity = right * x_velocity + normal * y_velocity; Debug.DrawRay(planetaria_transform.position, velocity, Color.yellow, 1f); acceleration = get_acceleration(); // TODO: accelerate vertically observer.data.clear_block_collision(); observer = new optional <CollisionObserver>(); } }
public bool collide(BlockCollision collision, CollisionObserver observer) { if (this.observer.exists) { this.observer.data.clear_block_collision(); } aerial_move(-collision.overshoot); // this only (truly) works with perpendicular vectors? this.observer = observer; this.collision = collision; horizontal_velocity = Vector3.Dot(velocity, Bearing.right(planetaria_transform.position, collision.geometry_visitor.normal())); vertical_velocity = Vector3.Dot(velocity, collision.geometry_visitor.normal()); if (vertical_velocity < 0) { vertical_velocity *= -collision.elasticity; } grounded_accelerate(0); return(this.observer.exists); }
public static optional <BlockCollision> block_collision(CollisionObserver observer, Arc arc, PlanetariaCollider collider, PlanetariaTransform transformation, PlanetariaRigidbody rigidbody) { optional <ArcVisitor> arc_visitor = collider.shape.arc_visitor(arc); if (!arc_visitor.exists) { Debug.LogError("This should never happen"); return(new optional <BlockCollision>()); } Quaternion block_to_world = collider.gameObject.internal_game_object.transform.rotation; Quaternion world_to_block = Quaternion.Inverse(block_to_world); Vector3 last_position = world_to_block * rigidbody.get_previous_position(); Vector3 current_position = world_to_block * rigidbody.get_position(); float extrusion = transformation.scale / 2; optional <Vector3> intersection_point = PlanetariaIntersection.arc_path_intersection(arc, last_position, current_position, extrusion); if (!intersection_point.exists) // theoretically only happens with moving objects for discrete collision checks { // these functions are general inverses of one another, but also serve to constrain/normalize the position to the arc path. float intersection_angle = arc.position_to_angle(current_position); if (Mathf.Abs(intersection_angle) <= arc.angle() / 2) // if the intersection is valid { intersection_point = arc.position(intersection_angle); // set the collision to the extruded collision point } } if (!intersection_point.exists) { Debug.LogError("Research why this happened."); return(new optional <BlockCollision>()); } BlockCollision result = new BlockCollision(); float angle = arc.position_to_angle(intersection_point.data); result.geometry_visitor = ShapeVisitor.geometry_visitor(arc_visitor.data, angle, extrusion, collider.gameObject.internal_game_object.transform); intersection_point.data = block_to_world * intersection_point.data; result.distance = Vector3.Angle(intersection_point.data, rigidbody.get_previous_position()) * Mathf.Deg2Rad; result.overshoot = Vector3.Angle(intersection_point.data, rigidbody.get_position()) * Mathf.Deg2Rad; result.observer = observer; result.self = observer.collider(); result.other = collider; PlanetariaPhysicMaterial self = result.self.material; PlanetariaPhysicMaterial other = result.other.material; result.elasticity = PlanetariaPhysics.blend( self.elasticity, self.elasticity_combine, other.elasticity, other.elasticity_combine); result.friction = PlanetariaPhysics.blend( self.friction, self.friction_combine, other.friction, other.friction_combine); result.magnetism = -(self.magnetism - other.magnetism * self.induced_magnetism_multiplier) * (other.magnetism - self.magnetism * other.induced_magnetism_multiplier); return(result); }