/* * 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.actions; import android.util.Log; import com.badlogic.gdx.scenes.scene2d.Action; import org.catrobat.catroid.common.ScreenValues; import org.catrobat.catroid.content.ActionFactory; import org.catrobat.catroid.content.CollisionScript; import org.catrobat.catroid.content.Sprite; import org.catrobat.catroid.content.bricks.PlaceAtBrick; import org.catrobat.catroid.physics.PhysicsCollision; import org.catrobat.catroid.physics.PhysicsObject; import org.catrobat.catroid.physics.PhysicsWorld; import org.catrobat.catroid.physics.content.actions.IfOnEdgeBouncePhysicsAction; import org.catrobat.catroid.test.physics.PhysicsBaseTest; import org.catrobat.catroid.test.utils.Reflection; import org.catrobat.catroid.test.utils.TestUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class IfOnEdgeBouncePhysicsActionTest extends PhysicsBaseTest { private static final String TAG = IfOnEdgeBouncePhysicsActionTest.class.getSimpleName(); private void logState(String explanationText, Sprite sprite, PhysicsObject physicsObject) { Log.d(TAG, explanationText); Log.d(TAG, "getX():" + sprite.look.getXInUserInterfaceDimensionUnit()); Log.d(TAG, "getY():" + sprite.look.getYInUserInterfaceDimensionUnit()); Log.d(TAG, "getVelocity():" + physicsObject.getVelocity().x + " / " + physicsObject.getVelocity().y); Log.d(TAG, "-------------------------------------------------"); } public void testNormalBehavior() { assertTrue("getLookData is null", sprite.look.getLookData() != null); PhysicsObject physicsObject = physicsWorld.getPhysicsObject(sprite); physicsObject.setType(PhysicsObject.Type.DYNAMIC); float setYValue = -ScreenValues.SCREEN_HEIGHT / 2 + 1; // So that nearly the half of the rectangle should be outside of the screen sprite.look.setYInUserInterfaceDimensionUnit(setYValue); float setVelocityYValue = -(IfOnEdgeBouncePhysicsAction.THRESHOLD_VELOCITY_TO_ACTIVATE_BOUNCE - 1.0f); physicsObject.setVelocity(physicsObject.getVelocity().x, setVelocityYValue); assertTrue("Unexpected Y-value", sprite.look.getYInUserInterfaceDimensionUnit() == (setYValue)); ActionFactory factory = sprite.getActionFactory(); Action ifOnEdgeBouncePhysicsAction = factory.createIfOnEdgeBounceAction(sprite); logState("Values after action creation", sprite, physicsObject); ifOnEdgeBouncePhysicsAction.act(0.1f); float setYValueAfterAct = sprite.look.getYInUserInterfaceDimensionUnit(); logState("Values after act of the action", sprite, physicsObject); physicsWorld.step(0.3f); logState("Values after step of physics world", sprite, physicsObject); assertTrue(physicsObject.getY() + " >= " + setYValue, (sprite.look.getYInUserInterfaceDimensionUnit() > setYValueAfterAct)); } public void testVelocityThresholdAtTopCollision() { assertTrue("getLookData is null", sprite.look.getLookData() != null); PhysicsObject physicsObject = physicsWorld.getPhysicsObject(sprite); physicsObject.setType(PhysicsObject.Type.DYNAMIC); float setYValue = ScreenValues.SCREEN_HEIGHT / 2 - 1; // So that nearly the half of the rectangle should be outside of the screen sprite.look.setYInUserInterfaceDimensionUnit(setYValue); float setVelocityYValue = IfOnEdgeBouncePhysicsAction.THRESHOLD_VELOCITY_TO_ACTIVATE_BOUNCE + 0.5f; physicsObject.setVelocity(physicsObject.getVelocity().x, setVelocityYValue); assertTrue("Unexpected Y-value", sprite.look.getY() == setYValue); assertTrue("Unexpected velocity-Y-value", physicsObject.getVelocity().y == setVelocityYValue); ActionFactory factory = sprite.getActionFactory(); Action ifOnEdgeBouncePhysicsAction = factory.createIfOnEdgeBounceAction(sprite); logState("Values after action creation", sprite, physicsObject); ifOnEdgeBouncePhysicsAction.act(0.1f); logState("Values after act of the action", sprite, physicsObject); assertEquals("Unexpected velocity-value (expected = " + setVelocityYValue + "; actual = " + physicsObject.getVelocity().y, setVelocityYValue, physicsObject.getVelocity().y, TestUtils.DELTA); physicsWorld.step(0.3f); logState("Values after step of physics world", sprite, physicsObject); assertTrue(physicsObject.getY() + " < " + setYValue, (sprite.look.getYInUserInterfaceDimensionUnit() < setYValue)); } public void testSpriteOverlapsRightAndTopAxis() { assertTrue("getLookData is null", sprite.look.getLookData() != null); PhysicsObject physicsObject = physicsWorld.getPhysicsObject(sprite); physicsObject.setType(PhysicsObject.Type.DYNAMIC); float setXValue = ScreenValues.SCREEN_WIDTH / 2 - sprite.look.getLookData().getPixmap().getWidth() / 4; sprite.look.setXInUserInterfaceDimensionUnit(setXValue); float setYValue = ScreenValues.SCREEN_HEIGHT / 2 - sprite.look.getLookData().getPixmap().getHeight() / 4; sprite.look.setYInUserInterfaceDimensionUnit(setYValue); float setVelocityXValue = 400.0f; float setVelocityYValue = 400.0f; physicsObject.setVelocity(setVelocityXValue, setVelocityYValue); assertTrue("Unexpected X-value", sprite.look.getX() == setXValue); assertTrue("Unexpected Y-value", sprite.look.getY() == setYValue); assertTrue("Unexpected velocity-X-value", physicsObject.getVelocity().x == setVelocityXValue); assertTrue("Unexpected velocity-Y-value", physicsObject.getVelocity().y == setVelocityYValue); ActionFactory factory = sprite.getActionFactory(); Action ifOnEdgeBouncePhysicsAction = factory.createIfOnEdgeBounceAction(sprite); logState("Values after action creation", sprite, physicsObject); ifOnEdgeBouncePhysicsAction.act(0.1f); logState("Values after first act of the action", sprite, physicsObject); float borderX = sprite.look.getXInUserInterfaceDimensionUnit(); float borderY = sprite.look.getYInUserInterfaceDimensionUnit(); assertTrue(borderX + " < " + setXValue, (borderX < setXValue)); assertTrue(borderY + " < " + setYValue, (borderY < setYValue)); assertEquals("Unexpected velocity-X-value (expected = " + setVelocityXValue + "; actual = " + physicsObject.getVelocity().x, setVelocityXValue, physicsObject.getVelocity().x, TestUtils.DELTA); assertEquals("Unexpected velocity-Y-value (expected = " + setVelocityYValue + "; actual = " + physicsObject.getVelocity().y, setVelocityYValue, physicsObject.getVelocity().y, TestUtils.DELTA); physicsWorld.step(0.1f); logState("Values after first step of physics world", sprite, physicsObject); float prevX = sprite.look.getXInUserInterfaceDimensionUnit(); float prevY = sprite.look.getYInUserInterfaceDimensionUnit(); ifOnEdgeBouncePhysicsAction = factory.createIfOnEdgeBounceAction(sprite); ifOnEdgeBouncePhysicsAction.act(0.1f); assertEquals("second act should not change X-coordinate. (expected = " + prevX + "; actual = " + sprite.look.getXInUserInterfaceDimensionUnit(), prevX, sprite.look.getXInUserInterfaceDimensionUnit(), TestUtils.DELTA); assertEquals("second act should not change Y-coordinate. (expected = " + prevY + "; actual = " + sprite.look.getYInUserInterfaceDimensionUnit(), prevY, sprite.look.getYInUserInterfaceDimensionUnit(), TestUtils.DELTA); logState("Values after second act of the action", sprite, physicsObject); physicsWorld.step(2.3f); logState("Values after second step of physics world", sprite, physicsObject); assertTrue(sprite.look.getXInUserInterfaceDimensionUnit() + " < " + borderX + "(border value X)", (sprite.look.getXInUserInterfaceDimensionUnit() < setXValue)); assertTrue(sprite.look.getYInUserInterfaceDimensionUnit() + " < " + borderY + "(border value Y)", (sprite.look.getYInUserInterfaceDimensionUnit() < setYValue)); } public void testCollisionBroadcastOnIfOnEdgeBounce() { assertTrue("getLookData is null", sprite.look.getLookData() != null); CollisionScript spriteCollisionScript = new CollisionScript(""); spriteCollisionScript.setAndReturnBroadcastMessage(sprite.getName(), PhysicsCollision .COLLISION_WITH_ANYTHING_IDENTIFIER); spriteCollisionScript.getScriptBrick(); int testXValue = 300; int testYValue = 250; PlaceAtBrick testBrick = new PlaceAtBrick(testXValue, testYValue); spriteCollisionScript.addBrick(testBrick); sprite.addScript(spriteCollisionScript); sprite.createStartScriptActionSequenceAndPutToMap(new HashMap<String, List<String>>()); PhysicsObject physicsObject = physicsWorld.getPhysicsObject(sprite); physicsObject.setType(PhysicsObject.Type.DYNAMIC); float setXValue = ScreenValues.SCREEN_WIDTH / 2 - sprite.look.getLookData().getPixmap().getWidth() / 4; sprite.look.setXInUserInterfaceDimensionUnit(setXValue); float setYValue = ScreenValues.SCREEN_HEIGHT / 2 - sprite.look.getLookData().getPixmap().getHeight() / 4; sprite.look.setYInUserInterfaceDimensionUnit(setYValue); assertEquals("SetXValue not the same", setXValue, sprite.look.getXInUserInterfaceDimensionUnit()); assertEquals("setYValue not the same", setYValue, sprite.look.getYInUserInterfaceDimensionUnit()); float setVelocityXValue = 400.0f; float setVelocityYValue = 400.0f; physicsObject.setVelocity(setVelocityXValue, setVelocityYValue); ActionFactory factory = sprite.getActionFactory(); Action ifOnEdgeBouncePhysicsAction = factory.createIfOnEdgeBounceAction(sprite); ArrayList<Sprite> activeVerticalBounces = (ArrayList<Sprite>) Reflection.getPrivateField(PhysicsWorld.class, physicsWorld, "activeVerticalBounces"); ArrayList<Sprite> activeHorizontalBounces = (ArrayList<Sprite>) Reflection.getPrivateField(PhysicsWorld.class, physicsWorld, "activeHorizontalBounces"); assertTrue("Bounce Once Vertical Array is not empty", activeVerticalBounces.isEmpty()); assertTrue("Bounce Once Horizontal Array is not empty", activeHorizontalBounces.isEmpty()); ifOnEdgeBouncePhysicsAction.act(1.0f); assertFalse("Bounce Once Vertical Array is empty", activeVerticalBounces.isEmpty()); assertFalse("Bounce Once Horizontal Array is empty", activeHorizontalBounces.isEmpty()); assertTrue("New X value is not smaller after IfOnEdgeBounce act", setXValue > sprite.look .getXInUserInterfaceDimensionUnit()); assertTrue("New Y value is not smaller after IfOnEdgeBounce act", setYValue > sprite.look .getYInUserInterfaceDimensionUnit()); physicsWorld.step(2.0f); assertTrue("Bounce Once Vertical Array is not empty after colliding once", activeVerticalBounces.isEmpty()); assertTrue("Bounce Once Horizontal Array is not empty after colliding once", activeHorizontalBounces.isEmpty()); while (!allActionsOfAllSpritesAreFinished()) { for (Sprite spriteOfList : project.getDefaultScene().getSpriteList()) { spriteOfList.look.act(1.0f); } } assertEquals("X Value of Sprite was not set", (float) testXValue, sprite.look .getXInUserInterfaceDimensionUnit()); assertEquals("Y Value of Sprite was not set", (float) testYValue, sprite.look .getYInUserInterfaceDimensionUnit()); } public boolean allActionsOfAllSpritesAreFinished() { for (Sprite spriteOfList : project.getDefaultScene().getSpriteList()) { if (!spriteOfList.look.getAllActionsAreFinished()) { return false; } } return true; } }