How do I use serialization to save a gamestate using multiple classes? - java

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?

Related

Java Constructor Injection

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.

Java inversion of control on an MVC based application

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.

Invoking methods of a class that instantiated this one

I'm developing a game in Java which uses the Lightweight Java Game Library (LWJGL) with OpenGL.
I encountered the following problem.
I want to create an ArrayList of all textures in an object in the main loop, and access these from objects instantiated in this main object. A simplified example:
game.class:
public class Game {
ArrayList Textures; // to hold the Texture object I created
Player player; // create Player object
public Game() {
new ResourceLoader(); // Here is the instance of the ResourceLoader class
player = new Player(StartingPosition) // And an instance of the playey, there are many more arguments I give it, but none of this matter (or so I hope)
while(true) { // main loop
// input handlers
player.draw() // here I call the player charcter to be drawn
}
}
// this method SHOULD allow the resource loader to add new textures
public void addTextures (Texture tx) {
Textures.add(tx);
}
}
ResourceLoader.class
public class ResourceLoader {
public ResourceLoader() {
Interface.this.addTexture(new Texture("image.png")); // this is the line I need help with
}
}
Player.class
public class Player {
public player() {
// some stuff, including assignment of appropriate textureID
}
public void draw() {
Interface.this.Textures.get(this.textureID).bind(); // this also doesn't work
// OpenGL method to draw the character
}
}
In my real code the ResourceLoader class has about 20 textures to load.
There is a total of over 400 entities in the game that have a draw method just like Player.class and most of them share the same texture; e.g. there are about 150-180 wall object all showing the same image of bricks.
The Game object is not the main class and it does not have the static void main() method, but it is one of the only few things instantiated in the main() method of the game.
Also, in the past, I worked around the problem by letting each entity load its own texture file. But as I increased the complexity and map size, it becomes very inefficient to load the same image hundreds of times.
I arrived at the state of the code above from this answer.
I believe I would have to put ResourceLoader.class and Player.class inside the game.class, which would not be a good solution considering that there are about 20 files that need this treatment and most of them are 200+ lines long.
I think my Texture object as well as initialization of OpenGL and other stuff are pretty generic and should not impact the issue in question. I can provide these if necessary.
Make the "outer" class instance a parameter to the constructors:
public class Player {
final Interface obj;
public player(Interface obj) {
this.obj = obj;
// some stuff, including assignment of appropriate textureID
}
public void draw() {
obj.Textures.get(this.textureID).bind();
}
}
public class ResourceLoader {
public ResourceLoader(Interface obj) {
obj.addTexture(new Texture("image.png"));
}
}
And instantiate those in Game like:
new Player(this);
Note: The example lines used Interface but Game does not implement it. I assume that's an artifact of code cleaned for the posting. Just use the type that is appropriate for your situation.

Java using an object from a central class

I am making a game in Java and I have a central(Engine) class which will render the scenery/player/etc.
In the Engine class I create my player object like so
public class Engine() {
public static Player player;
public Engine() {
RenderPlayer();
}
protected static void RenderPlayer() {
player = new Player();
}
}
I also have a Canvas class which handles the drawing of the player.
I want to be able to call the Players functions without having to create a new instance( since I created the player in the Engine class ). Whenever I try to use a function from the player, I get a null pointer expection.
This is how I call it.
Engine.player.tick();
I have spent a couple hours trying to figure it out, May someone tell me what I am doing wrong, and help me in the right direction? Thank you.
You need to call Engine.RenderPlayer() prior calling Engine.player.tick(); as this method assigns a new Player instance to the static player attribute. Before you call this method player is null and it is causing your NullPointerException.
You can fix this issue by simply changing:
public static Player player;
to:
public static Player player = new Player();
player is null if you never create an instance of Engine because RenderPlayer() is in the constructor of Engine.
You could just do
public static Player player = new Player();
or make sure to call RenderPlayer() explicitly before accessing player.

Looking for an appropriate design pattern

I have a game that tracks user stats after every match, such as how far they travelled, how many times they attacked, how far they fell, etc, and my current implementations looks somewhat as follows (simplified version):
Class Player{
int id;
public Player(){
int id = Math.random()*100000;
PlayerData.players.put(id,new PlayerData());
}
public void jump(){
//Logic to make the user jump
//...
//call the playerManager
PlayerManager.jump(this);
}
public void attack(Player target){
//logic to attack the player
//...
//call the player manager
PlayerManager.attack(this,target);
}
}
Class PlayerData{
public static HashMap<int, PlayerData> players = new HashMap<int,PlayerData>();
int id;
int timesJumped;
int timesAttacked;
}
public void incrementJumped(){
timesJumped++;
}
public void incrementAttacked(){
timesAttacked++;
}
}
Class PlayerManager{
public static void jump(Player player){
players.get(player.getId()).incrementJumped();
}
public void incrementAttacked(Player player, Player target){
players.get(player.getId()).incrementAttacked();
}
}
So I have a PlayerData class which holds all of the statistics, and brings it out of the player class because it isn't part of the player logic. Then I have PlayerManager, which would be on the server, and that controls the interactions between players (a lot of the logic that does that is excluded so I could keep this simple). I put the calls to the PlayerData class in the Manager class because sometimes you have to do certain checks between players, for instance if the attack actually hits, then you increment "attackHits".
The main problem (in my opinion, correct me if I'm wrong) is that this is not very extensible. I will have to touch the PlayerData class if I want to keep track of a new stat, by adding methods and fields, and then I have to potentially add more methods to my PlayerManager, so it isn't very modulized.
If there is an improvement to this that you would recommend, I would be very appreciative. Thanks.
I am not at all an expert in design patterns. But this is what I think might be useful:
To add actions to the player, you might wanna look at the Strategy Pattern. Just google for it and you will get lot of examples.
Here is an attempt by me:
For updating the player stats, I guess Observer Pattern will be helpful.
The Observer Pattern defines one-to-many dependency between objects so
that when one object changes state, all of its dependents are notified
and updated automatically.
It enforces loose coupling so that future changes are easy.
(You will have to read about Observer Pattern and also will have to see some examples. It is not as straight forward as Strategy.)
Due to the fact that you said you want to be able to add new stats and actions later, I would tend to make a stats object that doesn't need to know anything about the game it's recording. The advantage is that the Stats class would never need to change as you added new features.
public interface Stats {
void incrementStat(Object subject, String stat);
int getStat(Object subject, String stat);
}
You Player implementation would look something like:
public void jump() {
// Logic to make the player jump...
stats.incrementStat(this, "jump");
}
Of course, what you're trading for that flexibility is static type-checking on those increment methods. But in cases like this I tend to think the simplicity is worth it. In addition to removing tons of boiler plate from the PlayerData and PlayerManager classes, you also end up with a reusable component, and you can get rid of the cyclic dependency between PlayerManager and Player.

Categories