Skip to content
Snippets Groups Projects
Commit e48c8c6a authored by Tor Martin Frøberg Wang's avatar Tor Martin Frøberg Wang
Browse files

Third minigame is done. Completes issue #80

parent 82e552fe
No related branches found
No related tags found
1 merge request!77Resolve "Make a third minigame"
frontend/android/assets/FruitSlicerBackground.png

1.35 MiB

frontend/android/assets/FruitSlicerPhotoEdit.png

128 KiB

File added
File added
......@@ -13,13 +13,13 @@ import com.gameware.game.models.LocalStorage;
import com.gameware.game.states.BubbleWrapState;
import com.gameware.game.models.Player;
import com.gameware.game.states.ColorRushState;
import com.gameware.game.states.FruitCutState;
import com.gameware.game.states.FruitSlicerState;
import com.gameware.game.states.GameStateManager;
import com.gameware.game.states.LoginState;
import com.gameware.game.states.MenuState;
import com.gameware.game.states.PauseState;
import com.gameware.game.states.PlayStateTemplate;
import com.gameware.game.states.LoginState;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
......@@ -30,6 +30,7 @@ public class GameWare extends ApplicationAdapter {
private SpriteBatch batch;
private GameStateManager gsm;
private String fruitSlicerId = "5e90541aeba599f7b1bffceb";
private String colorRushId = "5e5d0efaa6e2bc5cb4920b7a";
private String bubbleWrapId = "5e5d0f1ea6e2bc5cb4920b7b";
......@@ -68,8 +69,11 @@ public class GameWare extends ApplicationAdapter {
}
gsm = GameStateManager.getInstance();
// Playable minigames
gameIdToPlayState.put(fruitSlicerId, new FruitSlicerState(gsm));
gameIdToPlayState.put(colorRushId, new ColorRushState(gsm));
gameIdToPlayState.put(bubbleWrapId, new BubbleWrapState(gsm));
batch = new SpriteBatch();
music = Gdx.audio.newMusic(Gdx.files.internal(("bensound-goinghigher.mp3")));
......
......@@ -15,12 +15,10 @@ public class FruitSprite extends Sprite {
private Vector3 cutVelocity1;
private Vector3 cutVelocity2;
private int cutRotationSpeed;
private int rotationSpeed;
private int cutWidth;
private int cutHeight;
private float totalLifetime;
private float currentLifetime;
private float cuttingVelocity;
private float gravity;
......@@ -30,7 +28,7 @@ public class FruitSprite extends Sprite {
private com.badlogic.gdx.graphics.g2d.Sprite cutFruit1;
private com.badlogic.gdx.graphics.g2d.Sprite cutFruit2;
public FruitSprite(int x, int y, int xVelocity, int yVelocity, int width, int height, Texture uncutFruitTexture){
public FruitSprite(int x, int y, int width, int height, Vector3 velocity, Texture uncutFruitTexture){
this.position = new Vector3(x, y, 0);
this.cutPosition1 = new Vector3(0,0,0);
this.cutPosition2 = new Vector3(0,0,0);
......@@ -38,11 +36,11 @@ public class FruitSprite extends Sprite {
this.cuttingVelocity = Gdx.graphics.getWidth()/2;
this.gravity = Gdx.graphics.getWidth()/3;
this.uncutVelocity = new Vector3(xVelocity,yVelocity,0);
this.uncutVelocity = velocity;
this.cutVelocity1 = new Vector3(-this.cuttingVelocity,0,0);
this.cutVelocity2 = new Vector3(this.cuttingVelocity,0,0);
this.cutRotationSpeed = 180;
this.rotationSpeed = (int) ((Math.random() - 0.5) * 1000);
this.width = width;
this.height = height;
this.cutWidth = width/2;
......@@ -50,9 +48,6 @@ public class FruitSprite extends Sprite {
this.isCut = false;
this.totalLifetime = 5;
this.currentLifetime = 0;
TextureRegion fullTexRegion = new TextureRegion(uncutFruitTexture);
int regionCutWidth = fullTexRegion.getRegionWidth()/2;
......@@ -92,9 +87,9 @@ public class FruitSprite extends Sprite {
@Override
public void update(float dt) {
this.currentLifetime += dt;
if(this.isCut){
// Updates the position of the two fruit pieces based on its velocity
this.cutVelocity1.scl(dt);
this.cutVelocity2.scl(dt);
......@@ -104,28 +99,33 @@ public class FruitSprite extends Sprite {
this.cutVelocity1.scl(1/dt);
this.cutVelocity2.scl(1/dt);
// Sets the position of the two fruit pieces
this.cutFruit1.setPosition(this.cutPosition1.x, this.cutPosition1.y);
this.cutFruit2.setPosition(this.cutPosition2.x, this.cutPosition2.y);
// Gravity affects the fruit pieces' velocity
this.cutVelocity1.y -= this.gravity*2*dt;
this.cutVelocity2.y -= this.gravity*2*dt;
this.cutFruit1.rotate(this.cutRotationSpeed/3*dt);
this.cutFruit2.rotate(-this.cutRotationSpeed/3*dt);
// Oppositely rotates the two pieces by a third of the original rotation speed
this.cutFruit1.rotate(this.rotationSpeed / 3*dt);
this.cutFruit2.rotate(-this.rotationSpeed / 3*dt);
}
else{
// Updates the position of the full fruit based on its velocity
this.uncutVelocity.scl(dt);
this.position.add(this.uncutVelocity.x, this.uncutVelocity.y, 0);
this.uncutVelocity.scl(1/dt);
// Gravity affects the fruit's velocity
this.uncutVelocity.y -= this.gravity*dt;
// Sets the full fruit's size, position and rotation
this.uncutFruit.setOriginCenter();
this.uncutFruit.setSize(this.width, this.height);
this.uncutFruit.setPosition(this.position.x, this.position.y);
this.uncutFruit.rotate(this.cutRotationSpeed*dt);
this.uncutFruit.rotate(this.rotationSpeed * dt);
}
}
......@@ -134,11 +134,13 @@ public class FruitSprite extends Sprite {
}
public boolean isDisposable() {
return this.currentLifetime >= this.totalLifetime;
// If the uncut fruit or the two cut fruit pieces have fallen this far in the y-direction, we know we can dispose it
return this.position.y < -this.height*3 || (this.cutPosition1.y < -this.height*3 && this.cutPosition2.y < -this.height*3);
}
public boolean isPressed(int x, int y) {
if(x > this.position.x && x < (this.position.x + this.width) && (Gdx.graphics.getHeight() - y) > this.position.y && (Gdx.graphics.getHeight() - y) < (this.position.y + this.height)) {
// If the user touched the fruit
if(!this.isCut && x > this.position.x && x < (this.position.x + this.width) && (Gdx.graphics.getHeight() - y) > this.position.y && (Gdx.graphics.getHeight() - y) < (this.position.y + this.height)) {
this.isCut = true;
// Updates the sprite positions
......@@ -151,6 +153,7 @@ public class FruitSprite extends Sprite {
this.cutVelocity1.rotate(this.uncutFruit.getRotation(), 0, 0, 1);
this.cutVelocity2.rotate(this.uncutFruit.getRotation(), 0, 0, 1);
// The two pieces keeps 25% of the original full fruits' velocity
this.cutVelocity1.add((float)(this.uncutVelocity.x*0.25), (float)(this.uncutVelocity.y*0.25), 0);
this.cutVelocity2.add((float)(this.uncutVelocity.x*0.25), (float)(this.uncutVelocity.y*0.25), 0);
......
package com.gameware.game.states;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.gameware.game.sprites.FruitSprite;
import java.util.ArrayList;
import java.util.List;
public class FruitCutState extends PlayStateTemplate {
private float currentDuration = 0f;
private float totalDuration = 30f;
private List<Texture> fruitTextures;
private FruitSprite fruitSprite;
public FruitCutState(GameStateManager gsm) {
super(gsm);
this.fruitTextures = new ArrayList<>();
int textureNum = 0;
while(textureNum < 20){
textureNum++;
String filename = "FruitTexture" + String.valueOf(textureNum) + ".png";
this.fruitTextures.add(new Texture(Gdx.files.internal(filename)));
}
Texture fruit = this.fruitTextures.get((int)(Math.random()*20));
float fruitAspectRatio = Float.valueOf(fruit.getWidth()) / Float.valueOf(fruit.getHeight());
int fruitWidth = 200;
int fruitHeight = (int) (fruitWidth/fruitAspectRatio);
fruitSprite = new FruitSprite(Gdx.graphics.getWidth()/2,Gdx.graphics.getWidth()/2,Gdx.graphics.getWidth()/2,Gdx.graphics.getWidth()/2,fruitWidth,fruitHeight,fruit);
}
@Override
public void handleInput(){
// ----- Din kode her -----
if(Gdx.input.justTouched()) {
int touchX = Gdx.input.getX();
int touchY = Gdx.input.getY();
this.fruitSprite.isPressed(touchX, touchY);
}
// ----- Din kode her -----
}
@Override
public void update(float dt){
super.update(dt);
this.handleInput();
// ----- Din kode her -----
this.currentDuration += dt;
if(this.currentDuration > this.totalDuration){
super.setGameFinished();
}
this.fruitSprite.update(dt);
// ----- Din kode her -----
}
@Override
public void render(SpriteBatch sb){
// ----- Din kode her -----
this.fruitSprite.draw(sb);
// ----- Din kode her -----
super.render(sb);
}
@Override
public void dispose(){
super.dispose();
// ----- Din kode her -----
// ----- Din kode her -----
}
}
package com.gameware.game.states;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector3;
import com.gameware.game.GameWare;
import com.gameware.game.sprites.FruitSprite;
import java.util.ArrayList;
import java.util.List;
public class FruitSlicerState extends PlayStateTemplate {
private float currentDuration = 0f;
private float totalDuration = 60f;
private float startingEmitFrequency = 1f;
private float endingEmitFrequency = 0.2f;
private float timeSinceLastEmit = 0;
private int totalFruitsCut = 0;
private BitmapFont font;
private Texture background = new Texture(Gdx.files.internal("FruitSlicerBackground.png"));
private List<Texture> fruitTextures;
private List<FruitSprite> emittedFruits;
private Sound sliceWhooshSound;
private Sound sliceSquishSound;
private FruitSprite fruitSprite;
public FruitSlicerState(GameStateManager gsm) {
super(gsm);
super.setPauseButtonWhite();
super.screenshot = new Texture(Gdx.files.internal("FruitSlicerPhotoEdit.png"));
this.sliceWhooshSound = Gdx.audio.newSound(Gdx.files.internal("sfx/FruitSlicerWhooshSound.mp3"));
this.sliceSquishSound = Gdx.audio.newSound(Gdx.files.internal("sfx/FruitSlicerSquishSound.mp3"));
this.fruitTextures = new ArrayList<>();
this.emittedFruits = new ArrayList<>();
// Creates the bitmapfont
font = new BitmapFont();
font.setColor(Color.WHITE);
font.getData().setScale(Gdx.graphics.getWidth()/ GameWare.WIDTH*2);
for(int textureNum = 1; textureNum <= 20; textureNum++){
String filename = "FruitTexture" + String.valueOf(textureNum) + ".png";
this.fruitTextures.add(new Texture(Gdx.files.internal(filename)));
}
}
@Override
public void handleInput(){
if(Gdx.input.justTouched()) {
int touchX = Gdx.input.getX();
int touchY = Gdx.input.getY();
boolean didCut = false;
for(FruitSprite fruit : this.emittedFruits){
if(fruit.isPressed(touchX, touchY)){
this.totalFruitsCut++;
didCut = true;
}
}
if(didCut){
this.sliceWhooshSound.play();
this.sliceSquishSound.play(0.15f);
}
super.setScore(this.totalFruitsCut);
}
}
@Override
public void update(float dt){
// Effectively updates the pause button and the loading text
super.update(dt);
this.handleInput();
this.currentDuration += dt;
this.timeSinceLastEmit += dt;
if(this.currentDuration > this.totalDuration){
super.setGameFinished();
}
// Increases the emiting frequency towards the endingEmitFrequency as the game gets closer to the end
float currentFrequency = (float) (this.startingEmitFrequency - (this.startingEmitFrequency - this.endingEmitFrequency) * Math.min(this.currentDuration / (this.totalDuration * 0.6), 1));
// Emits a new fruit
if(this.timeSinceLastEmit > currentFrequency){
this.emitNewFruit();
this.timeSinceLastEmit = 0;
}
for(FruitSprite fruit : this.emittedFruits){
fruit.update(dt);
}
// Removes the oldest fruit if it is disposable
if(this.emittedFruits.size() > 0 && this.emittedFruits.get(0).isDisposable()){
this.emittedFruits.get(0).dispose();
this.emittedFruits.remove(this.emittedFruits.get(0));
}
}
@Override
public void render(SpriteBatch sb){
sb.begin();
// Background
sb.draw(this.background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
sb.end();
// Fruits
for(FruitSprite fruit : this.emittedFruits){
fruit.draw(sb);
}
sb.begin();
// Time left
this.font.draw(sb, String.valueOf(Math.max(Math.round((this.totalDuration - this.currentDuration) * 100), 0.00) / 100.0), Gdx.graphics.getWidth()/40,Gdx.graphics.getHeight() - Gdx.graphics.getHeight()/40);
sb.end();
//Effectively renders the pause button and the loading text
super.render(sb);
}
@Override
public void dispose(){
super.dispose();
this.background.dispose();
this.font.dispose();
this.sliceWhooshSound.dispose();
this.sliceSquishSound.dispose();
for(Texture fruit : this.fruitTextures){
fruit.dispose();
}
}
public void emitNewFruit() {
// Four different emit modes: from left, from right, from entire bottom, and from bottom center with different velocity angles
int emitMode = (int) (Math.random() * 4);
FruitSprite fruitSprite;
Texture fruitTexture = this.fruitTextures.get((int) (Math.random() * 20));
Vector3 velocity = new Vector3(Gdx.graphics.getWidth() * 3 / 4, 0, 0);
int x, y, emitAngle, rotationSpeed;
float fruitAspectRatio = Float.valueOf(fruitTexture.getWidth()) / Float.valueOf(fruitTexture.getHeight());
int fruitWidth = Gdx.graphics.getWidth() / 5;
int fruitHeight = (int) (fruitWidth / fruitAspectRatio);
// Emit from left
if (emitMode == 0){
x = -fruitWidth * 2;
y = (int) (Math.random() * Gdx.graphics.getHeight() / 3);
emitAngle = (int) (15 + Math.random() * 60);
velocity.rotate(emitAngle, 0, 0, 1);
fruitSprite = new FruitSprite(x, y, fruitWidth, fruitHeight, velocity, fruitTexture);
this.emittedFruits.add(fruitSprite);
}
// Emit from right
else if(emitMode == 1) {
x = Gdx.graphics.getWidth() + fruitWidth * 2;
y = (int) (Math.random() * Gdx.graphics.getHeight() / 3);
emitAngle = (int) (180 - (15 + Math.random() * 60));
velocity.rotate(emitAngle, 0, 0, 1);
fruitSprite = new FruitSprite(x, y, fruitWidth, fruitHeight, velocity, fruitTexture);
this.emittedFruits.add(fruitSprite);
}
// Emit from entire bottom part of the screen
else if(emitMode == 2){
int xWidth = Gdx.graphics.getWidth() + fruitWidth * 2;
x = (int)(xWidth*Math.random());
y = -fruitHeight*2;
float emitAngleOffset = 30 - 30 * (Float.valueOf(x) / Float.valueOf(xWidth));
emitAngle = (int) (105 - emitAngleOffset);
velocity.x = (int) (velocity.x * (1.1 + 0.5 * (15 - Math.abs(90 - Float.valueOf(emitAngle)))/15));
velocity.rotate(emitAngle, 0, 0, 1);
fruitSprite = new FruitSprite(x - fruitWidth, y, fruitWidth, fruitHeight, velocity, fruitTexture);
this.emittedFruits.add(fruitSprite);
}
// Emit from bottom center, with random emit angles
else if(emitMode == 3){
x = Gdx.graphics.getWidth()/2 + fruitWidth/2;
y = - fruitHeight*2;
emitAngle = (int) (100 - Math.random()*20);
velocity.x = (int) (velocity.x * 1.4);
velocity.rotate(emitAngle, 0, 0, 1);
fruitSprite = new FruitSprite(x - fruitWidth, y, fruitWidth, fruitHeight, velocity, fruitTexture);
this.emittedFruits.add(fruitSprite);
}
}
@Override
public void reset(){
this.currentDuration = 0f;
this.timeSinceLastEmit = 0f;
this.totalFruitsCut = 0;
this.emittedFruits = new ArrayList<>();
}
}
......@@ -18,7 +18,7 @@ public class MenuState extends State{
private final Label subHeadLabel = new Label("Welcome "+ GameWare.getInstance().getPlayer().getName()+"!", skin, "big");
// Button texts
private final String singlePlayerBtnText = "Single player";
private final String singlePlayerBtnText = "Single-Player";
private final String multiPlayerBtnText = "Multiplayer";
private final String highScoreBtnText = "High Scores";
private final String optionBtnText = "Options";
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment