/*
* 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.common.defaultprojectcreators;
import android.content.Context;
import com.badlogic.gdx.math.Vector2;
import org.catrobat.catroid.ProjectManager;
import org.catrobat.catroid.R;
import org.catrobat.catroid.common.Constants;
import org.catrobat.catroid.common.LookData;
import org.catrobat.catroid.common.MessageContainer;
import org.catrobat.catroid.content.BroadcastScript;
import org.catrobat.catroid.content.CollisionScript;
import org.catrobat.catroid.content.Project;
import org.catrobat.catroid.content.Script;
import org.catrobat.catroid.content.SingleSprite;
import org.catrobat.catroid.content.Sprite;
import org.catrobat.catroid.content.StartScript;
import org.catrobat.catroid.content.WhenScript;
import org.catrobat.catroid.content.bricks.Brick;
import org.catrobat.catroid.content.bricks.BroadcastBrick;
import org.catrobat.catroid.content.bricks.ComeToFrontBrick;
import org.catrobat.catroid.content.bricks.ForeverBrick;
import org.catrobat.catroid.content.bricks.HideBrick;
import org.catrobat.catroid.content.bricks.IfOnEdgeBounceBrick;
import org.catrobat.catroid.content.bricks.LoopEndBrick;
import org.catrobat.catroid.content.bricks.PlaceAtBrick;
import org.catrobat.catroid.content.bricks.PointInDirectionBrick;
import org.catrobat.catroid.content.bricks.SetLookBrick;
import org.catrobat.catroid.content.bricks.SetSizeToBrick;
import org.catrobat.catroid.content.bricks.ShowBrick;
import org.catrobat.catroid.content.bricks.WaitBrick;
import org.catrobat.catroid.formulaeditor.Formula;
import org.catrobat.catroid.io.StorageHandler;
import org.catrobat.catroid.physics.PhysicsCollision;
import org.catrobat.catroid.physics.PhysicsObject;
import org.catrobat.catroid.physics.content.bricks.SetBounceBrick;
import org.catrobat.catroid.physics.content.bricks.SetFrictionBrick;
import org.catrobat.catroid.physics.content.bricks.SetGravityBrick;
import org.catrobat.catroid.physics.content.bricks.SetPhysicsObjectTypeBrick;
import org.catrobat.catroid.physics.content.bricks.TurnLeftSpeedBrick;
import org.catrobat.catroid.ui.fragment.SpriteFactory;
import org.catrobat.catroid.utils.ImageEditing;
import org.catrobat.catroid.utils.UtilFile;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class DefaultProjectCreatorPhysics extends DefaultProjectCreator {
private static SpriteFactory spriteFactory = new SpriteFactory();
private Vector2 backgroundImageScaleVector;
public DefaultProjectCreatorPhysics() {
standardProjectNameID = R.string.default_project_name_physics;
}
@Override
public Project createDefaultProject(String projectName, Context context, boolean landscapeMode)
throws
IOException,
IllegalArgumentException {
if (StorageHandler.getInstance().projectExists(projectName)) {
throw new IllegalArgumentException("Project with name '" + projectName + "' already exists!");
}
String backgroundName = context.getString(R.string.default_project_background_name);
Project defaultPhysicsProject = new Project(context, projectName);
String sceneName = defaultPhysicsProject.getDefaultScene().getName();
defaultPhysicsProject.setDeviceData(context);
StorageHandler.getInstance().saveProject(defaultPhysicsProject);
ProjectManager.getInstance().setProject(defaultPhysicsProject);
backgroundImageScaleVector = ImageEditing.calculateScaleFactorsToScreenSize(
R.drawable.physics_background_480_800, context);
backgroundImageScaleFactor = ImageEditing.calculateScaleFactorToScreenSize(
R.drawable.physics_background_480_800, context);
File backgroundFile = UtilFile.copyImageFromResourceIntoProject(projectName, sceneName, backgroundName
+ Constants.IMAGE_STANDARD_EXTENSION, R.drawable.physics_background_480_800, context, true,
backgroundImageScaleFactor);
LookData backgroundLookData = new LookData(backgroundName, backgroundFile.getName());
// Background sprite
Sprite backgroundSprite = defaultPhysicsProject.getDefaultScene().getSpriteList().get(0);
backgroundSprite.getLookDataList().add(backgroundLookData);
Sprite ball = spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Ball");
Sprite leftButton = spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Left button");
Sprite rightButton = spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Right button");
Sprite leftArm = spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Left arm");
Sprite rightArm = spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Right arm");
Sprite[] upperBouncers = { spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Left cat bouncer"),
spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Middle cat bouncer"),
spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Right cat bouncer") };
Sprite[] lowerBouncers = { spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Left circle bouncer"),
spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Middle circle bouncer"),
spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Right circle bouncer") };
Sprite middleBouncer = spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Cat head bouncer");
Sprite leftHardBouncer = spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Left hard bouncer");
Sprite rightHardBouncer = spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Right hard bouncer");
Sprite leftBottomWall = spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Left bottom wall");
Sprite rightBottomWall = spriteFactory.newInstance(SingleSprite.class.getSimpleName(), "Right bottom wall");
String restartName = "Restart Game";
Sprite restart = spriteFactory.newInstance(SingleSprite.class.getSimpleName(), restartName);
final String leftButtonPressed = "Left button pressed";
final String rightButtonPressed = "Right button pressed";
final float armMovingSpeed = 500.0f;
// Ball
StartScript startScript = new StartScript();
startScript.addBrick(new SetGravityBrick(new Vector2(0.0f, -35.0f * backgroundImageScaleVector.y)));
ball.addScript(startScript);
Script ballStartScript = createElement(context, projectName, sceneName, ball, "physics_pinball",
R.drawable.physics_pinball, new Vector2(0.0f, 380.0f),
Float.NaN);
setPhysicsProperties(ball, ballStartScript, PhysicsObject.Type.DYNAMIC, 60.0f, 40.0f);
Brick foreverBrick = new ForeverBrick();
Brick ifOnEdgeBounceBrick = new IfOnEdgeBounceBrick();
Brick foreverEndBrick = new LoopEndBrick();
ballStartScript.addBrick(foreverBrick);
ballStartScript.addBrick(ifOnEdgeBounceBrick);
ballStartScript.addBrick(foreverEndBrick);
Script receiveResetBallScript = new BroadcastScript("reset_ball");
receiveResetBallScript.addBrick(new HideBrick());
ball.addScript(receiveResetBallScript);
Script receiveStartBallScript = new BroadcastScript("start_ball");
receiveStartBallScript.addBrick(new PlaceAtBrick(new Formula(0),
new Formula(380.0f * backgroundImageScaleVector.y)));
receiveStartBallScript.addBrick(new ShowBrick());
ball.addScript(receiveStartBallScript);
// Restart View
Script startScriptRestart = createElement(context, projectName, sceneName, restart, "physics_restart",
R.drawable.physics_restart, new Vector2(0.0f, -490.0f), Float.NaN);
setPhysicsProperties(restart, startScriptRestart, PhysicsObject.Type.FIXED, 60.0f, 40.0f);
startScriptRestart.addBrick(new ComeToFrontBrick());
Script physicsCollisionScript = new CollisionScript(restartName + PhysicsCollision.COLLISION_MESSAGE_CONNECTOR + "Ball");
physicsCollisionScript.addBrick(new BroadcastBrick("reset_ball"));
physicsCollisionScript.addBrick(new PlaceAtBrick(0, 0));
restart.addScript(physicsCollisionScript);
Script tapOnRestartScript = new WhenScript();
tapOnRestartScript.addBrick(new BroadcastBrick("start_ball"));
tapOnRestartScript.addBrick(new PlaceAtBrick(new Formula(0), new Formula(-490 * backgroundImageScaleVector.y)));
restart.addScript(tapOnRestartScript);
// Buttons
createElement(context, projectName, sceneName, leftButton, "physics_button", R.drawable.physics_button, new Vector2(-180.0f, -325.0f), Float.NaN, 70f);
createButtonPressed(context, projectName, sceneName, leftButton, leftButtonPressed);
createElement(context, projectName, sceneName, rightButton, "physics_button", R.drawable.physics_button, new Vector2(180.0f, -325.0f), Float.NaN, 70f);
createButtonPressed(context, projectName, sceneName, rightButton, rightButtonPressed);
// Arms
Script leftArmStartScript = createElement(context, projectName, sceneName, leftArm, "physics_left_arm", R.drawable.physics_left_arm,
new Vector2(-102.0f, -285f), Float.NaN);
setPhysicsProperties(leftArm, leftArmStartScript, PhysicsObject.Type.FIXED, 50.0f, -1.0f);
createMovingArm(leftArm, leftButtonPressed, armMovingSpeed);
Script rightArmStartScript = createElement(context, projectName, sceneName, rightArm, "physics_right_arm", R.drawable.physics_right_arm, new Vector2(102.0f,
-285.0f), Float.NaN);
setPhysicsProperties(rightArm, rightArmStartScript, PhysicsObject.Type.FIXED, 50.0f, -1.0f);
createMovingArm(rightArm, rightButtonPressed, -armMovingSpeed);
Script leftBottomWallStartScript = createElement(context, projectName, sceneName, leftBottomWall, "physics_wall_left", R.drawable.physics_wall_left,
new Vector2(-180.0f, -220.0f), Float.NaN, 65f);
setPhysicsProperties(leftBottomWall, leftBottomWallStartScript, PhysicsObject.Type.FIXED, 5.0f, -1.0f);
Script rightBottomWallStartScript = createElement(context, projectName, sceneName, rightBottomWall, "physics_wall_right", R.drawable.physics_wall_right,
new Vector2(180.0f, -220.0f), Float.NaN, 65f);
setPhysicsProperties(rightBottomWall, rightBottomWallStartScript, PhysicsObject.Type.FIXED, 5.0f, -1.0f);
// Hard Bouncer
Script leftHardBouncerStartScript = createElement(context, projectName, sceneName, leftHardBouncer, "physics_left_hard_bouncer",
R.drawable.physics_left_hard_bouncer, new Vector2(-140.0f, -130.0f), Float.NaN);
setPhysicsProperties(leftHardBouncer, leftHardBouncerStartScript, PhysicsObject.Type.FIXED, 10.0f, -1.0f);
Script rightHardBouncerStartScript = createElement(context, projectName, sceneName, rightHardBouncer, "physics_right_hard_bouncer",
R.drawable.physics_right_hard_bouncer, new Vector2(140.0f, -130.0f), Float.NaN);
setPhysicsProperties(rightHardBouncer, rightHardBouncerStartScript, PhysicsObject.Type.FIXED, 10.0f, -1.0f);
// Lower circle bouncers
Vector2[] lowerBouncersPositions = { new Vector2(-100.0f, 0.0f),
new Vector2(0.0f, -70.0f), new Vector2(100.0f, 0.0f) };
for (int index = 0; index < lowerBouncers.length; index++) {
Script lowerBouncerStartScript = createElement(context, projectName, sceneName, lowerBouncers[index], "physics_bouncer_100",
R.drawable.physics_bouncer_100, lowerBouncersPositions[index], Float.NaN, 60f);
setPhysicsProperties(lowerBouncers[index], lowerBouncerStartScript, PhysicsObject.Type.FIXED, 116.0f, -1.0f);
}
// Middle bouncer
Script middleBouncerStartScript = createElement(context, projectName, sceneName, middleBouncer, "physics_square", R.drawable.physics_square, new Vector2(0.0f,
150.0f), Float.NaN, 65f);
setPhysicsProperties(middleBouncer, middleBouncerStartScript, PhysicsObject.Type.FIXED, 40.0f, 80.0f);
middleBouncerStartScript.addBrick(new TurnLeftSpeedBrick(100));
// Upper bouncers
Vector2[] upperBouncersPositions = { new Vector2(-150.0f, 200.0f), new Vector2(0.0f, 300.f),
new Vector2(150.0f, 200.0f) };
for (int index = 0; index < upperBouncers.length; index++) {
Script upperBouncersStartScript = createElement(context, projectName, sceneName, upperBouncers[index], "physics_bouncer_200",
R.drawable.physics_bouncer_200, upperBouncersPositions[index], Float.NaN, 50f);
setPhysicsProperties(upperBouncers[index], upperBouncersStartScript, PhysicsObject.Type.FIXED, 106.0f, -1.0f);
}
defaultPhysicsProject.getDefaultScene().addSprite(leftButton);
defaultPhysicsProject.getDefaultScene().addSprite(rightButton);
defaultPhysicsProject.getDefaultScene().addSprite(ball);
defaultPhysicsProject.getDefaultScene().addSprite(leftArm);
defaultPhysicsProject.getDefaultScene().addSprite(rightArm);
defaultPhysicsProject.getDefaultScene().addSprite(middleBouncer);
defaultPhysicsProject.getDefaultScene().addSprite(leftHardBouncer);
defaultPhysicsProject.getDefaultScene().addSprite(rightHardBouncer);
defaultPhysicsProject.getDefaultScene().addSprite(leftBottomWall);
defaultPhysicsProject.getDefaultScene().addSprite(rightBottomWall);
defaultPhysicsProject.getDefaultScene().addSprite(restart);
for (Sprite sprite : upperBouncers) {
defaultPhysicsProject.getDefaultScene().addSprite(sprite);
}
for (Sprite sprite : lowerBouncers) {
defaultPhysicsProject.getDefaultScene().addSprite(sprite);
}
StorageHandler.getInstance().saveProject(defaultPhysicsProject);
return defaultPhysicsProject;
}
private Script createElement(Context context, String projectName, String sceneName, Sprite sprite, String fileName,
int fileId,
Vector2 position, float angle) throws IOException {
return createElement(context, projectName, sceneName, sprite, fileName, fileId, position, angle, 100.0f);
}
private Script createElement(Context context, String projectName, String sceneName, Sprite sprite, String fileName,
int fileId,
Vector2 position, float angle, float scale) throws IOException {
File file = UtilFile.copyImageFromResourceIntoProject(projectName, sceneName, fileName, fileId, context, true,
backgroundImageScaleFactor);
LookData lookData = new LookData(fileName, file.getName());
List<LookData> looks = sprite.getLookDataList();
looks.add(lookData);
Script startScript = new StartScript();
startScript.addBrick(new PlaceAtBrick(new Formula(position.x * backgroundImageScaleVector.x), new Formula(position.y * backgroundImageScaleVector.y)));
if (scale != 100f) {
SetSizeToBrick setSizeToBrick = new SetSizeToBrick(scale);
startScript.addBrick(setSizeToBrick);
}
if (!Float.isNaN(angle)) {
PointInDirectionBrick pointInDirectionBrick = new PointInDirectionBrick(new Formula(angle));
startScript.addBrick(pointInDirectionBrick);
}
sprite.addScript(startScript);
return startScript;
}
private Script setPhysicsProperties(Sprite sprite, Script startScript, PhysicsObject.Type type,
float bounce, float friction) {
if (startScript == null) {
startScript = new StartScript();
}
startScript.addBrick(new SetPhysicsObjectTypeBrick(type));
if (bounce >= 0.0f) {
startScript.addBrick(new SetBounceBrick(bounce));
}
if (friction >= 0.0f) {
startScript.addBrick(new SetFrictionBrick(friction));
}
sprite.addScript(startScript);
return startScript;
}
private void createButtonPressed(Context context, String projectName, String sceneName, Sprite sprite, String
broadcastMessage)
throws IOException {
MessageContainer.addMessage(broadcastMessage);
WhenScript whenPressedScript = new WhenScript();
whenPressedScript.setAction(0);
BroadcastBrick leftButtonBroadcastBrick = new BroadcastBrick(broadcastMessage);
String filename = "button_pressed";
File file = UtilFile.copyImageFromResourceIntoProject(projectName, sceneName, filename, R.drawable
.physics_button_pressed, context, true, backgroundImageScaleFactor);
LookData lookData = new LookData(filename, file.getName());
List<LookData> looks = sprite.getLookDataList();
looks.add(lookData);
SetLookBrick lookBrick = new SetLookBrick();
lookBrick.setLook(lookData);
WaitBrick waitBrick = new WaitBrick(200);
SetLookBrick lookBack = new SetLookBrick();
lookBack.setLook(looks.get(0));
whenPressedScript.addBrick(leftButtonBroadcastBrick);
whenPressedScript.addBrick(lookBrick);
whenPressedScript.addBrick(waitBrick);
whenPressedScript.addBrick(lookBack);
sprite.addScript(whenPressedScript);
}
private void createMovingArm(Sprite sprite, String broadcastMessage, float degreeSpeed) {
BroadcastScript broadcastScript = new BroadcastScript(broadcastMessage);
int waitInMillis = 110;
broadcastScript.addBrick(new TurnLeftSpeedBrick(degreeSpeed));
broadcastScript.addBrick(new WaitBrick(waitInMillis));
broadcastScript.addBrick(new TurnLeftSpeedBrick(0));
broadcastScript.addBrick(new PointInDirectionBrick(90.0f));
sprite.addScript(broadcastScript);
}
}