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