Giving objects the ability to recreate - java

I'm putting together a game in Java. Basically, you need to avoid oncoming game objects. I want to recreate these objects once they have left the screen.
I'm trying to adhere to design patterns, I currently have a GameObject Factory that is responsible for creating the game worlds' objects. All of these objects are derived from an abstract GameObject. I was considering creating a Recreatable interface that exposed a recreate method, that recreate method then expects a GameObject Factory which in turn returns another random version of that game object.
Like this
public class Ghost extends GameObject implements Recreatable, Movable {
private int x;
private int y;
private int dx;
private int dy;
public Ghost(int x, int y) {
this.x = x;
this.y = y;
dx = 3;
dy = 5;
}
public void move() {
// move logic ...
}
public GameObject recreate(GameObjectFactory gameObjectFactory) {
return gameObjectFactory.getInstance("ghost");
}
}
I could then just check if it's an instance of re-creatable and if so add that recreated object to my list of moving game objects instead of doing a switch case/if else block of all the possible game objects.
This is an example of how it would look with the recreate method
public class GameSurfaceView extends SurfaceView implements Runnable {
private ArrayList<Movable> movables;
private GameObjectFactory gameObjectFactory;
public GameSurfaceView(Context context) {
super(context);
gameObjectFactory = new GameObjectFactory(this);
}
#Override
public void run() {
while (isRunning) {
if (!myHolder.getSurface().isValid())
continue;
ListIterator<Movable> movableListIterator = movables.listIterator();
while (movableListIterator.hasNext()) {
Movable movable = movableListIterator.next();
movable.move(canvas);
if (movable.hasPassedScreen()) {
if (movable instanceof Recreatable) {
Recreatable recreatable = (Recreatable) movable;
movableListIterator.set(recreatable.recreate(gameObjectFactory));
}
}
}
myHolder.unlockCanvasAndPost(canvas);
}
}
}
The if/else would look more like this for the run method
while (movableListIterator.hasNext()) {
Movable movable = movableListIterator.next();
movable.move(canvas);
if (movable.hasPassedScreen()) {
if (movable instanceof GhostObject) {
movableListIterator.set(gameObjectFactory.getInstance("ghost"));
} else if (movable instanceof WitchObject) {
movableListIterator.set(gameObjectFactory.getInstance("witch"));
} else if (movable instanceof VampireObject) {
movableListIterator.set(gameObjectFactory.getInstance("vampire"));
} else if (movable instanceof ZombieObject) {
movableListIterator.set(gameObjectFactory.getInstance("zombie"));
}
}
}
Is this a bad way of going about it?

Related

using constructor from another class in java to create objects in separate classs

how can I use the constructor from another class in java to make an object through a method in separate class. For example below is a constructor in a player class
public class Player extends Entity {
public Player(int maxEnergy, int x, int y) {
this.maxEnergy = maxEnergy;
this.energy = maxEnergy;
carryingGhost = false;
xPos = x;
yPos = y;
}
Which I want to use and create objects (player) through a method called
private Player createPlayer() {
and the above method is in separate class as
public class GameEngine {
**The method must return a Player object that represents the player in the
game. it must set the maxEnergy for the player, and the
X and Y positions corresponding to a tile position in the current level.
I have tried to initialize player within method with parameters and
without parameters as**
Player player = new Player(int maxEnergy, int x, int y);
this.player.getEnergy();
this.player.getMaxEnergy();
this.player.setPosition(x, y);
return player;
}
But it give errors.Any help will be appreciated.I am quite close to assume its not possible to have created objects like this.
below I share the complete game engine which is working with other classes as well .
import java.awt.Point;
import java.util.ArrayList;
import java.util.Random;
public enum TileType {
WALL, FLOOR1, FLOOR2, BANK, BREACH, DOOR;
}
public static final int LEVEL_WIDTH = 35;
public static final int LEVEL_HEIGHT = 18;
private Random rng = new Random();
private int levelNumber = 1; //current level
private int turnNumber = 1;
private GameGUI gui;
private TileType[][] level;
private ArrayList<Point> spawnLocations;
private Player player;
private Ghost[] ghosts;
public GameEngine(GameGUI gui) {
this.gui = gui;
}
private TileType[][] generateLevel() {
//YOUR CODE HERE
return null; //change this to return the 2D arrayof TileType
//values that you create above
}
private ArrayList<Point> getSpawns() {
ArrayList<Point> s = new ArrayList<Point>();
// YOUR CODE HERE
return s;
}
private Ghost[] addGhosts() {
//YOUR CODE HERE
return null; //change this to return an array of ghost objects
}
**/**
* Creates a Player object in the game. The method instantiates
* the Player class and assigns values for the energy and position.
* The first version of this method should use fixed a fixed position
for the player to start, by setting fixed X and Y values when calling
the constructor in the Player class. The second version of this method
should use the spawns ArrayLis to select a suitable location to spawn
the player and removes the Point from the spawns ArrayList. This will
prevent the Player from being added to the game inside a wall, bank or
breach for example.
#return A Player object representing the player in the game
*/**
private Player createPlayer() {
//YOUR CODE HERE
return null; //change this to return a Player object
}
public void movePlayerLeft() {
}
public void movePlayerRight() {
}
public void movePlayerUp() {
}
public void movePlayerDown() {
}
private void hitGhost(Ghost g) {
}
private void moveGhosts() {
}
private void moveGhost(Ghost g) {
}
private void cleanDefeatedGhosts() {
}
private void nextLevel() {
}
private void placePlayer() {
}
public void doTurn() {
cleanDefeatedGhosts();
moveGhosts();
gui.updateDisplay(level, player, ghosts);
}
public void startGame() {
level = generateLevel();
spawnLocations = getSpawns();
ghosts = addGhosts();
player = createPlayer();
gui.updateDisplay(level, player, ghosts);
}
}
I have used below method and its not showing error so far.
private Player createPlayer() {
int energy=player.getEnergy();
int maxEnergy=player.getMaxEnergy();
int xPos=player.xPos;
int yPos=player.yPos;
return new Player(maxEnergy,xPos,yPos);
}
The following should do it:
private Player createPlayer() {
int defaultMaxEnergy = 10; // Whatever value it should have
int initialX = 1; // Whatever value it should have
int initialY = 1; // Whatever value it should have
return new Player(defaultMaxEnergy, initialX, initialY);
}
Since the values are not in your descriptions I just selected a random number but you can pick whatever integers you want and that makes sense.
Does something like this work for your case?
public class GameEngine {
private Player createPlayer() {
return new Player(1,2,3);
}
}
Add a default no-args constructor in the player class. Once you create a constructor with Arg, java will not auto provide default one.
You have already declared Player
private Player player;
So you must not try to reinitialize using same variable name, rather
private Player createPlayer() {
Player newPlayer = new Player();
// set the different props of the Player obj
return newPlayer ;
}
What is the error which you are facing ? Can you share that ?

Java Polymorphism Subclass Functioncall

I am pretty sure I can find an answer on Stackoverflow for this question. Unfortunately I do not know the specific formulation to do so.
Given following code I have the problem, that I want to avoid typechecks. The comments will probably describe it better than my words.
Right now I am trying to have a shapesystem where every shape can collide with every possible specificShape.
CollisionClass:
public class ShapeCollision {
public static boolean intersects(RectShape rectShape1, RectShape rectShape2) { return true; }
public static boolean intersects(LineShape lineShape, RectShape rectShape) { return true; }
public static boolean intersects(RectShape rectShape1, Shape shape) { return true; }
public static boolean intersects(LineShape lineShape, Shape shape) { return true; }
public static boolean intersects(Shape shape1, Shape shape2){ return true; }
}
ShapeClasses:
public class RectShape extends Shape {
Vector size;
public RectShape(Vector pos, Vector size) {
super(pos);
this.size = size;
}
#Override
public boolean intersects(IShape shape) {
return ShapeCollision.intersects(this, shape);
}
}
public class LineShape extends Shape {
Vector pos2;
public LineShape(Vector pos, Vector pos2) {
super(pos);
this.pos2 = pos2;
}
#Override
public boolean intersects(IShape shape) {
return ShapeCollision.intersects(this, shape);
}
}
public class Shape implements IShape {
protected Vector pos;
public Shape(Vector pos) {
this.pos = pos;
}
#Override
public Vector getPos() {
return pos;
}
#Override
public void setPos(Vector pos) {
this.pos = pos;
}
#Override
public void move(Vector movementAmount) {
pos.add(movementAmount);
}
#Override
public boolean intersects(IShape shape) {
return ShapeCollision.intersects(this, shape);
}
}
Here is the confusing part for me:
Shape rect = new RectShape(new Vector(0,0), new Vector(20,20));
Shape rect2 = new RectShape(new Vector(0,0), new Vector(20,20));
Shape line = new LineShape(new Vector(0,0), new Vector(20,20));
//Since I am saving shape and no specific shapetype, it will pass shape and pick the specific superFunction
//Right now it calls the intersects(RectShape rectShape1, Shape shape) function due to calling it through the shape variable
rect.intersects(rect2);
//This calls the intersects(LineShape lineShape, Shape shape) function
rect.intersects(line);
//This calls the intersects(Shape shape1, Shape shape2) function
ShapeCollision.intersects(rect, line);
How can I achieve it without specifying the type of the variable, that the 'correct' function with the subclass parameter is called. (e.g.: (LineShape lineShape, RectShape rectShape))
I do not want to make any typechecks in those functions and call the functions specifically, but to use some DesignPatters or something similar if possible :)
What you want is NOT achievable without some type checking inside the functions or some explicit casting done on the Shape instances before passing them to the function calls.
Of course you could declare the objects references with the specific classes, but i guess that is not really helpful.

How to clone an object from an array of objects with different types

I've got this code:
int width = 1280;
int height = 720;
List<ElectronicDevice> devices = new ArrayList<ElectronicDevice>();
class ElectronicDevice {
int x;
int y;
// ...
}
class EClock extends ElectronicDevice {
int hz;
EClock(int x, int y, int clock) {
this.x = x;
this.y = y;
this.hz = hz;
}
// ...
}
class EBulb extends ElectronicDevice {
EClock(int x, int y) {
this.x = x;
this.y = y;
}
// ...
}
class ToolbarElement {
ElectronicDevice dev;
ToolbarElement(ElectronicDevice dev) {
this.dev = dev;
}
public void addDevice() {
// somehow add a copy of `dev` to the `devices` list
}
}
List<ToolbarElement> elements = new ArrayList<ToolbarElement>();
elements.add(new EClock(width/2, height/2, 5));
elements.add(new EBulb(width/2, height/2));
elements.get(0).addDevice();
I need to add a copy of ToolbarElement dev to devices, but I don't know how. It needs to be a deep copy. In the program I don't know the constructors of all devices, I'd like to just deep clone dev into devices.
I tried adding implements Cloneable to the ElectronicDevice class, but then I would need to add that and a clone() method to every class that extents ElectronicDevice.
After adding the implements Cloneable to ElectronicDevice it mostly worked, but all the clocks had desynchronized after adding more than 1 of them (this is a graphical application in Processing, every class that extends ElectronicDevice can have a behavior() method which specifies how it behaves and the clock oscillates between 0 and 1 with the frequency of hz Hz.)
This was my addDevice() implementation:
// In ElectronicDevice
class ElectronicDevice implements Cloneable {
// ...
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
// end of class code
}
// In ToolbarElement
class ToolbarElement {
// ...
public void addDevice() {
try { devices.add((ElectronicDevice)object.clone()); }
catch (CloneNotSupportedException e) { e.printStackTrace(); }
}
// end of class code
}
Is there any solution that wouldn't require modifying every single class that extends ElectronicDevice?

Java: How can I make a ball behave as a bouncing and elastic ball?

I have two classes BouncingBall and another one called ElasticBall. Both classes extends BallImpl which implements an interface called Ball.
public interface Ball {
int DEFAULT_RADIUS = 50;
int radius();
Point center();
void update();
}
public class BouncingBall extends BallImpl {
public static final int MOVEMENT_SPEED = 12;
static final int DOWN = 1;
static final int UP = -1;
private int direction;
BouncingBall(int x, int y, int direction) {
super(x, y);
this.direction = direction;
}
#Override
public void update() {
direction = reverseDirectionIfNecessary();
y = move();
}
private int reverseDirectionIfNecessary() {
if (movingTooHigh() || movingTooLow()) {
return switchDirection();
}
return this.direction;
}
private boolean movingTooLow() {
return y + radius >= BallWorld.BOX_HEIGHT && movingDown();
}
private boolean movingTooHigh() {
return y - radius <= 0 && movingUp();
}
private int switchDirection() {
return movingDown() ? UP : DOWN;
}
private int move() {
return y + (MOVEMENT_SPEED * direction);
}
private boolean movingDown() {
return direction == DOWN;
}
private boolean movingUp() {
return direction == UP;
}
}
public class ElasticBall extends BallImpl {
public static final int GROWTH_RATE = 2;
static final int GROW = 1;
static final int SHRINK = -1;
private int growthDirection;
ElasticBall(int x, int y, int radius, int growthDirection) {
super(x, y, radius);
this.growthDirection = growthDirection;
}
#Override
public void update() {
growthDirection = reverseGrowthDirectionIfNecessary();
radius = next();
}
private int reverseGrowthDirectionIfNecessary() {
if (growingTooBig() || shrinkingTooSmall()) {
return switchDirection();
}
return this.growthDirection;
}
private boolean shrinkingTooSmall() {
return radius <= 0 && shrinking();
}
private boolean growingTooBig() {
return radius >= Ball.DEFAULT_RADIUS && growing();
}
private int switchDirection() {
return growing() ? SHRINK : GROW;
}
private int next() {
return radius + (GROWTH_RATE * growthDirection);
}
private boolean shrinking() {
return growthDirection == SHRINK;
}
private boolean growing() {
return growthDirection == GROW;
}
}
I need to create a BouncingElasticBall which combines the behavior of the BouncingBall and the ElasticBall classes. I have poor knowledge in OOP, and I know Java does not allow multiple inheritance, so how can I solve this problem?
Thanks in advance.
One way you could approach this is to not extend BallImpl, but make sort-of plugins. Like this:
public class BallImpl implements Ball {
List<BallBehavior> behaviors = ...
#Override
public void update() {
behaviors.forEach(behavior -> behavior.update(this));
}
...
}
public interface BallBehavior {
void update(BallImpl ballImpl);
}
And then, just write your elastic and bouncing logic as behaviors.
Once you diverge hierarchies there's no way to merge them in java.
It's a design matter: if you know that ElasticBall and BouncingBall may be combined together, you should create two interfaces Elastic and Bouncing, both extending interface Ball, with common methods valid for both.
Then the common method implementations may be set into a common abstract class, let's say AbstractBall. At this point you can finally detail your three implementations:
ElasticBall extends AbstractBall implements Elastic
BouncingBall extendis AbstractBall implements Bouncing
ElasticBouncingBall extends AbstractBall implements Elastic, Bouncing
In this way you'll be able to control what to do in each method, reuse code for common stuff (in the abstract class).
You can use interfaces that allows multiple inheritance. Make the interface for each ballElasticBall and BouncingBall and implement both of them in BouncingElasticBall.

Avoid internal getters/setters - Game

I working on a Game. The View, Thread and the Engine are done. Now I going into how to, for example, set Coordinates to my Bitmap.
I have successfully done that using getters/setters-method. I've been reading around the web there the most of the good game developers say that "make your member variable public" and all that stuff.
Since I read the Avoid Internal Getters/Setters section at http://developer.android.com/guide/practices/design/performance.html, I started to wonder: How I can change my Coordinates-class to achieve this without "setters" for example?
Now my Coordinates-class look like:
package com.mygame.mygame;
public class Coordinates {
int x;
int y;
Coordinates instance = null;
public Coordinates getInstance(){
if(instance == null){
instance = new Coordinates();
}
return instance;
}
public Coordinates() {
}
public int getX() {
return x;
}
public void setX(int value) {
x = value;
}
public int getY() {
return y;
}
public void setY(int value) {
y = value;
}
}
How should I change my code to achieve this? Method calls are expensive, but I still have no idea how to restructure my current code without getters and setters.
UPDATED
public GameEngine getInstance(){
if(instance == null){
instance = new GameEngine(resources,view);
}
return instance;
}
UPDATE 2
GameEngine
static Resources res;
static GameView view;
static GameEngine instance = null;
public static GameEngine getInstance(Resources localResources, GameView localView){
view = localView;
res = localResources;
if(instance == null){
instance = new GameEngine(); //Init-stuff in the GameEngine
}
return instance;
}
and my GameView
static GameEngine engine;
public GameView(Context localContext) {
//Other stuff
engine = GameEngine.getInstance(context.getResources(), this);
//Other stuff
}
Thanks in advance!
You seem to misunderstand the word "internal". That document is more telling you that you should not do for example:
public Coordinates(int x, int y) {
setX(x);
setY(y);
}
but more so
public Coordinates(int x, int y) {
this.x = x;
this.y = y;
}
In other words, avoid using getters/setters in the same class as where they're definied.
Your current class isn't doing that anywhere by the way. Only the getInstance() method is just pretty pointless in this context. I'd get rid of it.
public is the default for members, unless otherwise specified. Just don't use the getter or setter for x and y.

Categories

Resources