Refactor effects to use the Factory pattern (#43)
This shows several advantages: - No need for several switchs with hardcoded names. - Easier and better control per theme (name, price…). - Easier to keep track of available effects and their order.
This commit is contained in:
parent
3429eda94c
commit
d7db9b8f82
19 changed files with 694 additions and 516 deletions
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
1010! Klooni, a free customizable puzzle game for Android and Desktop
|
||||
Copyright (C) 2017 Lonami Exo | LonamiWebs
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package io.github.lonamiwebs.klooni;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.audio.Sound;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import io.github.lonamiwebs.klooni.effects.EvaporateEffect;
|
||||
import io.github.lonamiwebs.klooni.effects.ExplodeEffect;
|
||||
import io.github.lonamiwebs.klooni.effects.IEffect;
|
||||
import io.github.lonamiwebs.klooni.effects.SpinEffect;
|
||||
import io.github.lonamiwebs.klooni.effects.VanishEffect;
|
||||
import io.github.lonamiwebs.klooni.effects.WaterdropEffect;
|
||||
import io.github.lonamiwebs.klooni.game.Cell;
|
||||
|
||||
public class Effect {
|
||||
|
||||
//region Members
|
||||
|
||||
private final int effectId;
|
||||
private final Sound effectSound;
|
||||
public final String name;
|
||||
public final int price;
|
||||
|
||||
//endregion
|
||||
|
||||
//region Constructor
|
||||
|
||||
// This method will load the sound "sound/effect_{effectName}.mp3"
|
||||
public Effect(final String effectName) {
|
||||
this(effectName, effectNameToInt(effectName));
|
||||
}
|
||||
|
||||
public Effect(final String effectName, final int id) {
|
||||
name = effectName;
|
||||
effectId = id;
|
||||
|
||||
FileHandle soundFile = Gdx.files.internal("sound/effect_" + name + ".mp3");
|
||||
if (!soundFile.exists())
|
||||
soundFile = Gdx.files.internal("sound/effect_vanish.mp3");
|
||||
|
||||
effectSound = Gdx.audio.newSound(soundFile);
|
||||
price = effectId == 0 ? 0 : 200; // TODO For now they're all 200 coins except the first
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
//region Public methods
|
||||
|
||||
public void playSound() {
|
||||
effectSound.play(MathUtils.random(0.7f, 1f), MathUtils.random(0.8f, 1.2f), 0);
|
||||
}
|
||||
|
||||
public String getDisplay() {
|
||||
// TODO For now, uppercase the first letter
|
||||
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
//region Static methods
|
||||
|
||||
public static Effect[] getEffects() {
|
||||
int id = 0;
|
||||
return new Effect[] {
|
||||
new Effect("vanish", id++),
|
||||
new Effect("waterdrop", id++),
|
||||
new Effect("evaporate", id++),
|
||||
new Effect("spin", id++),
|
||||
new Effect("explode", id++)
|
||||
};
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
//region Name <-> ID <-> IEffect
|
||||
|
||||
// Effects used when clearing a row
|
||||
public IEffect create(final Cell deadCell, final Vector2 culprit) {
|
||||
final IEffect effect;
|
||||
switch (effectId) {
|
||||
default:
|
||||
case 0:
|
||||
effect = new VanishEffect();
|
||||
break;
|
||||
case 1:
|
||||
effect = new WaterdropEffect();
|
||||
break;
|
||||
case 2:
|
||||
effect = new EvaporateEffect();
|
||||
break;
|
||||
case 3:
|
||||
effect = new SpinEffect();
|
||||
break;
|
||||
case 4:
|
||||
effect = new ExplodeEffect();
|
||||
break;
|
||||
}
|
||||
effect.setInfo(deadCell, culprit);
|
||||
return effect;
|
||||
}
|
||||
|
||||
private static int effectNameToInt(final String name) {
|
||||
// String comparision is more expensive compared to a single integer one,
|
||||
// and when creating instances of a lot of effects it's better if we can
|
||||
// save some processor cycles.
|
||||
if (name.equals("vanish")) return 0;
|
||||
if (name.equals("waterdrop")) return 1;
|
||||
if (name.equals("evaporate")) return 2;
|
||||
if (name.equals("spin")) return 3;
|
||||
if (name.equals("explode")) return 4;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
//region Disposal
|
||||
|
||||
void dispose() {
|
||||
effectSound.dispose();
|
||||
}
|
||||
|
||||
//endregion
|
||||
}
|
|
@ -22,18 +22,59 @@ import com.badlogic.gdx.Game;
|
|||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Preferences;
|
||||
import com.badlogic.gdx.Screen;
|
||||
import com.badlogic.gdx.audio.Sound;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.github.lonamiwebs.klooni.effects.EvaporateEffectFactory;
|
||||
import io.github.lonamiwebs.klooni.effects.ExplodeEffectFactory;
|
||||
import io.github.lonamiwebs.klooni.effects.SpinEffectFactory;
|
||||
import io.github.lonamiwebs.klooni.effects.VanishEffectFatory;
|
||||
import io.github.lonamiwebs.klooni.effects.WaterdropEffectFactory;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffectFactory;
|
||||
import io.github.lonamiwebs.klooni.screens.MainMenuScreen;
|
||||
import io.github.lonamiwebs.klooni.screens.TransitionScreen;
|
||||
|
||||
public class Klooni extends Game {
|
||||
// region Effects
|
||||
|
||||
// ordered list of effects. index 0 will get default if VanishEffectFactory is removed from list
|
||||
public final static IEffectFactory[] EFFECTS = {
|
||||
new VanishEffectFatory(),
|
||||
new WaterdropEffectFactory(),
|
||||
new EvaporateEffectFactory(),
|
||||
new SpinEffectFactory(),
|
||||
new ExplodeEffectFactory(),
|
||||
};
|
||||
|
||||
|
||||
private Map<String, Sound> effectSounds;
|
||||
|
||||
private void loadEffectSound(final String effectName) {
|
||||
FileHandle soundFile = Gdx.files.internal("sound/effect_" + effectName + ".mp3");
|
||||
if (!soundFile.exists())
|
||||
soundFile = Gdx.files.internal("sound/effect_vanish.mp3");
|
||||
|
||||
effectSounds.put(effectName, Gdx.audio.newSound(soundFile));
|
||||
}
|
||||
|
||||
public void playEffectSound() {
|
||||
effectSounds.get(effect.getName())
|
||||
.play(MathUtils.random(0.7f, 1f), MathUtils.random(0.8f, 1.2f), 0);
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
//region Members
|
||||
|
||||
// TODO Not sure whether the theme should be static or not since it might load textures
|
||||
// FIXME theme should NOT be static as it might load textures which will expose it to the race condition iff GDX got initialized before or not
|
||||
public static Theme theme;
|
||||
public Effect effect;
|
||||
public IEffectFactory effect;
|
||||
|
||||
|
||||
public Skin skin;
|
||||
|
||||
|
@ -74,7 +115,15 @@ public class Klooni extends Game {
|
|||
|
||||
Gdx.input.setCatchBackKey(true); // To show the pause menu
|
||||
setScreen(new MainMenuScreen(this));
|
||||
effect = new Effect(prefs.getString("effectName", "vanish"));
|
||||
String effectName = prefs.getString("effectName", "vanish");
|
||||
effectSounds = new HashMap<String, Sound>(EFFECTS.length);
|
||||
effect = EFFECTS[0];
|
||||
for (IEffectFactory e : EFFECTS) {
|
||||
loadEffectSound(e.getName());
|
||||
if (e.getName().equals(effectName)) {
|
||||
effect = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
@ -99,7 +148,12 @@ public class Klooni extends Game {
|
|||
super.dispose();
|
||||
skin.dispose();
|
||||
theme.dispose();
|
||||
effect.dispose();
|
||||
if (effectSounds != null) {
|
||||
for (Sound s : effectSounds.values()) {
|
||||
s.dispose();
|
||||
}
|
||||
effectSounds = null;
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
@ -183,40 +237,40 @@ public class Klooni extends Game {
|
|||
}
|
||||
|
||||
// Effects related
|
||||
public static boolean isEffectBought(Effect effect) {
|
||||
if (effect.price == 0)
|
||||
public static boolean isEffectBought(IEffectFactory effect) {
|
||||
if (effect.getPrice() == 0)
|
||||
return true;
|
||||
|
||||
String[] effects = prefs.getString("boughtEffects", "").split(":");
|
||||
for (String e : effects)
|
||||
if (e.equals(effect.name))
|
||||
if (e.equals(effect.getName()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean buyEffect(Effect effect) {
|
||||
public static boolean buyEffect(IEffectFactory effect) {
|
||||
final float money = getRealMoney();
|
||||
if (effect.price > money)
|
||||
if (effect.getPrice() > money)
|
||||
return false;
|
||||
|
||||
setMoney(money - effect.price);
|
||||
setMoney(money - effect.getPrice());
|
||||
|
||||
String bought = prefs.getString("boughtEffects", "");
|
||||
if (bought.equals(""))
|
||||
bought = effect.name;
|
||||
bought = effect.getName();
|
||||
else
|
||||
bought += ":" + effect.name;
|
||||
bought += ":" + effect.getName();
|
||||
|
||||
prefs.putString("boughtEffects", bought);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void updateEffect(Effect newEffect) {
|
||||
prefs.putString("effectName", newEffect.name).flush();
|
||||
public void updateEffect(IEffectFactory newEffect) {
|
||||
prefs.putString("effectName", newEffect.getName()).flush();
|
||||
// Create a new effect, since the one passed through the parameter may dispose later
|
||||
effect = new Effect(newEffect.name);
|
||||
effect = newEffect;
|
||||
}
|
||||
|
||||
// Money related
|
||||
|
|
|
@ -33,6 +33,7 @@ public class SkinLoader {
|
|||
|
||||
private final static float bestMultiplier;
|
||||
|
||||
// FIXME this static code is exposed to a race condition and will fail if called class gets loaded before execution of Klooni.create
|
||||
static {
|
||||
// Use the height to determine the best match
|
||||
// We cannot use a size which is over the device height,
|
||||
|
|
|
@ -21,19 +21,19 @@ import com.badlogic.gdx.graphics.Texture;
|
|||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
|
||||
import io.github.lonamiwebs.klooni.Effect;
|
||||
import io.github.lonamiwebs.klooni.Klooni;
|
||||
import io.github.lonamiwebs.klooni.Theme;
|
||||
import io.github.lonamiwebs.klooni.game.Board;
|
||||
import io.github.lonamiwebs.klooni.game.GameLayout;
|
||||
import io.github.lonamiwebs.klooni.game.Piece;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffectFactory;
|
||||
|
||||
// Card-like actor used to display information about a given theme
|
||||
public class EffectCard extends ShopCard {
|
||||
|
||||
//region Members
|
||||
|
||||
private final Effect effect;
|
||||
private final IEffectFactory effect;
|
||||
private final Board board;
|
||||
|
||||
// We want to create an effect from the beginning
|
||||
|
@ -45,7 +45,7 @@ public class EffectCard extends ShopCard {
|
|||
|
||||
//region Constructor
|
||||
|
||||
public EffectCard(final Klooni game, final GameLayout layout, final Effect effect) {
|
||||
public EffectCard(final Klooni game, final GameLayout layout, final IEffectFactory effect) {
|
||||
super(game, layout, effect.getDisplay(), Klooni.theme.background);
|
||||
background = Theme.getBlankTexture();
|
||||
this.effect = effect;
|
||||
|
@ -118,12 +118,12 @@ public class EffectCard extends ShopCard {
|
|||
|
||||
@Override
|
||||
public void usedItemUpdated() {
|
||||
if (game.effect.name.equals(effect.name))
|
||||
if (game.effect.getName().equals(effect.getName()))
|
||||
priceLabel.setText("currently used");
|
||||
else if (Klooni.isEffectBought(effect))
|
||||
priceLabel.setText("bought");
|
||||
else
|
||||
priceLabel.setText("buy for "+effect.price);
|
||||
priceLabel.setText("buy for "+effect.getPrice());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -139,12 +139,12 @@ public class EffectCard extends ShopCard {
|
|||
|
||||
@Override
|
||||
public boolean isUsed() {
|
||||
return game.effect.name.equals(effect.name);
|
||||
return game.effect.getName().equals(effect.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPrice() {
|
||||
return effect.price;
|
||||
return effect.getPrice();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
package io.github.lonamiwebs.klooni.effects;
|
||||
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.math.Interpolation;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import io.github.lonamiwebs.klooni.game.Cell;
|
||||
|
||||
public class EvaporateEffect implements IEffect {
|
||||
private Vector2 pos;
|
||||
private float originalX;
|
||||
|
||||
private float size;
|
||||
|
||||
private Color vanishColor;
|
||||
private float vanishSize;
|
||||
private float vanishElapsed;
|
||||
private float driftMagnitude;
|
||||
private float randomOffset;
|
||||
|
||||
private static final float UP_SPEED = 100.0f;
|
||||
private static final float LIFETIME = 3.0f;
|
||||
private static final float INV_LIFETIME = 1.0f / 3.0f;
|
||||
|
||||
public EvaporateEffect() {
|
||||
vanishElapsed = Float.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInfo(Cell deadCell, Vector2 culprit) {
|
||||
pos = deadCell.pos.cpy();
|
||||
originalX = pos.x;
|
||||
size = deadCell.size;
|
||||
|
||||
vanishSize = deadCell.size;
|
||||
vanishColor = deadCell.getColorCopy();
|
||||
driftMagnitude = Gdx.graphics.getWidth() * 0.05f;
|
||||
vanishElapsed = 0;
|
||||
randomOffset = MathUtils.random(MathUtils.PI2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch) {
|
||||
vanishElapsed += Gdx.graphics.getDeltaTime();
|
||||
|
||||
// Update the size as we fade away
|
||||
final float progress = vanishElapsed * INV_LIFETIME;
|
||||
vanishSize = Interpolation.fade.apply(size, 0, progress);
|
||||
|
||||
// Fade away depending on the time
|
||||
vanishColor.set(vanishColor.r, vanishColor.g, vanishColor.b, 1.0f - progress);
|
||||
|
||||
// Ghostly fade upwards, by doing a lerp from our current position to the wavy one
|
||||
pos.x = MathUtils.lerp(
|
||||
pos.x,
|
||||
originalX + MathUtils.sin(randomOffset + vanishElapsed * 3f) * driftMagnitude,
|
||||
0.3f
|
||||
);
|
||||
pos.y += UP_SPEED * Gdx.graphics.getDeltaTime();
|
||||
|
||||
Cell.draw(vanishColor, batch, pos.x, pos.y, vanishSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return vanishElapsed > LIFETIME;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
1010! Klooni, a free customizable puzzle game for Android and Desktop
|
||||
Copyright (C) 2017 Lonami Exo | LonamiWebs
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package io.github.lonamiwebs.klooni.effects;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.math.Interpolation;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import io.github.lonamiwebs.klooni.game.Cell;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffect;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffectFactory;
|
||||
|
||||
|
||||
public class EvaporateEffectFactory implements IEffectFactory {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "evaporate";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplay() {
|
||||
return "Evaporate";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrice() {
|
||||
return 200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IEffect create(Cell deadCell, Vector2 culprit) {
|
||||
IEffect effect = new EvaporateEffect();
|
||||
effect.setInfo(deadCell, culprit);
|
||||
return effect;
|
||||
}
|
||||
|
||||
|
||||
private class EvaporateEffect implements IEffect {
|
||||
private Vector2 pos;
|
||||
private float originalX;
|
||||
|
||||
private float size;
|
||||
|
||||
private Color vanishColor;
|
||||
private float vanishSize;
|
||||
private float vanishElapsed;
|
||||
private float driftMagnitude;
|
||||
private float randomOffset;
|
||||
|
||||
private static final float UP_SPEED = 100.0f;
|
||||
private static final float LIFETIME = 3.0f;
|
||||
private static final float INV_LIFETIME = 1.0f / 3.0f;
|
||||
|
||||
EvaporateEffect() {
|
||||
vanishElapsed = Float.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInfo(Cell deadCell, Vector2 culprit) {
|
||||
pos = deadCell.pos.cpy();
|
||||
originalX = pos.x;
|
||||
size = deadCell.size;
|
||||
|
||||
vanishSize = deadCell.size;
|
||||
vanishColor = deadCell.getColorCopy();
|
||||
driftMagnitude = Gdx.graphics.getWidth() * 0.05f;
|
||||
vanishElapsed = 0;
|
||||
randomOffset = MathUtils.random(MathUtils.PI2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch) {
|
||||
vanishElapsed += Gdx.graphics.getDeltaTime();
|
||||
|
||||
// Update the size as we fade away
|
||||
final float progress = vanishElapsed * INV_LIFETIME;
|
||||
vanishSize = Interpolation.fade.apply(size, 0, progress);
|
||||
|
||||
// Fade away depending on the time
|
||||
vanishColor.set(vanishColor.r, vanishColor.g, vanishColor.b, 1.0f - progress);
|
||||
|
||||
// Ghostly fade upwards, by doing a lerp from our current position to the wavy one
|
||||
pos.x = MathUtils.lerp(
|
||||
pos.x,
|
||||
originalX + MathUtils.sin(randomOffset + vanishElapsed * 3f) * driftMagnitude,
|
||||
0.3f
|
||||
);
|
||||
pos.y += UP_SPEED * Gdx.graphics.getDeltaTime();
|
||||
|
||||
Cell.draw(vanishColor, batch, pos.x, pos.y, vanishSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return vanishElapsed > LIFETIME;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
package io.github.lonamiwebs.klooni.effects;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
|
||||
import io.github.lonamiwebs.klooni.game.Cell;
|
||||
|
||||
public class ExplodeEffect implements IEffect {
|
||||
private Color color;
|
||||
boolean dead;
|
||||
|
||||
private final static float EXPLOSION_X_RANGE = 0.25f;
|
||||
private final static float EXPLOSION_Y_RANGE = 0.30f;
|
||||
private final static float GRAVITY_PERCENTAGE = -0.60f;
|
||||
|
||||
class Shard {
|
||||
final Vector2 pos, vel, acc;
|
||||
final float size;
|
||||
|
||||
public Shard(final Vector2 pos, final float size) {
|
||||
final float xRange = Gdx.graphics.getWidth() * EXPLOSION_X_RANGE;
|
||||
final float yRange = Gdx.graphics.getHeight() * EXPLOSION_Y_RANGE;
|
||||
vel = new Vector2(MathUtils.random(-xRange, +xRange), MathUtils.random(-yRange * 0.2f, +yRange));
|
||||
acc = new Vector2(0f, Gdx.graphics.getHeight() * GRAVITY_PERCENTAGE);
|
||||
|
||||
this.size = size * MathUtils.random(0.40f, 0.60f);
|
||||
this.pos = pos.cpy().add(this.size * 0.5f, this.size * 0.5f);
|
||||
}
|
||||
|
||||
public void draw(final Batch batch, final float dt) {
|
||||
vel.add(acc.x * dt, acc.y * dt).scl(0.99f);
|
||||
pos.add(vel.x * dt, vel.y * dt);
|
||||
Cell.draw(color, batch, pos.x, pos.y, size);
|
||||
}
|
||||
}
|
||||
|
||||
private Shard[] shards;
|
||||
|
||||
@Override
|
||||
public void setInfo(Cell deadCell, Vector2 culprit) {
|
||||
color = deadCell.getColorCopy();
|
||||
|
||||
shards = new Shard[MathUtils.random(4, 6)];
|
||||
for (int i = 0; i != shards.length; ++i)
|
||||
shards[i] = new Shard(deadCell.pos, deadCell.size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch) {
|
||||
dead = true; // assume we're death
|
||||
final Vector3 translation = batch.getTransformMatrix().getTranslation(new Vector3());
|
||||
for (int i = shards.length; i-- != 0; ) {
|
||||
shards[i].draw(batch, Gdx.graphics.getDeltaTime());
|
||||
dead &= translation.y + shards[i].pos.y + shards[i].size < 0; // all must be dead
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return dead;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
1010! Klooni, a free customizable puzzle game for Android and Desktop
|
||||
Copyright (C) 2017 Lonami Exo | LonamiWebs
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package io.github.lonamiwebs.klooni.effects;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
|
||||
import io.github.lonamiwebs.klooni.game.Cell;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffect;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffectFactory;
|
||||
|
||||
|
||||
public class ExplodeEffectFactory implements IEffectFactory {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "explode";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplay() {
|
||||
return "Explode";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrice() {
|
||||
return 200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IEffect create(Cell deadCell, Vector2 culprit) {
|
||||
IEffect effect = new ExplodeEffect();
|
||||
effect.setInfo(deadCell, culprit);
|
||||
return effect;
|
||||
}
|
||||
|
||||
|
||||
private class ExplodeEffect implements IEffect {
|
||||
private Color color;
|
||||
boolean dead;
|
||||
|
||||
private final static float EXPLOSION_X_RANGE = 0.25f;
|
||||
private final static float EXPLOSION_Y_RANGE = 0.30f;
|
||||
private final static float GRAVITY_PERCENTAGE = -0.60f;
|
||||
|
||||
private class Shard {
|
||||
final Vector2 pos, vel, acc;
|
||||
final float size;
|
||||
|
||||
Shard(final Vector2 pos, final float size) {
|
||||
final float xRange = Gdx.graphics.getWidth() * EXPLOSION_X_RANGE;
|
||||
final float yRange = Gdx.graphics.getHeight() * EXPLOSION_Y_RANGE;
|
||||
vel = new Vector2(MathUtils.random(-xRange, +xRange), MathUtils.random(-yRange * 0.2f, +yRange));
|
||||
acc = new Vector2(0f, Gdx.graphics.getHeight() * GRAVITY_PERCENTAGE);
|
||||
|
||||
this.size = size * MathUtils.random(0.40f, 0.60f);
|
||||
this.pos = pos.cpy().add(this.size * 0.5f, this.size * 0.5f);
|
||||
}
|
||||
|
||||
public void draw(final Batch batch, final float dt) {
|
||||
vel.add(acc.x * dt, acc.y * dt).scl(0.99f);
|
||||
pos.add(vel.x * dt, vel.y * dt);
|
||||
Cell.draw(color, batch, pos.x, pos.y, size);
|
||||
}
|
||||
}
|
||||
|
||||
private Shard[] shards;
|
||||
|
||||
@Override
|
||||
public void setInfo(Cell deadCell, Vector2 culprit) {
|
||||
color = deadCell.getColorCopy();
|
||||
|
||||
shards = new Shard[MathUtils.random(4, 6)];
|
||||
for (int i = 0; i != shards.length; ++i)
|
||||
shards[i] = new Shard(deadCell.pos, deadCell.size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch) {
|
||||
dead = true; // assume we're death
|
||||
final Vector3 translation = batch.getTransformMatrix().getTranslation(new Vector3());
|
||||
for (int i = shards.length; i-- != 0; ) {
|
||||
shards[i].draw(batch, Gdx.graphics.getDeltaTime());
|
||||
dead &= translation.y + shards[i].pos.y + shards[i].size < 0; // all must be dead
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return dead;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package io.github.lonamiwebs.klooni.effects;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.math.Interpolation;
|
||||
import com.badlogic.gdx.math.Matrix4;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import io.github.lonamiwebs.klooni.game.Cell;
|
||||
|
||||
public class SpinEffect implements IEffect {
|
||||
private float age;
|
||||
private Vector2 pos;
|
||||
private float size;
|
||||
private Color color;
|
||||
|
||||
private static final float LIFETIME = 2.0f;
|
||||
private static final float INV_LIFETIME = 1.0f / LIFETIME;
|
||||
|
||||
private static final float TOTAL_ROTATION = 600;
|
||||
|
||||
@Override
|
||||
public void setInfo(Cell deadCell, Vector2 culprit) {
|
||||
age = 0;
|
||||
pos = deadCell.pos.cpy();
|
||||
size = deadCell.size;
|
||||
color = deadCell.getColorCopy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch) {
|
||||
age += Gdx.graphics.getDeltaTime();
|
||||
|
||||
final float progress = age * INV_LIFETIME;
|
||||
final float currentSize = Interpolation.pow2In.apply(size, 0, progress);
|
||||
final float currentRotation = Interpolation.sine.apply(0, TOTAL_ROTATION, progress);
|
||||
|
||||
final Matrix4 original = batch.getTransformMatrix().cpy();
|
||||
final Matrix4 rotated = batch.getTransformMatrix();
|
||||
|
||||
final float disp =
|
||||
+ 0.5f * (size - currentSize) // the smaller, the more we need to "push" to center
|
||||
+ currentSize * 0.5f; // center the cell for rotation
|
||||
|
||||
rotated.translate(pos.x + disp, pos.y + disp, 0);
|
||||
rotated.rotate(0, 0, 1, currentRotation);
|
||||
rotated.translate(currentSize * -0.5f, currentSize * -0.5f, 0); // revert centering for rotation
|
||||
|
||||
batch.setTransformMatrix(rotated);
|
||||
Cell.draw(color, batch, 0, 0, currentSize);
|
||||
batch.setTransformMatrix(original);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return age > LIFETIME;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
1010! Klooni, a free customizable puzzle game for Android and Desktop
|
||||
Copyright (C) 2017 Lonami Exo | LonamiWebs
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package io.github.lonamiwebs.klooni.effects;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.math.Interpolation;
|
||||
import com.badlogic.gdx.math.Matrix4;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import io.github.lonamiwebs.klooni.game.Cell;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffect;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffectFactory;
|
||||
|
||||
|
||||
public class SpinEffectFactory implements IEffectFactory {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "spin";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplay() {
|
||||
return "Spin";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrice() {
|
||||
return 200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IEffect create(Cell deadCell, Vector2 culprit) {
|
||||
IEffect effect = new SpinEffect();
|
||||
effect.setInfo(deadCell, culprit);
|
||||
return effect;
|
||||
}
|
||||
|
||||
|
||||
private class SpinEffect implements IEffect {
|
||||
private float age;
|
||||
private Vector2 pos;
|
||||
private float size;
|
||||
private Color color;
|
||||
|
||||
private static final float LIFETIME = 2.0f;
|
||||
private static final float INV_LIFETIME = 1.0f / LIFETIME;
|
||||
|
||||
private static final float TOTAL_ROTATION = 600;
|
||||
|
||||
@Override
|
||||
public void setInfo(Cell deadCell, Vector2 culprit) {
|
||||
age = 0;
|
||||
pos = deadCell.pos.cpy();
|
||||
size = deadCell.size;
|
||||
color = deadCell.getColorCopy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch) {
|
||||
age += Gdx.graphics.getDeltaTime();
|
||||
|
||||
final float progress = age * INV_LIFETIME;
|
||||
final float currentSize = Interpolation.pow2In.apply(size, 0, progress);
|
||||
final float currentRotation = Interpolation.sine.apply(0, TOTAL_ROTATION, progress);
|
||||
|
||||
final Matrix4 original = batch.getTransformMatrix().cpy();
|
||||
final Matrix4 rotated = batch.getTransformMatrix();
|
||||
|
||||
final float disp =
|
||||
+0.5f * (size - currentSize) // the smaller, the more we need to "push" to center
|
||||
+ currentSize * 0.5f; // center the cell for rotation
|
||||
|
||||
rotated.translate(pos.x + disp, pos.y + disp, 0);
|
||||
rotated.rotate(0, 0, 1, currentRotation);
|
||||
rotated.translate(currentSize * -0.5f, currentSize * -0.5f, 0); // revert centering for rotation
|
||||
|
||||
batch.setTransformMatrix(rotated);
|
||||
Cell.draw(color, batch, 0, 0, currentSize);
|
||||
batch.setTransformMatrix(original);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return age > LIFETIME;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
package io.github.lonamiwebs.klooni.effects;
|
||||
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.math.Interpolation;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import io.github.lonamiwebs.klooni.game.Cell;
|
||||
|
||||
public class VanishEffect implements IEffect {
|
||||
private Cell cell;
|
||||
|
||||
private Color vanishColor;
|
||||
private float vanishSize;
|
||||
private float vanishElapsed;
|
||||
private float vanishLifetime;
|
||||
|
||||
private final static float MINIMUM_SIZE = 0.3f;
|
||||
|
||||
public VanishEffect() {
|
||||
vanishElapsed = Float.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInfo(Cell deadCell, Vector2 culprit) {
|
||||
cell = deadCell;
|
||||
|
||||
vanishSize = cell.size;
|
||||
vanishColor = cell.getColorCopy();
|
||||
vanishLifetime = 1f;
|
||||
|
||||
// The vanish distance is this measure (distance² + size³ * 20% size)
|
||||
// because it seems good enough. The more the distance, the more the
|
||||
// delay, but we decrease the delay depending on the cell size too or
|
||||
// it would be way too high
|
||||
Vector2 center = new Vector2(cell.pos.x + cell.size * 0.5f, cell.pos.y + 0.5f);
|
||||
float vanishDist = Vector2.dst2(
|
||||
culprit.x, culprit.y, center.x, center.y) / ((float)Math.pow(cell.size, 4.0f) * 0.2f);
|
||||
|
||||
// Negative time = delay, + 0.4*lifetime because elastic interpolation has that delay
|
||||
vanishElapsed = vanishLifetime * 0.4f - vanishDist;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch) {
|
||||
vanishElapsed += Gdx.graphics.getDeltaTime();
|
||||
|
||||
// vanishElapsed might be < 0 (delay), so clamp to 0
|
||||
float progress = Math.min(1f,
|
||||
Math.max(vanishElapsed, 0f) / vanishLifetime);
|
||||
|
||||
// If one were to plot the elasticIn function, they would see that the slope increases
|
||||
// a lot towards the end- a linear interpolation between the last size + the desired
|
||||
// size at 20% seems to look a lot better.
|
||||
vanishSize = MathUtils.lerp(
|
||||
vanishSize,
|
||||
Interpolation.elasticIn.apply(cell.size, 0, progress),
|
||||
0.2f
|
||||
);
|
||||
|
||||
float centerOffset = cell.size * 0.5f - vanishSize * 0.5f;
|
||||
Cell.draw(vanishColor, batch, cell.pos.x + centerOffset, cell.pos.y + centerOffset, vanishSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return vanishSize < MINIMUM_SIZE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
1010! Klooni, a free customizable puzzle game for Android and Desktop
|
||||
Copyright (C) 2017 Lonami Exo | LonamiWebs
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package io.github.lonamiwebs.klooni.effects;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.math.Interpolation;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import io.github.lonamiwebs.klooni.game.Cell;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffect;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffectFactory;
|
||||
|
||||
|
||||
public class VanishEffectFatory implements IEffectFactory {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "vanish";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplay() {
|
||||
return "Vanish";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrice() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IEffect create(Cell deadCell, Vector2 culprit) {
|
||||
IEffect effect = new VanishEffect();
|
||||
effect.setInfo(deadCell, culprit);
|
||||
return effect;
|
||||
}
|
||||
|
||||
|
||||
private class VanishEffect implements IEffect {
|
||||
private Cell cell;
|
||||
|
||||
private Color vanishColor;
|
||||
private float vanishSize;
|
||||
private float vanishElapsed;
|
||||
private float vanishLifetime;
|
||||
|
||||
private final static float MINIMUM_SIZE = 0.3f;
|
||||
|
||||
VanishEffect() {
|
||||
vanishElapsed = Float.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInfo(Cell deadCell, Vector2 culprit) {
|
||||
cell = deadCell;
|
||||
|
||||
vanishSize = cell.size;
|
||||
vanishColor = cell.getColorCopy();
|
||||
vanishLifetime = 1f;
|
||||
|
||||
// The vanish distance is this measure (distance² + size³ * 20% size)
|
||||
// because it seems good enough. The more the distance, the more the
|
||||
// delay, but we decrease the delay depending on the cell size too or
|
||||
// it would be way too high
|
||||
Vector2 center = new Vector2(cell.pos.x + cell.size * 0.5f, cell.pos.y + 0.5f);
|
||||
float vanishDist = Vector2.dst2(
|
||||
culprit.x, culprit.y, center.x, center.y) / ((float) Math.pow(cell.size, 4.0f) * 0.2f);
|
||||
|
||||
// Negative time = delay, + 0.4*lifetime because elastic interpolation has that delay
|
||||
vanishElapsed = vanishLifetime * 0.4f - vanishDist;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch) {
|
||||
vanishElapsed += Gdx.graphics.getDeltaTime();
|
||||
|
||||
// vanishElapsed might be < 0 (delay), so clamp to 0
|
||||
float progress = Math.min(1f,
|
||||
Math.max(vanishElapsed, 0f) / vanishLifetime);
|
||||
|
||||
// If one were to plot the elasticIn function, they would see that the slope increases
|
||||
// a lot towards the end- a linear interpolation between the last size + the desired
|
||||
// size at 20% seems to look a lot better.
|
||||
vanishSize = MathUtils.lerp(
|
||||
vanishSize,
|
||||
Interpolation.elasticIn.apply(cell.size, 0, progress),
|
||||
0.2f
|
||||
);
|
||||
|
||||
float centerOffset = cell.size * 0.5f - vanishSize * 0.5f;
|
||||
Cell.draw(vanishColor, batch, cell.pos.x + centerOffset, cell.pos.y + centerOffset, vanishSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return vanishSize < MINIMUM_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
package io.github.lonamiwebs.klooni.effects;
|
||||
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
|
||||
import io.github.lonamiwebs.klooni.SkinLoader;
|
||||
import io.github.lonamiwebs.klooni.game.Cell;
|
||||
|
||||
public class WaterdropEffect implements IEffect {
|
||||
private Vector2 pos;
|
||||
private boolean dead;
|
||||
|
||||
private Color cellColor;
|
||||
private Color dropColor;
|
||||
private float cellSize;
|
||||
|
||||
private final float fallAcceleration;
|
||||
private float fallSpeed;
|
||||
|
||||
private static final float FALL_ACCELERATION = 500.0f;
|
||||
private static final float FALL_VARIATION = 50.0f;
|
||||
private static final float COLOR_SPEED = 7.5f;
|
||||
|
||||
private final static Texture dropTexture;
|
||||
|
||||
static {
|
||||
dropTexture = SkinLoader.loadPng("cells/drop.png");
|
||||
}
|
||||
|
||||
public WaterdropEffect() {
|
||||
fallAcceleration = FALL_ACCELERATION + MathUtils.random(-FALL_VARIATION, FALL_VARIATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInfo(Cell deadCell, Vector2 culprit) {
|
||||
pos = deadCell.pos.cpy();
|
||||
cellSize = deadCell.size;
|
||||
cellColor = deadCell.getColorCopy();
|
||||
dropColor = new Color(cellColor.r, cellColor.g, cellColor.b, 0.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch) {
|
||||
final float dt = Gdx.graphics.getDeltaTime();
|
||||
fallSpeed += fallAcceleration * dt;
|
||||
pos.y -= fallSpeed * dt;
|
||||
|
||||
cellColor.set(
|
||||
cellColor.r, cellColor.g, cellColor.b,
|
||||
Math.max(cellColor.a - COLOR_SPEED * dt, 0.0f)
|
||||
);
|
||||
dropColor.set(
|
||||
cellColor.r, cellColor.g, cellColor.b,
|
||||
Math.min(dropColor.a + COLOR_SPEED * dt, 1.0f)
|
||||
);
|
||||
|
||||
Cell.draw(cellColor, batch, pos.x, pos.y, cellSize);
|
||||
Cell.draw(dropTexture, dropColor, batch, pos.x, pos.y, cellSize);
|
||||
|
||||
final Vector3 translation = batch.getTransformMatrix().getTranslation(new Vector3());
|
||||
dead = translation.y + pos.y + dropTexture.getHeight() < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return dead;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
1010! Klooni, a free customizable puzzle game for Android and Desktop
|
||||
Copyright (C) 2017 Lonami Exo | LonamiWebs
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package io.github.lonamiwebs.klooni.effects;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
|
||||
import io.github.lonamiwebs.klooni.SkinLoader;
|
||||
import io.github.lonamiwebs.klooni.game.Cell;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffect;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffectFactory;
|
||||
|
||||
|
||||
public class WaterdropEffectFactory implements IEffectFactory {
|
||||
private Texture dropTexture;
|
||||
|
||||
|
||||
private void init() {
|
||||
if(dropTexture == null)
|
||||
dropTexture = SkinLoader.loadPng("cells/drop.png");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "waterdrop";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplay() {
|
||||
return "Waterdrop";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrice() {
|
||||
return 200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IEffect create(Cell deadCell, Vector2 culprit) {
|
||||
init();
|
||||
IEffect effect = new WaterdropEffect();
|
||||
effect.setInfo(deadCell, culprit);
|
||||
return effect;
|
||||
}
|
||||
|
||||
|
||||
private class WaterdropEffect implements IEffect {
|
||||
private Vector2 pos;
|
||||
private boolean dead;
|
||||
|
||||
private Color cellColor;
|
||||
private Color dropColor;
|
||||
private float cellSize;
|
||||
|
||||
private final float fallAcceleration;
|
||||
private float fallSpeed;
|
||||
|
||||
private static final float FALL_ACCELERATION = 500.0f;
|
||||
private static final float FALL_VARIATION = 50.0f;
|
||||
private static final float COLOR_SPEED = 7.5f;
|
||||
|
||||
WaterdropEffect() {
|
||||
fallAcceleration = FALL_ACCELERATION + MathUtils.random(-FALL_VARIATION, FALL_VARIATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInfo(Cell deadCell, Vector2 culprit) {
|
||||
pos = deadCell.pos.cpy();
|
||||
cellSize = deadCell.size;
|
||||
cellColor = deadCell.getColorCopy();
|
||||
dropColor = new Color(cellColor.r, cellColor.g, cellColor.b, 0.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Batch batch) {
|
||||
final float dt = Gdx.graphics.getDeltaTime();
|
||||
fallSpeed += fallAcceleration * dt;
|
||||
pos.y -= fallSpeed * dt;
|
||||
|
||||
cellColor.set(
|
||||
cellColor.r, cellColor.g, cellColor.b,
|
||||
Math.max(cellColor.a - COLOR_SPEED * dt, 0.0f)
|
||||
);
|
||||
dropColor.set(
|
||||
cellColor.r, cellColor.g, cellColor.b,
|
||||
Math.min(dropColor.a + COLOR_SPEED * dt, 1.0f)
|
||||
);
|
||||
|
||||
Cell.draw(cellColor, batch, pos.x, pos.y, cellSize);
|
||||
Cell.draw(dropTexture, dropColor, batch, pos.x, pos.y, cellSize);
|
||||
|
||||
final Vector3 translation = batch.getTransformMatrix().getTranslation(new Vector3());
|
||||
dead = translation.y + pos.y + dropTexture.getHeight() < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return dead;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,8 +27,8 @@ import java.io.DataInputStream;
|
|||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import io.github.lonamiwebs.klooni.Effect;
|
||||
import io.github.lonamiwebs.klooni.effects.IEffect;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffect;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffectFactory;
|
||||
import io.github.lonamiwebs.klooni.serializer.BinSerializable;
|
||||
|
||||
// Represents the on screen board, with all the put cells
|
||||
|
@ -183,7 +183,7 @@ public class Board implements BinSerializable {
|
|||
//
|
||||
// If the piece is put on the top left corner, all the cells will be cleared.
|
||||
// If we first cleared the columns, then the rows wouldn't have been cleared.
|
||||
public int clearComplete(final Effect effect) {
|
||||
public int clearComplete(final IEffectFactory effect) {
|
||||
int clearCount = 0;
|
||||
boolean[] clearedRows = new boolean[cellCount];
|
||||
boolean[] clearedCols = new boolean[cellCount];
|
||||
|
@ -235,7 +235,7 @@ public class Board implements BinSerializable {
|
|||
return clearCount;
|
||||
}
|
||||
|
||||
public void clearAll(final int clearFromX, final int clearFromY, final Effect effect) {
|
||||
public void clearAll(final int clearFromX, final int clearFromY, final IEffectFactory effect) {
|
||||
final Vector2 culprit = cells[clearFromY][clearFromX].pos;
|
||||
|
||||
for (int i = 0; i < cellCount; ++i) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package io.github.lonamiwebs.klooni.effects;
|
||||
package io.github.lonamiwebs.klooni.interfaces;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.math.Vector2;
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
1010! Klooni, a free customizable puzzle game for Android and Desktop
|
||||
Copyright (C) 2017 Lonami Exo | LonamiWebs
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package io.github.lonamiwebs.klooni.interfaces;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import io.github.lonamiwebs.klooni.game.Cell;
|
||||
|
||||
/**
|
||||
* IEffectEfactory interface has to be implemented for each effect.
|
||||
*
|
||||
* It tells the name and the price of the effect and will create it, when needed.
|
||||
*
|
||||
* @see IEffect
|
||||
*/
|
||||
public interface IEffectFactory {
|
||||
public String getName();
|
||||
public String getDisplay();
|
||||
public int getPrice();
|
||||
public IEffect create(final Cell deadCell, final Vector2 culprit);
|
||||
}
|
|
@ -34,7 +34,6 @@ import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;
|
|||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||
import com.badlogic.gdx.utils.SnapshotArray;
|
||||
|
||||
import io.github.lonamiwebs.klooni.Effect;
|
||||
import io.github.lonamiwebs.klooni.Klooni;
|
||||
import io.github.lonamiwebs.klooni.Theme;
|
||||
import io.github.lonamiwebs.klooni.actors.EffectCard;
|
||||
|
@ -43,6 +42,7 @@ import io.github.lonamiwebs.klooni.actors.ShopCard;
|
|||
import io.github.lonamiwebs.klooni.actors.SoftButton;
|
||||
import io.github.lonamiwebs.klooni.actors.ThemeCard;
|
||||
import io.github.lonamiwebs.klooni.game.GameLayout;
|
||||
import io.github.lonamiwebs.klooni.interfaces.IEffectFactory;
|
||||
|
||||
// Screen where the user can customize the look and feel of the game
|
||||
class CustomizeScreen implements Screen {
|
||||
|
@ -200,7 +200,7 @@ class CustomizeScreen implements Screen {
|
|||
shopGroup.clear();
|
||||
|
||||
if (showingEffectsShop)
|
||||
for (Effect effect : Effect.getEffects())
|
||||
for (IEffectFactory effect : Klooni.EFFECTS)
|
||||
addCard(new EffectCard(game, layout, effect));
|
||||
|
||||
else // showingThemesShop
|
||||
|
|
|
@ -241,7 +241,7 @@ class GameScreen implements Screen, InputProcessor, BinSerializable {
|
|||
if (bonus > 0) {
|
||||
bonusParticleHandler.addBonus(result.pieceCenter, bonus);
|
||||
if (Klooni.soundsEnabled()) {
|
||||
game.effect.playSound();
|
||||
game.playEffectSound();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue