Create a generic ShopCard to reuse more code

This commit is contained in:
Lonami Exo 2017-07-19 14:47:47 +02:00
parent 5b25a3f6d5
commit d2325220f8
6 changed files with 193 additions and 226 deletions

View file

@ -20,9 +20,6 @@ package io.github.lonamiwebs.klooni.actors;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import io.github.lonamiwebs.klooni.Effect; import io.github.lonamiwebs.klooni.Effect;
import io.github.lonamiwebs.klooni.Klooni; import io.github.lonamiwebs.klooni.Klooni;
@ -31,49 +28,25 @@ import io.github.lonamiwebs.klooni.game.Cell;
import io.github.lonamiwebs.klooni.game.GameLayout; import io.github.lonamiwebs.klooni.game.GameLayout;
// Card-like actor used to display information about a given theme // Card-like actor used to display information about a given theme
public class EffectCard extends Actor { public class EffectCard extends ShopCard {
//region Members //region Members
private final Klooni game;
public final Effect effect; public final Effect effect;
private final Texture background; private final Texture background;
private Color color; private Color color;
private final Label nameLabel;
private final Label priceLabel;
public final Rectangle nameBounds;
public final Rectangle priceBounds;
public float cellSize;
//endregion //endregion
//region Constructor //region Constructor
public EffectCard(final Klooni game, final GameLayout layout, final Effect effect) { public EffectCard(final Klooni game, final GameLayout layout, final Effect effect) {
this.game = game; super(game, layout, effect.getDisplay(), Klooni.theme.background);
this.effect = effect;
background = Theme.getBlankTexture(); background = Theme.getBlankTexture();
Label.LabelStyle labelStyle = new Label.LabelStyle();
labelStyle.font = game.skin.getFont("font_small");
priceLabel = new Label("", labelStyle);
nameLabel = new Label(effect.getDisplay(), labelStyle);
Color labelColor = Theme.shouldUseWhite(Klooni.theme.background) ? Color.WHITE : Color.BLACK;
priceLabel.setColor(labelColor);
nameLabel.setColor(labelColor);
priceBounds = new Rectangle();
nameBounds = new Rectangle();
layout.update(this);
usedEffectUpdated();
color = Klooni.theme.getRandomCellColor(); color = Klooni.theme.getRandomCellColor();
this.effect = effect;
usedItemUpdated();
} }
//endregion //endregion
@ -91,14 +64,11 @@ public class EffectCard extends Actor {
// so it's becomes cellSize * 2 // so it's becomes cellSize * 2
Cell.draw(color, batch, x + cellSize * 2, y + cellSize * 2, cellSize); Cell.draw(color, batch, x + cellSize * 2, y + cellSize * 2, cellSize);
nameLabel.setBounds(x + nameBounds.x, y + nameBounds.y, nameBounds.width, nameBounds.height); super.draw(batch, parentAlpha);
nameLabel.draw(batch, parentAlpha);
priceLabel.setBounds(x + priceBounds.x, y + priceBounds.y, priceBounds.width, priceBounds.height);
priceLabel.draw(batch, parentAlpha);
} }
public void usedEffectUpdated() { @Override
public void usedItemUpdated() {
if (game.effect.name.equals(effect.name)) if (game.effect.name.equals(effect.name))
priceLabel.setText("currently used"); priceLabel.setText("currently used");
else if (Klooni.isEffectBought(effect)) else if (Klooni.isEffectBought(effect))
@ -107,16 +77,29 @@ public class EffectCard extends Actor {
priceLabel.setText("buy for "+effect.price); priceLabel.setText("buy for "+effect.price);
} }
@Override
public void use() { public void use() {
game.updateEffect(effect); game.updateEffect(effect);
usedEffectUpdated(); usedItemUpdated();
} }
@Override
public boolean isBought() {
return Klooni.isEffectBought(effect);
}
@Override
public boolean isUsed() { public boolean isUsed() {
return game.effect.equals(effect.name); return game.effect.equals(effect.name);
} }
void performBuy() { @Override
public float getPrice() {
return effect.price;
}
@Override
public void performBuy() {
Klooni.buyEffect(effect); Klooni.buyEffect(effect);
use(); use();
} }

View file

@ -43,7 +43,7 @@ public class MoneyBuyBand extends Table {
// The theme card that is going to be bought next. We can't // The theme card that is going to be bought next. We can't
// only save the Theme because we need to tell the ThemeCard // only save the Theme because we need to tell the ThemeCard
// that it was bought so it can reflect the new theme status. // that it was bought so it can reflect the new theme status.
private Object toBuy; // Either ThemeCard or EffectCard private ShopCard toBuy;
// Used to interpolate between strings // Used to interpolate between strings
private StringBuilder shownText; private StringBuilder shownText;
@ -78,10 +78,7 @@ public class MoneyBuyBand extends Table {
@Override @Override
public void changed(ChangeEvent event, Actor actor) { public void changed(ChangeEvent event, Actor actor) {
if (toBuy != null) { if (toBuy != null) {
if (toBuy instanceof ThemeCard) toBuy.performBuy();
((ThemeCard)toBuy).performBuy();
else if (toBuy instanceof EffectCard)
((EffectCard)toBuy).performBuy();
} }
showCurrentMoney(); showCurrentMoney();
hideBuyButtons(); hideBuyButtons();
@ -175,25 +172,10 @@ public class MoneyBuyBand extends Table {
//region Public methods //region Public methods
// Asks the user to buy the given theme, or shows // Asks the user to buy the given theme or effect,
// that they don't have enough money to buy it // or shows that they don't have enough money to buy it
public void askBuy(final ThemeCard toBuy) { public void askBuy(final ShopCard toBuy) {
if (toBuy.theme.getPrice() > Klooni.getMoney()) { if (toBuy.getPrice() > Klooni.getMoney()) {
setTempText("cannot buy!");
confirmButton.setVisible(false);
cancelButton.setVisible(false);
}
else {
this.toBuy = toBuy;
setText("confirm?");
confirmButton.setVisible(true);
cancelButton.setVisible(true);
}
}
// TODO Make a generic card class so they all inherit
public void askBuy(final EffectCard toBuy) {
if (toBuy.effect.price > Klooni.getMoney()) {
setTempText("cannot buy!"); setTempText("cannot buy!");
confirmButton.setVisible(false); confirmButton.setVisible(false);
cancelButton.setVisible(false); cancelButton.setVisible(false);

View file

@ -0,0 +1,79 @@
/*
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.actors;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import io.github.lonamiwebs.klooni.Klooni;
import io.github.lonamiwebs.klooni.Theme;
import io.github.lonamiwebs.klooni.game.GameLayout;
public abstract class ShopCard extends Actor {
final Klooni game;
final Label nameLabel;
final Label priceLabel;
public final Rectangle nameBounds;
public final Rectangle priceBounds;
public float cellSize;
public ShopCard(final Klooni game, final GameLayout layout,
final String itemName, final Color backgroundColor) {
this.game = game;
Label.LabelStyle labelStyle = new Label.LabelStyle();
labelStyle.font = game.skin.getFont("font_small");
priceLabel = new Label("", labelStyle);
nameLabel = new Label(itemName, labelStyle);
Color labelColor = Theme.shouldUseWhite(backgroundColor) ? Color.WHITE : Color.BLACK;
priceLabel.setColor(labelColor);
nameLabel.setColor(labelColor);
priceBounds = new Rectangle();
nameBounds = new Rectangle();
layout.update(this);
}
@Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
final float x = getX(), y = getY();
nameLabel.setBounds(x + nameBounds.x, y + nameBounds.y, nameBounds.width, nameBounds.height);
nameLabel.draw(batch, parentAlpha);
priceLabel.setBounds(x + priceBounds.x, y + priceBounds.y, priceBounds.width, priceBounds.height);
priceLabel.draw(batch, parentAlpha);
}
public abstract void usedItemUpdated();
public abstract void use();
public abstract boolean isBought();
public abstract boolean isUsed();
public abstract float getPrice();
public abstract void performBuy();
}

View file

@ -17,12 +17,8 @@
*/ */
package io.github.lonamiwebs.klooni.actors; package io.github.lonamiwebs.klooni.actors;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import io.github.lonamiwebs.klooni.Klooni; import io.github.lonamiwebs.klooni.Klooni;
import io.github.lonamiwebs.klooni.Theme; import io.github.lonamiwebs.klooni.Theme;
@ -30,21 +26,13 @@ import io.github.lonamiwebs.klooni.game.Cell;
import io.github.lonamiwebs.klooni.game.GameLayout; import io.github.lonamiwebs.klooni.game.GameLayout;
// Card-like actor used to display information about a given theme // Card-like actor used to display information about a given theme
public class ThemeCard extends Actor { public class ThemeCard extends ShopCard {
//region Members //region Members
public final Theme theme; public final Theme theme;
private final Texture background; private final Texture background;
private final Label nameLabel;
private final Label priceLabel;
public final Rectangle nameBounds;
public final Rectangle priceBounds;
public float cellSize;
private final static int colorsUsed[][] = { private final static int colorsUsed[][] = {
{0, 7, 7}, {0, 7, 7},
{8, 7, 3}, {8, 7, 3},
@ -56,24 +44,11 @@ public class ThemeCard extends Actor {
//region Constructor //region Constructor
public ThemeCard(final Klooni game, final GameLayout layout, final Theme theme) { public ThemeCard(final Klooni game, final GameLayout layout, final Theme theme) {
this.theme = theme; super(game, layout, theme.getDisplay(), theme.background);
background = Theme.getBlankTexture(); background = Theme.getBlankTexture();
Label.LabelStyle labelStyle = new Label.LabelStyle(); this.theme = theme;
labelStyle.font = game.skin.getFont("font_small"); usedItemUpdated();
priceLabel = new Label("", labelStyle);
nameLabel = new Label(theme.getDisplay(), labelStyle);
Color labelColor = Theme.shouldUseWhite(theme.background) ? Color.WHITE : Color.BLACK;
priceLabel.setColor(labelColor);
nameLabel.setColor(labelColor);
priceBounds = new Rectangle();
nameBounds = new Rectangle();
layout.update(this);
usedThemeUpdated();
} }
//endregion //endregion
@ -95,14 +70,11 @@ public class ThemeCard extends Actor {
} }
} }
nameLabel.setBounds(x + nameBounds.x, y + nameBounds.y, nameBounds.width, nameBounds.height); super.draw(batch, parentAlpha);
nameLabel.draw(batch, parentAlpha);
priceLabel.setBounds(x + priceBounds.x, y + priceBounds.y, priceBounds.width, priceBounds.height);
priceLabel.draw(batch, parentAlpha);
} }
public void usedThemeUpdated() { @Override
public void usedItemUpdated() {
if (Klooni.theme.getName().equals(theme.getName())) if (Klooni.theme.getName().equals(theme.getName()))
priceLabel.setText("currently used"); priceLabel.setText("currently used");
else if (Klooni.isThemeBought(theme)) else if (Klooni.isThemeBought(theme))
@ -111,16 +83,29 @@ public class ThemeCard extends Actor {
priceLabel.setText("buy for "+theme.getPrice()); priceLabel.setText("buy for "+theme.getPrice());
} }
@Override
public void use() { public void use() {
Klooni.updateTheme(theme); Klooni.updateTheme(theme);
usedThemeUpdated(); usedItemUpdated();
} }
@Override
public boolean isBought() {
return Klooni.isThemeBought(theme);
}
@Override
public boolean isUsed() { public boolean isUsed() {
return Klooni.theme.getName().equals(theme.getName()); return Klooni.theme.getName().equals(theme.getName());
} }
void performBuy() { @Override
public float getPrice() {
return theme.getPrice();
}
@Override
public void performBuy() {
Klooni.buyTheme(theme); Klooni.buyTheme(theme);
use(); use();
} }

View file

@ -23,8 +23,7 @@ import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.Label;
import io.github.lonamiwebs.klooni.actors.Band; import io.github.lonamiwebs.klooni.actors.Band;
import io.github.lonamiwebs.klooni.actors.EffectCard; import io.github.lonamiwebs.klooni.actors.ShopCard;
import io.github.lonamiwebs.klooni.actors.ThemeCard;
// Helper class to calculate the size of each element // Helper class to calculate the size of each element
// //
@ -35,7 +34,7 @@ public class GameLayout {
//region Members //region Members
private float screenWidth, marginWidth, availableWidth; private float screenWidth, marginWidth, availableWidth;
private float screenHeight, logoHeight, scoreHeight, boardHeight, pieceHolderHeight, themeCardHeight; private float screenHeight, logoHeight, scoreHeight, boardHeight, pieceHolderHeight, shopCardHeight;
//endregion //endregion
@ -63,7 +62,7 @@ public class GameLayout {
boardHeight = screenHeight * 0.50f; boardHeight = screenHeight * 0.50f;
pieceHolderHeight = screenHeight * 0.25f; pieceHolderHeight = screenHeight * 0.25f;
themeCardHeight = screenHeight * 0.15f; shopCardHeight = screenHeight * 0.15f;
} }
//endregion //endregion
@ -132,33 +131,18 @@ public class GameLayout {
band.infoBounds.set(area.x, area.y + area.height * 0.10f, area.width, area.height * 0.35f); band.infoBounds.set(area.x, area.y + area.height * 0.10f, area.width, area.height * 0.35f);
} }
public void update(ThemeCard card) { public void update(ShopCard card) {
card.setSize(availableWidth - marginWidth, themeCardHeight); card.setSize(availableWidth - marginWidth, shopCardHeight);
card.cellSize = themeCardHeight * 0.2f; card.cellSize = shopCardHeight * 0.2f;
// X offset from the cells (5 cells = themeCardHeight) // X offset from the cells (5 cells = shopCardHeight)
card.nameBounds.set( card.nameBounds.set(
themeCardHeight, card.cellSize, shopCardHeight, card.cellSize,
availableWidth - themeCardHeight, themeCardHeight); availableWidth - shopCardHeight, shopCardHeight);
card.priceBounds.set( card.priceBounds.set(
themeCardHeight, -card.cellSize, shopCardHeight, -card.cellSize,
availableWidth - themeCardHeight, themeCardHeight); availableWidth - shopCardHeight, shopCardHeight);
}
// TODO Probably a more generic class "card" that can hold any type (theme/effect)
public void update(EffectCard card) {
card.setSize(availableWidth - marginWidth, themeCardHeight);
card.cellSize = themeCardHeight * 0.2f;
// X offset from the cells (5 cells = themeCardHeight)
card.nameBounds.set(
themeCardHeight, card.cellSize,
availableWidth - themeCardHeight, themeCardHeight);
card.priceBounds.set(
themeCardHeight, -card.cellSize,
availableWidth - themeCardHeight, themeCardHeight);
} }
//endregion //endregion

View file

@ -37,6 +37,7 @@ import io.github.lonamiwebs.klooni.Klooni;
import io.github.lonamiwebs.klooni.Theme; import io.github.lonamiwebs.klooni.Theme;
import io.github.lonamiwebs.klooni.actors.EffectCard; import io.github.lonamiwebs.klooni.actors.EffectCard;
import io.github.lonamiwebs.klooni.actors.MoneyBuyBand; import io.github.lonamiwebs.klooni.actors.MoneyBuyBand;
import io.github.lonamiwebs.klooni.actors.ShopCard;
import io.github.lonamiwebs.klooni.actors.SoftButton; import io.github.lonamiwebs.klooni.actors.SoftButton;
import io.github.lonamiwebs.klooni.actors.ThemeCard; import io.github.lonamiwebs.klooni.actors.ThemeCard;
import io.github.lonamiwebs.klooni.game.GameLayout; import io.github.lonamiwebs.klooni.game.GameLayout;
@ -189,110 +190,63 @@ class CustomizeScreen implements Screen {
final GameLayout layout = new GameLayout(); final GameLayout layout = new GameLayout();
shopGroup.clear(); shopGroup.clear();
if (showingEffectsShop) { if (showingEffectsShop)
for (Effect effect : Effect.getEffects()) { for (Effect effect : Effect.getEffects())
final EffectCard card = new EffectCard(game, layout, effect); addCard(new EffectCard(game, layout, effect));
card.addListener(new InputListener() {
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
shopDragStartX = x;
shopDragStartY = y;
return true;
}
// We could actually rely on touchDragged not being called, else // showingThemesShop
// but perhaps it would be hard for some people not to move for (Theme theme : Theme.getThemes())
// their fingers even the slightest bit, so we use a custom addCard(new ThemeCard(game, layout, theme));
// drag limit
@Override // Scroll to the currently selected item
public void touchUp(InputEvent event, float x, float y, int pointer, int button) { table.layout();
x -= shopDragStartX; for (Actor a : shopGroup.getChildren()) {
y -= shopDragStartY; ShopCard c = (ShopCard)a;
float distSq = x * x + y * y; if (c.isUsed()) {
if (distSq < DRAG_LIMIT_SQ) { shopScroll.scrollTo(
if (Klooni.isEffectBought(card.effect)) c.getX(), c.getY() + c.getHeight(),
card.use(); c.getWidth(), c.getHeight());
else break;
buyBand.askBuy(card);
for (Actor a : shopGroup.getChildren()) {
EffectCard c = (EffectCard)a;
c.usedEffectUpdated();
}
}
}
});
shopGroup.addActor(card);
// Scroll to the currently selected theme
table.layout();
for (Actor a : shopGroup.getChildren()) {
EffectCard c = (EffectCard)a;
if (c.isUsed()) {
shopScroll.scrollTo(
c.getX(), c.getY() + c.getHeight(),
c.getWidth(), c.getHeight());
break;
}
c.usedEffectUpdated();
}
}
} else {
// Showing themes shop otherwise
for (Theme theme : Theme.getThemes()) {
final ThemeCard card = new ThemeCard(game, layout, theme);
card.addListener(new InputListener() {
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
shopDragStartX = x;
shopDragStartY = y;
return true;
}
// We could actually rely on touchDragged not being called,
// but perhaps it would be hard for some people not to move
// their fingers even the slightest bit, so we use a custom
// drag limit
@Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
x -= shopDragStartX;
y -= shopDragStartY;
float distSq = x * x + y * y;
if (distSq < DRAG_LIMIT_SQ) {
if (Klooni.isThemeBought(card.theme))
card.use();
else
buyBand.askBuy(card);
for (Actor a : shopGroup.getChildren()) {
ThemeCard c = (ThemeCard)a;
c.usedThemeUpdated();
}
}
}
});
shopGroup.addActor(card);
// Scroll to the currently selected theme
table.layout();
for (Actor a : shopGroup.getChildren()) {
ThemeCard c = (ThemeCard)a;
if (c.isUsed()) {
shopScroll.scrollTo(
c.getX(), c.getY() + c.getHeight(),
c.getWidth(), c.getHeight());
break;
}
c.usedThemeUpdated();
}
} }
c.usedItemUpdated();
} }
} }
private void addCard(final ShopCard card) {
card.addListener(new InputListener() {
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
shopDragStartX = x;
shopDragStartY = y;
return true;
}
// We could actually rely on touchDragged not being called,
// but perhaps it would be hard for some people not to move
// their fingers even the slightest bit, so we use a custom
// drag limit
@Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
x -= shopDragStartX;
y -= shopDragStartY;
float distSq = x * x + y * y;
if (distSq < DRAG_LIMIT_SQ) {
if (card.isBought())
card.use();
else
buyBand.askBuy(card);
for (Actor a : shopGroup.getChildren()) {
((ShopCard)a).usedItemUpdated();
}
}
}
});
shopGroup.addActor(card);
}
//endregion //endregion
//region Public methods //region Public methods