Home | History | Annotate | Download | only in replicaisland
      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 
     17 package com.replica.replicaisland;
     18 
     19 
     20 public 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