1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.replica.replicaisland; 18 19 20public class OrbitalMagnetComponent extends GameComponent { 21 private final static float DEFAULT_STRENGTH = 15.0f; 22 23 private float mStrength; 24 private Vector2 mCenter; 25 private Vector2 mDelta; 26 private Vector2 mRim; 27 private Vector2 mVelocity; 28 private float mMagnetRadius; 29 private float mAreaRadius; 30 31 public OrbitalMagnetComponent() { 32 super(); 33 mCenter = new Vector2(); 34 mDelta = new Vector2(); 35 mRim = new Vector2(); 36 mVelocity = new Vector2(); 37 reset(); 38 setPhase(ComponentPhases.COLLISION_DETECTION.ordinal()); 39 } 40 41 @Override 42 public void reset() { 43 mCenter.zero(); 44 mDelta.zero(); 45 mRim.zero(); 46 mVelocity.zero(); 47 mStrength = DEFAULT_STRENGTH; 48 mAreaRadius = 0.0f; 49 mMagnetRadius = 0.0f; 50 } 51 52 @Override 53 public void update(float timeDelta, BaseObject parent) { 54 GameObjectManager manager = sSystemRegistry.gameObjectManager; 55 if (manager != null) { 56 GameObject player = manager.getPlayer(); 57 if (player != null) { 58 GameObject parentObject = (GameObject)parent; 59 applyMagnetism(player, 60 parentObject.getCenteredPositionX(), 61 parentObject.getCenteredPositionY(), 62 timeDelta); 63 } 64 } 65 } 66 67 private void applyMagnetism(GameObject target, float centerX, float centerY, float timeDelta) { 68 mCenter.set(centerX, centerY); 69 final float targetX = target.getCenteredPositionX(); 70 final float targetY = target.getCenteredPositionY(); 71 mDelta.set(targetX, targetY); 72 mDelta.subtract(mCenter); 73 74 final float distanceFromCenter2 = mDelta.length2(); 75 final float area2 = mAreaRadius * mAreaRadius; 76 if (distanceFromCenter2 < area2) { 77 mRim.set(mDelta); 78 mRim.normalize(); 79 mRim.multiply(mMagnetRadius); 80 mRim.add(mCenter); 81 // rim is now the closest point on the magnet circle 82 83 // remove gravity 84 final Vector2 targetVelocity = target.getVelocity(); 85 GravityComponent gravity = target.findByClass(GravityComponent.class); 86 final Vector2 gravityVector = gravity.getGravity(); 87 mVelocity.set(gravityVector); 88 mVelocity.multiply(timeDelta); 89 targetVelocity.subtract(mVelocity); 90 91 mDelta.add(targetVelocity); 92 mDelta.normalize(); 93 mDelta.multiply(mMagnetRadius); 94 mDelta.add(mCenter); 95 96 // mDelta is now the next point on the magnet circle in the direction of 97 // movement. 98 99 mDelta.subtract(mRim); 100 mDelta.normalize(); 101 // Now mDelta is the tangent to the magnet circle, pointing in the direction 102 // of movement. 103 104 mVelocity.set(mDelta); 105 mVelocity.normalize(); 106 107 // mVelocity is now the direction to push the player 108 109 mVelocity.multiply(mStrength); 110 float weight = 1.0f; 111 if (distanceFromCenter2 > mMagnetRadius * mMagnetRadius) { 112 float distance = (float)Math.sqrt(distanceFromCenter2); 113 weight = (distance - mMagnetRadius) / (mAreaRadius - mMagnetRadius); 114 weight = 1.0f - weight; 115 mVelocity.multiply(weight); 116 } 117 final float speed = targetVelocity.length(); 118 targetVelocity.add(mVelocity); 119 if (targetVelocity.length2() > (speed * speed)) { 120 targetVelocity.normalize(); 121 targetVelocity.multiply(speed); 122 } 123 124 } 125 126 } 127 128 public void setup(float areaRadius, float orbitRadius) { 129 mAreaRadius = areaRadius; 130 mMagnetRadius = orbitRadius; 131 } 132} 133