StationSystem.java
package com.devcharles.piazzapanic.componentsystems;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import com.badlogic.ashley.core.Engine;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.systems.IteratingSystem;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.devcharles.piazzapanic.GameScreen;
import com.devcharles.piazzapanic.components.ControllableComponent;
import com.devcharles.piazzapanic.components.FoodComponent;
import com.devcharles.piazzapanic.components.PlayerComponent;
import com.devcharles.piazzapanic.components.StationComponent;
import com.devcharles.piazzapanic.components.TintComponent;
import com.devcharles.piazzapanic.components.CookingComponent;
import com.devcharles.piazzapanic.components.FoodComponent.FoodType;
import com.devcharles.piazzapanic.input.KeyboardInput;
import com.devcharles.piazzapanic.scene2d.Hud;
import com.devcharles.piazzapanic.utility.EntityFactory;
import com.devcharles.piazzapanic.utility.Difficulty;
import com.devcharles.piazzapanic.utility.Mappers;
import com.devcharles.piazzapanic.utility.Station;
import com.devcharles.piazzapanic.utility.Station.StationType;
import com.devcharles.piazzapanic.utility.WorldTilemapRenderer;
import static com.devcharles.piazzapanic.utility.Station.StationType.oven;
/**
* This system manages player-station interaction and station food processing.
*/
public class StationSystem extends IteratingSystem {
KeyboardInput input;
boolean interactingStation = false;
EntityFactory factory;
WorldTilemapRenderer mapRenderer;
Hud hud;
private GameScreen gameScreen;
private TintComponent readyTint;
private float tickAccumulator = 0;
private final Float[] tillBalance;
private Difficulty difficulty;
public Integer timer = 15;
public StationSystem(KeyboardInput input, EntityFactory factory, WorldTilemapRenderer mapRenderer,
Float[] tillBalance, Hud hud, Difficulty difficulty, GameScreen gameScreen) {
super(Family.all(StationComponent.class).get());
this.input = input;
this.factory = factory;
this.mapRenderer = mapRenderer;
this.tillBalance = tillBalance;
this.hud = hud;
this.difficulty = difficulty;
this.gameScreen = gameScreen;
}
@Override
public void update(float deltaTime) {
tickAccumulator += deltaTime;
super.update(deltaTime);
if (tickAccumulator > 0.5f) {
tickAccumulator -= 0.5f;
}
}
@Override
protected void processEntity(Entity entity, float deltaTime) {
StationComponent station = Mappers.station.get(entity);
stationTick(station, deltaTime);
if (station.interactingCook != null) {
PlayerComponent player = Mappers.player.get(station.interactingCook);
if (player == null) {
return;
}
if (player.putDown) {
player.putDown = false;
ControllableComponent controllable = Mappers.controllable.get(station.interactingCook);
switch (station.type) {
case ingredient:
controllable.currentFood.pushItem(factory.createFood(station.ingredient),
station.interactingCook);
System.out.println(station.ingredient);
break;
case bin:
processBin(controllable);
break;
case serve:
processServe(station.interactingCook);
break;
default:
processStation(controllable, station);
break;
}
} else if (player.pickUp) {
player.pickUp = false;
ControllableComponent controllable = Mappers.controllable.get(station.interactingCook);
switch (station.type) {
case ingredient:
controllable.currentFood.pushItem(factory.createFood(station.ingredient),
station.interactingCook);
break;
case bin:
case serve:
break;
default:
stationPickup(station, controllable);
break;
}
} else if (player.interact) {
player.interact = false;
interactStation(station);
}
}
}
/**
* Try and process the food from the player.
*/
private void processStation(ControllableComponent controllable, StationComponent station) {
if (station.locked) {
tryBuy(station);
return;
}
if (controllable.currentFood.isEmpty()) {
return;
}
Gdx.app.log("putDown", Mappers.food.get(controllable.currentFood.peek()).type.name());
FoodComponent food = Mappers.food.get(controllable.currentFood.peek());
HashMap<FoodType, FoodType> recipes = Station.recipeMap.get(station.type);
if (recipes == null) {
return;
}
FoodType result = recipes.get(food.type);
if (result == null) {
return;
}
int foodIndex = station.food.indexOf(null);
// If there is space on the station
if (foodIndex != -1) {
// Pop if off player stack
// Store in station
station.food.set(foodIndex, controllable.currentFood.pop());
} else {
return;
}
// success
CookingComponent cooking = getEngine().createComponent(CookingComponent.class);
cooking.timer.start();
// Flag the food as processed if InstaCook is active
if (gameScreen.InstaCook) {
cooking.processed = true;
}
station.food.get(foodIndex).add(cooking);
Gdx.app.log("Food processed", String.format("%s turned into %s", food.type, result));
// If the station is an oven start the cooking animation.
if (station.type == oven) {
mapRenderer.animateOven(station.tileMapPosition);
}
}
/**
* Perform special action (flipping patties, etc.)
*
* @param station the station the action is being performed on.
*/
private void interactStation(StationComponent station) {
for (Entity food : station.food) {
if (food == null || !Mappers.cooking.has(food)) {
continue;
}
CookingComponent cooking = Mappers.cooking.get(food);
// Check if it's ready without ticking the timer
boolean ready = cooking.timer.tick(0);
// Make the food ready if the InstaCook powerup is active
if (gameScreen.InstaCook) {
ready = true;
return;
}
if (cooking.processed) {
food.remove(TintComponent.class);
return;
}
if (ready && !cooking.processed) {
food.remove(TintComponent.class);
cooking.processed = true;
cooking.timer.reset();
return;
}
}
}
/**
* Try to combine the ingredients at the top of the player's inventory stack
* (max 3) into a ready meal.
*
* @param cook the cook whos inventory is being used for creating the food.
*/
private void processServe(Entity cook) {
ControllableComponent controllable = Mappers.controllable.get(cook);
if (controllable.currentFood.size() < 2) {
return;
}
int count = 2;
FoodType result = tryAssemble(controllable, count);
if (result == null) {
result = tryAssemble(controllable, ++count);
if (result == null) {
return;
}
}
for (int i = 0; i < count; i++) {
Entity e = controllable.currentFood.pop();
getEngine().removeEntity(e);
}
controllable.currentFood.pushItem(factory.createFood(result), cook);
}
/**
* Attempt to create a food.
*
* @param count number of ingredients to combine
*/
private FoodType tryAssemble(ControllableComponent controllable, int count) {
Set<FoodType> ingredients = new HashSet<FoodType>();
int i = 0;
for (Entity foodEntity : controllable.currentFood) {
if (i > count - 1) {
break;
}
ingredients.add(Mappers.food.get(foodEntity).type);
i++;
}
return Station.assembleRecipes.get(ingredients);
}
/**
* Destroy the top food in the inventory of a cook.
*/
private void processBin(ControllableComponent controllable) {
if (controllable.currentFood.isEmpty()) {
return;
}
Entity e = controllable.currentFood.pop();
getEngine().removeEntity(e);
}
/**
* Pick up ready food from a station
*/
private void stationPickup(StationComponent station, ControllableComponent controllable) {
for (Entity foodEntity : station.food) {
if (foodEntity != null && !Mappers.cooking.has(foodEntity)) {
if (controllable.currentFood.pushItem(foodEntity, station.interactingCook)) {
station.food.set(station.food.indexOf(foodEntity), null);
Mappers.transform.get(foodEntity).scale.set(1, 1);
Gdx.app.log("Picked up", Mappers.food.get(foodEntity).type.toString());
}
return;
}
}
}
/**
* Cook the food in the station. This progresses the timer in the food being
* cooked in the station.
*
* @param station
* @param deltaTime
*/
private void stationTick(StationComponent station, float deltaTime) {
if (station.type == StationType.cutting_board && station.interactingCook == null) {
return;
}
for (Entity foodEntity : station.food) {
if (foodEntity == null || !Mappers.cooking.has(foodEntity)) {
continue;
}
CookingComponent cooking = Mappers.cooking.get(foodEntity);
boolean ready = cooking.timer.tick(deltaTime);
if (gameScreen.InstaCook) {
ready = true;
}
if (ready && cooking.processed) {
cooking.timer.stop();
cooking.timer.reset();
switch (station.type) {
case cutting_board:
gameScreen.audio.playChop();
break;
case grill:
gameScreen.audio.playSizzle();
break;
case oven:
gameScreen.audio.playDing();
break;
case ingredient:
gameScreen.audio.playTap();
break;
case serve:
gameScreen.audio.playTap();
break;
default:
break;
}
FoodComponent food = Mappers.food.get(foodEntity);
// Process the food into its next form
food.type = Station.recipeMap.get(station.type).get(food.type);
Mappers.texture.get(foodEntity).region = EntityFactory.getFoodTexture(food.type);
foodEntity.remove(CookingComponent.class);
Gdx.app.log("Food ready", food.type.name());
// If the station is an oven turn off the animation.
if (station.type == oven) {
mapRenderer.removeOvenAnimation(station.tileMapPosition);
}
} else if (ready) {
if (tickAccumulator > 0.5f) {
if (!Mappers.tint.has(foodEntity)) {
foodEntity.add(readyTint);
} else {
foodEntity.remove(TintComponent.class);
}
}
}
}
}
/**
* Unlocks the current station if the player is in endless mode and has enough
* money.
*
* @param station The current station component with details about the current
* station.
*/
public void tryBuy(StationComponent station) {
// TODO sound effect for success or failure.
// TODO set price for new stations.
if (difficulty == Difficulty.SCENARIO) {
hud.displayInfoMessage("You can only unlock new stations in endless mode");
return;
}
float priceOfNewStation = 5;
if (tillBalance[0] - priceOfNewStation < 0) {
hud.displayInfoMessage("Insufficient funds - Each station costs $" + priceOfNewStation);
} else {
mapRenderer.unlockStation(station.tileMapPosition, station.type.getValue());
tillBalance[0] -= priceOfNewStation;
station.locked = false;
hud.displayInfoMessage("New station unlocked!");
}
}
@Override
public void addedToEngine(Engine engine) {
super.addedToEngine(engine);
readyTint = getEngine().createComponent(TintComponent.class);
readyTint.tint = Color.ORANGE;
}
}