/*
* The MIT License (MIT)
*
* FXGL - JavaFX Game Library
*
* Copyright (c) 2015-2017 AlmasB (almaslvl@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.almasb.fxglgames.breakout;
import com.almasb.fxgl.app.ApplicationMode;
import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.audio.Music;
import com.almasb.fxgl.core.math.FXGLMath;
import com.almasb.fxgl.ecs.Entity;
import com.almasb.fxgl.effect.ParticleControl;
import com.almasb.fxgl.effect.ParticleEmitter;
import com.almasb.fxgl.entity.Entities;
import com.almasb.fxgl.entity.EntityView;
import com.almasb.fxgl.entity.RenderLayer;
import com.almasb.fxgl.entity.component.PositionComponent;
import com.almasb.fxgl.gameplay.Level;
import com.almasb.fxgl.input.UserAction;
import com.almasb.fxgl.parser.text.TextLevelParser;
import com.almasb.fxgl.physics.CollisionHandler;
import com.almasb.fxgl.settings.GameSettings;
import com.almasb.fxglgames.breakout.control.BallControl;
import com.almasb.fxglgames.breakout.control.BatControl;
import com.almasb.fxglgames.breakout.control.BrickControl;
import javafx.animation.PathTransition;
import javafx.geometry.Point2D;
import javafx.scene.effect.BlendMode;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.QuadCurve;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.util.Duration;
/**
* @author Almas Baimagambetov (almaslvl@gmail.com)
*/
public class BreakoutApp extends GameApplication {
private BatControl getBatControl() {
return getGameWorld().getEntitiesByType(BreakoutType.BAT).get(0).getControlUnsafe(BatControl.class);
}
private BallControl getBallControl() {
return getGameWorld().getEntitiesByType(BreakoutType.BALL).get(0).getControlUnsafe(BallControl.class);
}
@Override
protected void initSettings(GameSettings settings) {
settings.setTitle("Breakout Underwater");
settings.setVersion("0.1");
settings.setWidth(600);
settings.setHeight(800);
settings.setIntroEnabled(false);
settings.setMenuEnabled(false);
settings.setProfilingEnabled(false);
settings.setCloseConfirmation(false);
settings.setApplicationMode(ApplicationMode.DEVELOPER);
}
@Override
protected void initInput() {
getInput().addAction(new UserAction("Move Left") {
@Override
protected void onAction() {
getBatControl().left();
}
}, KeyCode.A);
getInput().addAction(new UserAction("Move Right") {
@Override
protected void onAction() {
getBatControl().right();
}
}, KeyCode.D);
}
@Override
protected void initAssets() {}
@Override
protected void initGame() {
Music music = getAssetLoader().loadMusic("breakout/BGM01.wav");
music.setCycleCount(Integer.MAX_VALUE);
getAudioPlayer().playMusic(music);
TextLevelParser parser = new TextLevelParser(new BreakoutFactory());
Level level = parser.parse("breakout/levels/level1.txt");
getGameWorld().setLevel(level);
getGameWorld().addEntity(Entities.makeScreenBounds(40));
Rectangle bg0 = new Rectangle(getWidth(), getHeight());
LinearGradient gradient = new LinearGradient(getWidth() / 2, 0, getWidth() / 2, getHeight(),
false, CycleMethod.NO_CYCLE, new Stop(0.2, Color.AQUA), new Stop(0.8, Color.BLACK));
bg0.setFill(gradient);
Rectangle bg1 = new Rectangle(getWidth(), getHeight(), Color.color(0, 0, 0, 0.2));
bg1.setBlendMode(BlendMode.DARKEN);
Pane bg = new Pane();
bg.getChildren().addAll(bg0, bg1);
Entities.builder()
.viewFromNode(new EntityView(bg, RenderLayer.BACKGROUND))
.buildAndAttach(getGameWorld());
ParticleEmitter emitter = new ParticleEmitter();
emitter.setSourceImage(getAssetLoader().loadTexture("breakout/bubble.png").getImage());
emitter.setEmissionRate(0.25);
emitter.setExpireFunction((i, x, y) -> Duration.seconds(3));
emitter.setVelocityFunction((i, x, y) -> new Point2D(0, -FXGLMath.random(2f, 4f)));
emitter.setSpawnPointFunction((i, x, y) -> new Point2D(FXGLMath.random(0, (float)getWidth()), y + FXGLMath.random(50)));
emitter.setScaleFunction((i, x, y) -> new Point2D(FXGLMath.random(-0.05f, 0), FXGLMath.random(-0.05f, 0)));
Entity bubbles = new Entity();
bubbles.addComponent(new PositionComponent(0, getHeight()));
bubbles.addControl(new ParticleControl(emitter));
getGameWorld().addEntity(bubbles);
// Level info
}
@Override
protected void initPhysics() {
getPhysicsWorld().setGravity(0, 0);
getPhysicsWorld().addCollisionHandler(new CollisionHandler(BreakoutType.BALL, BreakoutType.BRICK) {
@Override
protected void onCollisionBegin(Entity ball, Entity brick) {
brick.getControlUnsafe(BrickControl.class).onHit();
}
});
}
@Override
protected void initUI() {
Text text = getUIFactory().newText("Level 1", Color.WHITE, 48);
QuadCurve curve = new QuadCurve(-100, 0, getWidth() / 2, getHeight(), getWidth() + 100, 0);
PathTransition transition = new PathTransition(Duration.seconds(4), curve, text);
transition.setOnFinished(e -> {
getGameScene().removeUINode(text);
getBallControl().release();
});
getGameScene().addUINode(text);
transition.play();
}
@Override
protected void onUpdate(double tpf) {}
public static void main(String[] args) {
launch(args);
}
}