currently I am in the process of developing a trading card game in Java using Libgdx. Each player has a number of cards with different abilities and attributes. Each card class extends the Actor class, but I am wondering if there is a way I can draw text onto these Actors, that will move when the cards do.
For example, each card has a set amount of hit points, which will vary depending on the damage that card has taken. I was wondering what the best way to draw these hitpoints into the card would be, so that when the card moves, the hitpoints will move with it. Occasionally, the cards will stack or overlap, and in these instances I would obviously want the text of cards at the bottom to be concealed by cards at the top, rather than it all overlapping.
Any guidance would be greatly appreciated.
There is an easy solution thanks to the inheritance that libGDX provides.
As Group is an actor you can easily do... (pseudo code)
public class Card extends Group {
final private static TextureAtlas ATLAS;
static {
ATLAS = AssetManager.get("game.pack", TextureAtlas.class);
}
public enum Type {
type1, type2, type3
}
private Type type;
private Image card;
private Label text;
private int hitPoints;
public Card(Type type) {
this.type = type;
card = new Image(ATLAS.get(type));
text = new Label("HP: " + hitPoints);
addActor(card);
addActor(text);
}
}
This assumes you have enum for card types associated with the identifiers in your texture atlas; if you are not using a texture atlas I highly recommend that you do.
In your game logic class I am assuming it would be an extension of the Screen class you can simply;
private Card card;
#override
public void show() {
card = new Card(Card.Type.type1);
stage.addActor(card);
// This is an example - as the card and text reside within a group they can be moved as a sole entity relative to their parent
card.addAction(moveBy(100, 100, 2, Interpolation.Linear));
}
Of course positioning of actors if specific to your use case etc... Any questions just ask :)
Related
For a project I am involved in, I have the task of writing some code to be able to save and load the current gamestate. Now, being that I am using java, I already know Serialization is probably the best way to go about this. Now, the gamestate that I have to save involves one main class witha singleton pattern shown here:
public class Game implements java.io.Serializable
{
private static ArrayList<Room> world;
private static Game game = nul
private Game(){}
public static Game getGame()
{
if (game != null)
{
game = new Game();
}
return game;
}
A little bit further down in the code are a bunch of objects that are used to help the game run.
Position heroPos = new Position(HERO_ROOM_INDEX,
HERO_POS_X, HERO_POS_Y);
Rectangle heroHitbox = new Rectangle(
new Position(HERO_ROOM_INDEX,
HERO_HITBOX_X_OFFSET, HERO_HITBOX_Y_OFFSET),
HERO_HITBOX_WIDTH,
HERO_HITBOX_HEIGHT);
Entity hero = new Player(heroPos, heroHitbox, HERO_SYMBOL);
Position leverPos = new Position(getPlayerRoomIndex(), LEVER_POS_X,
LEVER_POS_Y);
(The actual code is pretty long and would be hard to read, but it follows mostly the same format)
Where Entity, Rectangle, Position are all separate classes in different packages than Game. So, if I were to try and serialize this Game object, how would I go about it? Would I have to use ObjectOutputStream to write every single object that Game creates into a file? Or do I just have to make sure that all of these classes that Game uses implement the Serializable interface, and then just serialize the Game object?
Having an issue with tables and updating a label! Here is the dilemma, I have a sell button in my game that is updating the player's coins whenever they sell an item, that part is working perfectly. The issue I am having is trying to get the coin value to update on the screen while there in this separate menu (see pic attached, coins in the top left). The problem is that the coin value is in another stage in another class. This is because I have different tables that pop up in the middle when I click the different buttons at the bottom. I have tried helper methods for going in and clearing that table and updating it and then sending me back to this item page but it is not working, I can post any code needed but this is more of a general question on how to update a label within a table in a stage.
Update: So to kinda sum up my question, I have a Screen and I have have three tables in it the bottom table the top left and the top right. Then I add the table to the stage in the middle when they press the inventory or shop button etc. What I am looking to do is to keep the item page open and simply just update the value of the Coin label, I know I can change the text using .setText(); Im just not sure how I can update that portion of the screen etc..
Update 2: If I just set the screen back to a new screen of this screen it updates the coin value but then I am not on the item page anymore which is not ideal.
Update 3: Thanks for the help so far guys, #John your answer is super helpful aswell. Im still not getting this working though here is a little bit of the code where the label is being handled.
playerCoinLabel = new Label(playerSave.getCoinsString(),skin,"defaultMiddle");
This is where it is getting added to the table.
tableLeft = new Table(skin);
stage.addActor(tableLeft);
tableLeft.setBounds(0,0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
tableLeft.setFillParent(true);
tableLeft.top().left();
tableLeft.add(healthNonButton).size(84,80).left().padLeft(10).padTop(5);
tableLeft.add(playerHealthLabel).left().padLeft(15);
tableLeft.row();
tableLeft.add(levelNonButton).size(74,70).center().padLeft(10);
tableLeft.add(playerLevelLabel).left().padLeft(19);
tableLeft.row();
tableLeft.add(coinNonButton).size(74,70).center().padLeft(10);
tableLeft.add(this.playerCoinLabel).left().padLeft(15); //This line
tableLeft.row();
Then I have this method for updating my label using the setText like you guys were telling me about.
public void updatePlayerCoins() {
playerCoinLabel.setText(playerSave.getCoinsString());
}
and if I call this method anywhere, render() or where im setting the new coin value it is not updating/changing the label in the top left of my screen. I can post all the code to a github if I need to just posted the things involving the label. This is just a project im working on to increase my skill set so sorry if I sound amateur, it is because I am!
Thanks everyone!
It seems like you're asking two things- how do I update a label? and How do I structure my code? It's hard to tell what's going wrong with the former since we can't see your code, but #Tenfour04 is right- you want to retain a reference to the label somewhere and call setText() when you want to change the amount.
As far as structuring your code, I would suggest a simple OOP design and then evolve it like so:
First, we need an object to represent the player:
class Player {
private int coins; // Pretend there are getters / setters.
private int health;
private int level;
}
Now you probably have more than one way that you want to represent this player information, so we'll split the rendering code into a separate class or set of classes:
class StatWidget {
private Stage stage;
private Player player;
private Label lblCoins;
public StatWidget(Player player) { // Pseudo-code
this.player = player;
this.stage = new Stage();
Table tbl = new Table();
this.lblCoins = new Label(); // Notice we keep a reference to the label
tbl.add( this.coins );
}
public void update() {
lblCoins.setText(player.getCoins());
}
}
Now you can sync the UI with your player object's state simply by calling Player#update(). But when do you call it?
You could call update() in your render method. This is a little inefficient because you're updating the object whether it needs to be updated or not, but it's dead simple, and if you're only updating a few UI elements this way it probably doesn't matter. Personally, I'd stop here.
If you want to be more precise, you would only call update() when you actually make a change to the Player's coins. You can do this by finding the places in your code where you set the player's coins and add the update call like so:
player.setCoins( A_LOT_OF_MONEY );
statWidget.update();
Problem is this gets more cumbersome as you add more widgets- all your game logic now has to know about StatWidget and make calls to it. We could cut this dependency a little bit by using an event-driven architecture. Essentially, whenever player's state changes, it would send an event to interested parties notifying them of the change. You could use the pseudo-code below:
interface Publisher {
void subscribe(Subscriber subby);
void unsubscribe(Subscriber subby);
}
class Player implements Publisher {
private List<Subscriber> subscribers;
private int coins;
// ...
public void setCoins(int amount) {
this.coins = amount;
for(Subscriber subscriber : subscribers) subscriber.notify("COINS", amount);
}
public void subscribe(Subscriber subby) {
this.subscribers.add(subby);
}
public void unsubscribe(Subscriber subby) {
this.subscribers.remove(subby);
}
}
interface Subscriber {
void notify(String event, int qty);
void dispose();
}
class StatWidget implements Subscriber {
private Publisher player;
private Label label;
// ...
public StatWidget(Player player) {
this.player = player;
this.player.addSubscriber(this);
void notify(String event, int qty) {
if(event.equals("COINS")) label.setText(qty);
}
void dispose() {
this.player.unsubscribe(this);
}
}
The event system above could certainly be polished, and you could likely do clever things with generics (or use a library that has thought all this out for your), but hopefully it illustrates the concepts.
I'm writing a small Java program that randomly deals out playing cards, then displays them on screen in a window.
Since I'm using NetBeans, the GUI was started for me, and I've been writing my methods for randomly choosing cards, setting up an array to store whether or not a card has already been dealt, etc., all in the same class NetBeans set up for me when it built the JFrame.
I'd like to move all my non-GUI code into its own Class, and then just pass data back to the GUI class as needed to display the cards, but I'm not sure of the best way to share data between the two classes.
I know about set/get methods and I know I could make public class-level variables, but everything I've been reading tells me to avoid both as much as possible.
Right now I have a method that generates an int between 1 and 52 for each card dealt. 1 = Ace of spades, 2= 2 of spades, etc. Once the GUI has that number, it can display the appropriate card in the appropriate place on the screen (or at least it will be able to once I've coded the GUI side of things). If I'm looking to pass that integer value to the GUI class, then display a specific card on the screen based on that value, how should I do it?
Seems to me a public variable would make this easy, as would a simple get method...but in the interest of avoiding those options is there another way?
I can provide code snippets if that helps.
Here's one way you could start to implement this idea using OO concepts.
Make a Card class to represent a card.
public class Card {
// FIELDS
// card name
private final String name;
// card value (number)
private final int value;
// another arbitrary value to demonstrate setter
private Object arbitraryValue;
public Card(String name, String value) {
this.name = name;
this.value = value;
}
public String getName() {
return this.name;
}
public int getValue() {
return this.value;
}
public Object getArbitraryValue() {
return this.arbitraryValue;
}
public void setArbitraryValue(Object arbitraryValue) {
this.arbitraryValue = arbitraryValue;
}
}
Create a CardManager class to hold methods that pertain to handling cards (e.g. utility methods and card data storage)
public class CardManager() {
private List<Card> cards = new ArrayList<Card>();
public void addCard(Card card) {
this.cards.add(card);
}
// and so on...your methods here.
}
Finally, create a class for your GUI (CardGUI) management and make use of the other classes to manage it.
You can do so like this:
public class CardGUI() {
public static void main(String[] args) {
// create your GUI and put your logic here...
// also use your other classes, perhaps like so.
Card card = new Card("One", 1);
CardManager cardManager = new CardManager();
cardManager.addCard(card);
// From there you can manage your cards through other classes.
}
Hope this helps / demonstrates how to share data between classes following standards.
Edit:
To answer your question on exactly how you would get the value, then see the above Card class. You would simple create a new card (Card card = new Card("name", intval);), then you would use the method Card#getValue() to get that value and display it in the GUI.
Let's say I have a class resources which instantiates all of my OpenGL / Java game objects and I then pass these via constructor to my Scene class (which requires them), like so (simplified example).....
public class Resources {
Hero hero;
Enemy enemy;
MenuButtons mainMenuButtons;
Background background;
Scene mainMenu;
public void createObjects(){
hero = new Hero();
enemy = new Enemy();
mainMenuButtons = new MenuButtons();
background = new Background();
mainMenu = new Scene(hero, enemy, mainMenuButtons, background);
}
}
Obviously my Scene's constructor would need to take 4 arguments like so:
public class MainMenu implements Scene {
hero Hero;
enemy Enemy;
mainMenuButtons MenuButtons;
background Background;
public MainMenu(Hero hero, Enemy enemy, MainMenuButtons mainMenuButtons, Background background){
this.hero = hero;
this.enemy = enemy;
this.mainMenuButtons = mainMenuButtons;
this.background = background;
}
}
As more objects are required, the constructor grows ever longer. Now let's say I do something like the following instead:
public class MainMenu implements Scene {
Resources resources;
public MainMenu(Resources resources){
this.hero = resources.hero;
this.enemy = resources.enemy;
this.mainMenuButtons = resources.mainMenuButtons;
this.background = resources.background;
}
}
Both options would allow me to use objects within my mainMenuScene like so:
hero.move();
The 2nd seems to be little neater as the constructor will never need to take any additional arguments. However as far as I can recall, I've never really seen any examples like this. Is this a valid technique? Would I run into an problems using it?
Short Answer:-Yes the technique is valid and it should work fine.
Longer part:-
I would like to suggest two design approaches to consider
The essence pattern
The fluent interface pattern
These are both similar in intent.
Also the builder pattern can be helpful. We see it many times using hibernate. For your class it could like below:-
public class mainMenu implements Scene {
private Hero hero;
private Enemy enemy;
private MenuButtons mainMenuButtons;
private Background background;
public mainMenu setHero(Hero hero){this.hero = hero; return this}
public mainMenu setEnemy(Enemy enemy){this.enemy = enemy; return this}
public mainMenu setMainMenuButtons(MenuButtons mainMenuButtons){this.mainMenuButtons = mainMenuButtons; return this}
public mainMenu setBackground(Background background){this.background = background; return this}
}
And then you could create objects using chaining something like below:-
mainMenu main =new mainMenu().
setHero(new Hero()).
setEnemy(new Enemy()).
setMainMenuButtons(new MainMenuButtons()).
setBackground(new Background());
P.S. Even if you don't want to use above patterns I recommend three changes or habits.
1. Class name start with uppercase alphabet and
2. A convention of organizing the arguments alphabetically.
3. Probably you want to set acces level of the members to private.
I like it. Instead of Resources, I like to call it an ApplicationContext and use the same way.
I've been critized for creating a "God Object". I disagree with this. As long as the ApplicationContext is thin and only holds objects, but doesn't know anything about them (call any methods), then it's fine. It could be replaced by a List or Map, except I like the additional type checking.
See the Service Locator pattern for another way of doing this.
I'm building an MVC based java application/game and trying to use IoC to separate object creation from application logic.
Let's assume I have just 2 entity : Board and Player where
each one has a Model class, a View class and a Controller class.
The BoardModel needs a PlayerModel (to handle some app logic) and the BoardView needs a PlayerView (to render it inside its space ).
To create a new Player I use a PlayerFactory class that creates the PlayerModel, the PlayerView and the PlayerController and wires them together.
The problem is that after creating the Player I need the PlayerModel and PlayerView instances to create the Board.
My solution is to "wrap" the PlayerModel, PlayerView and PlayerController in a Player class that only has these 3 fields and 3 getters; pass the Player to the BoardFactory and inside the factory use the 3 getter to get the View and the Model needed by the Board.
I'm doing something like this :
PlayerFactory pFactory = new PlayerFactory();
Player player = pFactory.build("HUMAN");
BoardFactory bFactory = new BoardFactory();
Board board = bFactory.build(player);
My worries are about the "wrapper" Player class.
Does it make sense to have a class just to hold 3 objects ?
Is there a better way to pass the dependencies to the Board without using a IoC container?
Your overall approach looks good. Although, there are a couple of changes I would make :
PlayerController and Player seem to have the same responsibility. I would get rid of Player completely and just use a PlayerController instead
The pseudo-code would look like this :
public class PlayerController {
private PlayerView playerView;
private PlayerModel playerModel;
//constructor that intializes playerView and playerModel
public void render() { playerView.render() }
public void moveForward(int steps) {
if(playerModel.canMoveForward()) {
playerView.moveForward(steps);
}
}
}
Similarly, you can get rid of Board and just have a BoardController instead. BoardController can then depend on PlayerController instead of depending on Player. The pseudo-code for this would look something like :
public class BoardController {
private PlayerController playerController;
private BoardView boardView;
private BoardModel boardModel;
//constructor that intializes the dependencies
public void render() {
playerController.render();
boardView.render();
}
public void movePlayerForward(int steps) {
if(!boardModel.isGameOver()) {
playerController.moveForward(steps);
}
}
}
This way, you get rid of Player and Board classes that were really not doing much. Alternately, you can rename the above classes to Player and Board. Another advantage of the above pseudo-code is that you also end up making your code more readable by implementing the Tell Dont Ask principle.