/*
* Catroid: An on-device visual programming system for Android devices
* Copyright (C) 2010-2016 The Catrobat Team
* (<http://developer.catrobat.org/credits>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* An additional term exception under section 7 of the GNU Affero
* General Public License, version 3, is available at
* http://developer.catrobat.org/license_additional_term
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.catrobat.catroid.test.physics;
import android.test.AndroidTestCase;
import android.util.Log;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.GdxNativesLoader;
import org.catrobat.catroid.content.Sprite;
import org.catrobat.catroid.physics.PhysicsLook;
import org.catrobat.catroid.physics.PhysicsObject;
import org.catrobat.catroid.physics.PhysicsObject.Type;
import org.catrobat.catroid.physics.PhysicsWorld;
import org.catrobat.catroid.test.utils.Reflection;
import org.catrobat.catroid.test.utils.Reflection.ParameterList;
import java.util.Map;
public class PhysicsWorldTest extends AndroidTestCase {
static {
GdxNativesLoader.load();
}
private static final String TAG = PhysicsObjectTest.class.getSimpleName();
private PhysicsWorld physicsWorld;
private World world;
private Map<Sprite, PhysicsObject> physicsObjects;
@SuppressWarnings("unchecked")
@Override
public void setUp() {
physicsWorld = new PhysicsWorld(1920, 1600);
world = (World) Reflection.getPrivateField(physicsWorld, "world");
physicsObjects = (Map<Sprite, PhysicsObject>) Reflection.getPrivateField(physicsWorld, "physicsObjects");
PhysicsBaseTest.stabilizePhysicsWorld(physicsWorld);
}
@Override
public void tearDown() {
physicsWorld = null;
world = null;
physicsObjects = null;
}
public void testDefaultSettings() {
assertEquals("Wrong configuration", 10.0f, PhysicsWorld.RATIO);
assertEquals("Wrong configuration", 3, PhysicsWorld.VELOCITY_ITERATIONS);
assertEquals("Wrong configuration", 3, PhysicsWorld.POSITION_ITERATIONS);
assertEquals("Wrong configuration", new Vector2(0, -10), PhysicsWorld.DEFAULT_GRAVITY);
assertFalse("Wrong configuration", PhysicsWorld.IGNORE_SLEEPING_OBJECTS);
assertEquals("Wrong configuration", 6, Reflection.getPrivateField(physicsWorld, "STABILIZING_STEPS"));
short expectedCategoryBoundaryBox = 0x0002;
short expectedCategoryPhysicsObject = 0x0004;
assertEquals("Wrong configuration", 0x0000, PhysicsWorld.CATEGORY_NO_COLLISION);
assertEquals("Wrong configuration", expectedCategoryBoundaryBox, PhysicsWorld.CATEGORY_BOUNDARYBOX);
assertEquals("Wrong configuration", expectedCategoryPhysicsObject, PhysicsWorld.CATEGORY_PHYSICSOBJECT);
assertEquals("Wrong configuration", expectedCategoryPhysicsObject, PhysicsWorld.MASK_BOUNDARYBOX);
assertEquals("Wrong configuration", ~expectedCategoryBoundaryBox, PhysicsWorld.MASK_PHYSICSOBJECT);
assertEquals("Wrong configuration", -1, PhysicsWorld.MASK_TO_BOUNCE);
assertEquals("Wrong configuration", 0, PhysicsWorld.MASK_NO_COLLISION);
}
public void testWrapper() {
assertNotNull("Didn't load box2d wrapper", world);
}
public void testGravity() {
assertEquals("Wrong initialization", PhysicsWorld.DEFAULT_GRAVITY, world.getGravity());
Vector2 newGravity = new Vector2(-1.2f, 3.4f);
physicsWorld.setGravity(newGravity.x, newGravity.y);
assertEquals("Did not update gravity", newGravity, world.getGravity());
}
public void testGetNullPhysicsObject() {
try {
physicsWorld.getPhysicsObject(null);
fail("Get physics object of a null sprite didn't cause a null pointer exception");
} catch (NullPointerException exception) {
Log.d(TAG, "Exception thrown as expected");
}
}
public void testGetPhysicsObject() {
Sprite sprite = new Sprite("TestSprite");
PhysicsObject physicsObject = physicsWorld.getPhysicsObject(sprite);
assertNotNull("No physics object was created", physicsObject);
assertEquals("Wrong number of physics objects were stored", 1, physicsObjects.size());
assertTrue("Sprite wasn't saved into physics object map", physicsObjects.containsKey(sprite));
assertEquals("Wrong map relation for sprite", physicsObject, physicsObjects.get(sprite));
}
public void testCreatePhysicsObject() {
Object[] values = { new Sprite("testsprite") };
ParameterList paramList = new ParameterList(values);
PhysicsObject physicsObject = (PhysicsObject) Reflection.invokeMethod(physicsWorld, "createPhysicsObject",
paramList);
assertEquals("Type is not the expected", Type.NONE, physicsObject.getType());
}
public void testGetSamePhysicsObject() {
Sprite sprite = new Sprite("TestSprite");
PhysicsObject physicsObject = physicsWorld.getPhysicsObject(sprite);
PhysicsObject samePhysicsObject = physicsWorld.getPhysicsObject(sprite);
assertEquals("Wrong number of physics objects stored", 1, physicsObjects.size());
assertEquals("Physics objects are different", physicsObject, samePhysicsObject);
}
public void testSteps() throws SecurityException, IllegalArgumentException, NoSuchFieldException,
IllegalAccessException {
Sprite sprite = new Sprite("TestSprite");
sprite.look = new PhysicsLook(sprite, physicsWorld);
PhysicsObject physicsObject = physicsWorld.getPhysicsObject(sprite);
Vector2 velocity = new Vector2(2.3f, 4.5f);
float rotationSpeed = 45.0f;
physicsWorld.setGravity(0.0f, 0.0f);
assertEquals("Physics object has a wrong start position", new Vector2(), physicsObject.getPosition());
physicsObject.setVelocity(velocity.x, velocity.y);
physicsObject.setRotationSpeed(rotationSpeed);
physicsWorld.step(1.0f);
assertEquals("Wrong x position", velocity.x, physicsObject.getX(), 1e-8);
assertEquals("Wrong y position", velocity.y, physicsObject.getY(), 1e-8);
assertEquals("Wrong angle", rotationSpeed, physicsObject.getDirection(), 1e-8);
// TODO[Physics] angle problem
physicsWorld.step(1.0f);
assertEquals("Wrong x position", 2 * velocity.x, physicsObject.getX(), 1e-8);
assertEquals("Wrong y position", 2 * velocity.y, physicsObject.getY(), 1e-8);
assertEquals("Wrong angle", 2 * rotationSpeed, physicsObject.getDirection(), 1e-8);
}
}