I'm creating a Pacman clone in JavaFX, but actually the language shouldn't matter at all, it's more about the logic behind it which I can't figure out.
I've taken a video of the issue, it illustrates quite well what bug I'm facing.
I want that the Player can eat a Food (eg. the Food gets deleted from the board[][] and the score is increased). This works. But I also want the Ghosts not to be able to eat the Food, but my draws are all based off of the board[][], so I can't have a Ghost and a Food at the same place.
Not sure how it should be done, my thought was that I can create a holdingObject variable which "holds" the Food object and which is then placed back to where it came from when the Ghost moves further.
My GameView has these two important fields in it:
private static GameObject board[][];
private static LinkedHashSet<Moveable> moveableLinkedHashSet;
Both variables get filled by other methods, these work fine.
The following code block seems to contain the issue, although it may also have to be dealed with in the Line #89 (see link below).
private void executeMoveWithPosition(Position positionDest) {
GameObject ghost = this;
// TODO: Fix holding object. Currently it's a mess:
// TODO: Two consecutive foods won't be handled correctly, food gets set to wrong position at the beginning
// holdingObject gets set to the current position - possibly null, that's ok
LevelManager.getBoard()[position.getX()][position.getY()] = holdingObject;
// ghost gets inserted at the new position
LevelManager.getBoard()[positionDest.getX()][positionDest.getY()] = ghost;
// holdingObject gets emptied
holdingObject = null;
// actually move the ghost
position.setX(positionDest.getX());
position.setY(positionDest.getY());
}
Ghost.java, from which I removed methods and if clauses which didn't matter for this.
If I understand correctly, you simply don't know what data structure you should use to represent your game board, including the player, enemies and items (food).
Without investigating your code in detail, I would suggest...
You create a Tile class. The board can then be made up of those. It can save information on whether it is a traversable or not and could also hold the item that is placed upon it.
Your enemies already have a class (Ghost) that holds their position, so just make sure you have a collection of enemies that you can iterate over for rendering and game logic. This way, you don't need the board to keep track of these itself.
Optionally, have an Item (or Food) class, that you handle just like your enemies: they hold their position and you keep all of them in a collection. Again, the Tiles then don't need to keep track of these anymore.
In order to figure out if there is a Ghost or Food on a Tile, you would then need to iterate over all of these and check their position. For a game with such a small and simple level, this should be no issue.
Of course, there are other solutions and ultimately only you can know which one fits your project.
EDIT: As it turns out after exchange of some comments, solving the problem at hand was as easy as just not putting the Ghosts into the board array, as they do hold their own position. The above covers that plus is a bit more general and broad and should hopefully apply to others with similar issues as well.
Related
I am using Slick2D to make a simple game with a number of sprites. There is a player sprite which will push other object sprites around the map.
I have used an ArrayList to store all the sprite types created, but when I use the player to push a particular type of sprite (for example a wooden block) all the occurrences of that particular sprite type in that map gets updated as well. How do I specify to update that one particular wooden block rather than updating all the wooden blocks loaded in the game?
ArrayList:
private ArrayList<Sprite> sprites;
Creating all the sprites and storing them inside the ArrayList:
public static ArrayList<Sprite> loadSprites(String filename) {
ArrayList<Sprite> list = new ArrayList<>();
/*bunch of code to load the sprite*/
list.add(World.createSprite(name, x, y));
return list;
}
here types is a 2D array where I am storing all the names of the sprites according to their map coordinates, which I am getting from a csv file.
public static Sprite createSprite(String name, float x, float y) {
switch (name) {
case "player":
return new Player(x, y, "player");
case "wood":
return new Wall(x, y, "wood");
case "tile":
return new Floor(x, y, "tile");
case "wall":
return new Stone(x, y, "wall");
case "metal":
return new Target(x, y, "metal");
}
return null;
}
Thanks in advance. :)
What you need to do is to identify the object the player pushes. Let's assume you have three sprites in your list all of the type wood. From what you wrote in your question it seems like if the player starts pushing obviously all sprites get updated as well because either:
Your program can't determine what sprite exactly is supposed to be pushed.
Your program knows what sprite is supposed to be pushed but cant determine what sprite to update visually (hard to tell with your provided code)
So what you should do is to ensure that the pushing action is only performed to the object/sprite the player is interacting with. You need to have constraints to check for this interaction this constraint might be pushing a button or intersecting with that one particular sprite / object. So you could do for example the following:
Iterate through your arraylist and check with which object/sprite your player is intersecting.
If there is an intersection with an object of your list you exactly know what object that is and you could call the update, push or any other method on the object.
If you have more than one possible candidate to update you need to specify your search, for example you could only interact with objects / sprites your player is looking at.
Call the needed method of that particular one object (eg. push()).
What also might be a solution is that you should be sure about your game architecture. By this I mean that you should be certain about how your game is internally designed. Generally each gameobject in your game should have sprite and maybe a sound or certain other attributes. By this you make sure that each object has a specific sprite just for itself, so you wont get into trouble with updating any other sprites because you only can access this specific sprite by this specific object. So maybe you should consider not iterating over a list of sprites but rather iterate over a list of gameobjects in your world (I'm not sure but maybe a sprite is a gameobject for you, but a sprite is just the graphical representation of a gameobject.). Check for interaction with each of these gameobjects and in case perform a specific action. Such code could look like the following:
//inside the update method of your player
for(GameObject gameObject : world.getAllGameObjects()){
if(player.getHitbox().intersects(gameObject.hitbox())){
gameObject.update() //push, update sprite, whatever
}
}
Checking for intersection is only one solution as I already said you could also check for the pressing of a key or for a certain distance. From my understanding what is important for you is the identification of a single object and to update that single object.
It's hard to tell what exactly your problem is because I dont have insight in your entire code, but if you ensure to find the right object to interact with and also making sure that only this object is graphically updated this will work.
Beside the architecture it self the problem might be here:
if (Loader.getSpriteOfType("wood", Player.getPlayerX() - 1, Player.getPlayerY())) {
dir = DIR_LEFT;
}
I'm not sure what Loader.getSpriteOfType(..) does since I don't know how sprites or objects are entirly stored and handled in your game cycle, but I'd assume that it returns all (not only a specific one) sprites of type "wood" because it's searching for "wood" and finds all objects which "wood", but you want only the exact one which your player is interacting with so maybe you should be more specific in that if-clause (just an assumption though since I don't know your code).
Hope this helps you and gives you something to think about.
I have a setup which should be able to run multiple cameras at the same time. These cameras detect objects (not in a OO-kind of way, but a physical object, like a chair) and give these objects unique IDs.
However, I am thinking about how I should determine from which camera a motion is detected. The reason why this is needed is because if something (could be a human or an object) moves from camera1 to camera2, the ID should remain the same.
I have no solution for this, which is why I ask you.
My setup, however, looks like this.
public class Camera extends Thread{
public int cameraID;
private ImageHandling imgHandling;
public void run(){
while(true){
//read images from camera
.
.
.
imgHandling.initialize(this);
//imgHandling does all the image analysis and also handles the tracking AND the motion detection. This should not be relevant for this question.
//The identification of different movements is also done in the imageHandling.
}
}
}
This means that every camera will have its own ImageHandling class. Also, every camera is a thread, and the fetching of images is meant to be in the run-method. Also, each camera has a unique ID, i.e. if the setup has 3 cameras, the IDs will be 1, 2 and 3.
I'm programming in Java, but I don't think that a solution has to be language specific.
Based on additional information from the chat, the basic question is more along the lines of "How do we track a moving object" rather than "How do we find out which camera detected movement".
For the sake of completeness, "How do we find out which camera detected movement" is actually fairly easy (and basically covered in the question). Pass the Camera instance to the ImageHandling class.
What happens then gets more interesting...
What you really need to do once a Camera detects motion is to have a MovingObject class that keeps track of one moving object. Obviously some manager somewhere needs to keep a list of Movingobjects.
At a guess you would have something like:
class MovingObject
{
Camera firstDetectedOn;
int speed;
int directionOfMotion;
int width;
int height;
}
The manager then needs to be smart and allow merging of objects.
e.g. If an object is seem on camera1 and then a similar object (size/direction/speed) is seen on camera2, then perhaps they are the same object and not 2 separate ones. Add to that the physical layout - if cam2 is East of cam1 and the object in cam1 is moving East then it is much more likely to be the same than if the object in cam1 was moving West.
One approach may be to keep the items as unique objects and record somewhere that they "might" be the same. If the object disappears of cam1 but you know it might be the object found on cam2, then you may be able to assume it is in fact the same.
First of all, I am not sure whether it is allowed to ask this kind of question. So I am trying to create a board game and I was stuck at the implementation of generating valid moves for Piece. Here is the extract of the class diagram.
You can think this board game like chess, so we need to know the location of other pieces while generating valid moves. The problem is I have no idea how to check it. Is my class diagram wrong? Or should I check at the board every time I check a square? And how do I do that in Java? Thanks for helping.
The piece should not decide what its valid moves are, it should only be aware of where it is and how it's capable of moving. It is not responsible for that sort of logic.
The board should manage whether or not that's allowed or not (that is, it takes a piece which returns its possible moves to it, and in turn returns the valid moves).
The Piece class exposes a getPossibleMoves method that returns the list of positions it can reach:
public List<Square> getPossibleMoves(){ // might want to differentiate types of moves
Then, the board class has a getValidMoves method that takes a piece and returns its valid moves.
public List<Square> getValidMoves(Piece piece) {
return piece.getPossibleMoves().
stream(). // and filter by
filter(move -> isOnValidBoardCoordinate(move)). // can shorten
filter(move -> doesNotIntersectOtherPiece(move)).
filter(move -> otherValidation(move)).
collect(Collectors.toList());
}
I want my game to draw coins from a sprite and then my main character would be able to pick them up. I'm trying to use array list for this but i have no idea how to implement this feature. Do I make an array list of Sprites I need to draw and then reuse it ? If so , how ?
Or do I use some other function ? I'm a begginer , so sorry if this question seems odd .
I recommend using Libgdx's Array class instead of a Java ArrayList, as it is optimized for game performance.
Create an Array to hold all the active coins.
Array<Sprite> activeCoins = new Array<Sprite>();
Then create a coin pool. A pool is a helper for creating copies of something without causing garbage collection hiccups. You need to make a subclass of Pool to use. It describes how to create a new coin when one is needed.
public class CoinPool extends Pool<Sprite> {
TextureRegion coinTextureRegion;
public CoinPool(TextureRegion coinTextureRegion){
this.coinTextureRegion = coinTextureRegion;
}
protected Sprite newObject(){
return new Sprite(coinTextureRegion);
}
}
Then create an instance of CoinPool to use in your game.
Now whenever you want a new coin, pull one from the pool. It will only instantiate a new one if necessary. Otherwise, it will hand you a recycled one from earlier. And once you get it, set it's position and other parameters wherever you want it. Keep in mind it might still have old values attached to it, so if you are rotating your coins and moving them around or changing color, you'll want to be sure you reset position and rotation, and color.
Sprite newCoin = coinPool.obtain();
newCoin.setPosition(x,y,z); //as desired
newCoin.setRotation(0); //if you are rotating them
newCoin.setColor(Color.WHITE); //if you have been changing their color
activeCoins.add(newCoin); //Add your new coin to the list of active coins
And whenever you are done with a coin (when it has been collected), you need to remove it from the active coins list and return it to the pool:
for (Sprite coin : activeCoins){
boolean grabbed = isCoinGrabbed(coin); //however you want to do this
if (grabbed){
coinGrabbed(); //whatever you want to happen when a coin is grabbed
activeCoins.remove(coin);
coinPool.free(coin); //return it to the pool
}
}
And to draw them, you can just submit all the sprites currently in the activeCoins list to the sprite batch.
I recently designed a game in Java that was a 2D side scrolling role playing game. Part of the game was to walk around and pick up items like swords and armor.
The way that I accomplished loading the sprites to my game was to give a JLabel my image (which was retrieved locally on start of the game) by setting it's icon to the image.
Next I would randomly place my JLabel on the game map. I didn't use an array list, although you could if you had multiple types of swords, or coins, etc.
The array list could contain types of swords (JLabel's with their icon set to a sprite) such as a bronze, silver, and a gold sword.
Once your JLabel('s) is loading to your map you can give them a hit box and if your character moves inside the hit box then remove the JLabel from the map and into the players backpack (or whatever it is, maybe append a coin amount?).
I have made threads in the past about similar questions but because of my lack of detail the answers have not really been related to what I needed so I am going to try explain my question in as much detail as I can and hopefully it will be easier for you to understand what I require.
I watched Bucky's slick game tutorials on youtube and made a 2D Java game, the game is basically a 2D player viewed from above (birds eye view) can move around a 2D map with user key input (up, down, left, right). The map the player moves around is very small so that meant boundaries had to be set so that the player could not walk off of the map, to give you a better idea of how this was done, here is the tutorial for setting up the voundries:
http://www.youtube.com/watch?v=FgGRHId8Fn8
The video will also show you exactly what the game is like.
The problem is, these boundaries only require one axis meaning that if the player is walking down you say something like "if player gets to the coordinate (number) on the X axis change the player movement to the opposite direction so that he can not go any further."
Now this creates a problem for me because this only requires one axis so it easy to set up and understand but if you look on the video, on the map there is a house and I want my player not to be able to walk over that also but this deals with 2 dimensions, I have looked at things like rectangle collisions and have seen things relating to them in the other posts but I get confused because I am new to Java and havent really done much with it at the moment apart from watching Bucky's tutorials.
My code at the moment for my game class has got the following methods: init, render and update. So to sum it up I really just want to set up a way of not letting my player walk through the house, I will mention also (I should have mentioned it in my other threads) as I am very new to Java, could you please take a step by step method of showing me how to set up the collisions, I mean even the basics of things like making the rectangle if required.
If my code is required please tell me and I will post it as soon as possible.
Thank you in advance.
You can set up the board as a 2x2 grid of a class that has has property such as 'isBlocked'. By default the edges of the board would have this property set to true to prevent the character from walking off the edge. When you add other obstacles such as a house or a wall the grid position(s) the object occupies would also have the property set to true. Then when moving a character you just check if the grid position the character moves to has the property set to false to see if it's an allowable move. This also makes it quite trivial to save the level data so you can just load them from disk later on.
Two possible options:
Extend Shape or Rectangle or the relevant Slick objects (they should exist IMO) and just check for intersect()
Look for (x1,y1) and (x2,y2) values such that it starts outside and ends up inside.
Assuming you have intersect() methods:
//Grab the previous position
prevPosX = movingobject.X;
prevPosY = movingobject.Y;
//Update the position
movingobject.update();
//Test for collision
if(movingobject.intersects(targetobj)) {
//If it collided, move it back
movingobject.X = prevPosX;
movingobject.Y = prevPosY;
//And reverse the direction
//(might want to do other stuff - e.g. just stop the object)
movingobject.speed *= -1; //Reverse the speed
}
in this case your update class should also add one more condition to look for the house. let say the cooridnates of house(assuming rectanglular house here for other shape just change x and y values) are (x1,y1)(x1,y2)(x2,y2)(x3,y1) you have to add a condition to make sure
x value is not between x1 and x2 and at the same time y value cannot between y1 and y2.