I've been learning Java by experimenting with a little "game" that started with just trying to make a ball jump. I've got 3 classes (JumpingBall3, BallSprite3, & Floor) and have achieved a gravity of some sorts, a jump that works consistently, and hit detection against floors to stop the ball falling infinitely. With this last point I've spotted a potential issue with future development. Right now I have two floors created by JumpingBall3 ("floor1" & "platform") and I detect collision within the BallSpite3 using the following code:
public boolean collision()
{
if (game.floor1.getBounds().intersects(getBounds()) || game.platform.getBounds().intersects(getBounds())) {
onFloor = true;
}
else
{
onFloor = false;
}
return onFloor;
}
If I were to keep adding more floors or platforms that "if" condition is quickly going to spiral out of control in terms of length. Is there a way to create a method that cycles through all visible Floor objects created in my JumpingBall3 class?
I've posted the full code online here, it seemed a bit lengthy to include within this post.
The simplest thing to do is to keep all the objects that you want to check in a Collection like for example a List, then iterate over this List.
So for example, here a good choice would be to use a collection of Floor, on which we iterate to check if we have a collision with one of them.
public boolean collision() {
boolean onFloor = false;
Rectangle rectangle = getBounds();
for (Floor floor : floors) {
if (floor.getBounds().intersects(rectangle)) {
onFloor = true;
break;
}
}
return onFloor;
}
Assuming that you use Java 8 , you could rely on the Stream API to do the same thing as next:
public boolean collision() {
Rectangle rectangle = getBounds();
return floors.stream().map(Floor::getBounds).anyMatch(rectangle::intersects);
}
An approachable solution to this problem is to have your "game world" contain a list of entities (where an entity can be a ball or wall or any other in game object), and have some mechanism that detects which entities are near which other entities. This would end up calling some type of entity.checkCollision(neighborEntity) method.
You still need to have different behaviors for colliding with different entities. You can do this by having the base Entity class have some common attributes you can turn off or on, or store behaviors that you can apply directly to the collided entity.
// within some game loop, check for collisions
for (Entity entity : collidableEntities)
{
ball.checkCollision(entity);
}
Your classes could look like this to have programmed behaviors.
public Entity
{
public void applyCollisionBehaviorTo(Ball ball) { // Override to do something}
public void onCollision() { // Override to do something }
public collidesWith(Entity neighbor) { // your collision math }
public void checkCollision(Entity neighbor)
{
if (collidesWith(neighbor))
{
onCollision()
}
}
}
public Wall extends Entity
{
#Overide
public void applyCollisionBehaviorTo(Ball ball)
{
ball.reverseDirection();
}
}
public Ball extends Entity
{
#Overide
public void onCollision(Entity collidingEntity)
{
collidingEntity.applyCollisionBehaviorTo(this);
}
}
create a list with all objects. then use a loop over all the object you want to detect (excepting the one that making the detection of course)
Related
Following Scenario:
Classes:
GamePlayScene (Game logic and collision detection)
Obstacle (has the Rect getObstacleBounds() method to return Bounds)
ObstacleManager (has the LinkedList of obstacle objects)
I want to access the Boundaries (an android.Rect) of an obstacle. All obstacles will be stored into a LinkedList.
Now in the running game I want to access the getObstacleBounds() method in my GameplayScene Class but the problem is that I can't access the obstacle object directly but I obviously have to cycle through all my Objects in the LinkedList in my ObstacleManager.
Due to that I thought I have to also implement a Rect getObstacleBounds() in my Obstacle Manager, from where I cycle through every obstacle in my List and return that Rect.
Is this the right way to do so? I am fairly new to accessing objects and their methods in a LinkedList
If not: How would I implement access to such methods?
Here is my idea what I thought cold work / be the right way.
(Not compilable, more or less pseudo code)
GameplayScene.java
private ObstacleManager obstacleManager;
public GameplayScene() {
obstacleManager = new ObstacleManager();
obstacleManager.addObstacle(new Obstacle(...));
}
public void hitDetection() {
//get the Boundaries of obstacle(s) for collision detection
}
Obstacle.java
//...
public Rect getObstacleBounds() {
return obstacleBounds;
}
ObstacleManager.java
LinkedList<Obstacle> obstacles = new LinkedList<>();
public void update() { //example method
for (Obstacle o : obstacles){
o.update();
}
}
public Rect getObjectBounds() {
return ...
//how do I cycle through my objects and return each Bounds Rect?
}
In the end, depends of what you want to do in hitDetection
If you just want to check if a hit happened
In this case, you can just receive the list of Rect and check if any hit happened
GameplayScene.java
public void hitDetection() {
ArrayList<Rect> listOfBounds = obstacleManager.getObstacleBounds();
for(Rect bound : listOfBounds) {
// Do you stuff
// Note the here, you are receiving a list of Rects only.
// So, you can only check if a hit happened.. but you can't update the Obstacles because here, you don't have access to them.
// Nothing stops you of receiving the whole list of items if you want to(like the reference of ObstacleManager.obstacles).
}
}
ObstacleManager.java
public ArrayList<Rect> getObjectBounds() {
// You can also return just an array.. like Rect[] listToReturn etc
ArrayList<Rect> listToReturn = new ArrayList(obstacles.size());
for (Obstacle item : obstacles) {
listToReturn.add(item.getObjectBounds);
}
return listToReturn;
}
If you need to update some info on the Obstacle that was hit
In this case, you can transfer the hitDetection logic to you ObstacleManager (I'm assuming you check coordinates X and Y to check if obstacle was hit):
GameplayScene.java
public void hitDetection(int touchX, int touchY) {
Obstacle objectHit = obstacleManager.getObstacleTouched(int touchX, int touchY);
if (objectHit != null) {
objectHit.doStuffAlpha();
objectHit.doStuffBeta();
} else {
// No obstacle was hit.. Nothing to do
}
}
ObstacleManager.java
public Obstacle getObstacleTouched(int touchX, int touchY) {
Obstacle obstacleToReturn = null;
for (Obstacle item : obstacles) {
if(item.wasHit(touchX, touchY) {
obstacleToReturn = item;
break;
}
}
return listToReturn;
}
There are several ways to achieve what you want. Some better than others etcIn the end, depends of what you want to do exactly.
I'm making a game and i have timer loop and in the timer i have some features which allow flowers to spawn. Once the flowers hit the age of lets say 300 they turn into deadflwoers and the image changes, but once they hit the age of 400 then i want them to disappear of the scene but i dont know where i'm going wrong in order to do so.
AnimationTimer timer = new AnimationTimer() {
ArrayList<GameObject>DeadFlowers = new ArrayList<GameObject>();
#Override
public void handle(long now) {
// TODO Auto-generated method stub
gc.drawImage(img1, 0, 0, canvas.getWidth(), canvas.getHeight());
if(count++>60) {
flowers.add(new SpawnFlowers(gc, rnd.nextInt(600), rnd.nextInt(550)));
count = 1;
}
for(GameObject obj : Hive) {
obj.update();
}
for(GameObject obj : flowers) {
((SpawnFlowers)obj).grow();
}
for(GameObject obj : DeadFlowers) {
((SpawnFlowers)obj).removeFlowers();
DeadFlowers.remove(obj);
}
for(GameObject obj : characterList) {
obj.update();
}
}
};
my Flowers class:
class SpawnFlowers extends GameObject implements FlowerIF {
FlowerIF delegate;
int age= 0;
public SpawnFlowers(GraphicsContext gc, double x, double y) {
super(gc, x, y);
img = new Image("/res/rose.png");
update();
delegate = this;
// TODO Auto-generated constructor stub
}
public void grow() {
age+=1;
if(age == 300)
delegate = new DeadFlower(gc, x, y);
delegate.update();
}
public void removeFlowers() {
if (age == 400) {
delegate.update();
}
}
}
You have a list DeadFlowers but you never add() something.
Therefore your loop
for(GameObject obj : DeadFlowers) {
((SpawnFlowers)obj).removeFlowers();
DeadFlowers.remove(obj);
}
will never run.
You could for example do
public void grow() {
age+=1;
if(age == 300) {
delegate = new DeadFlower(gc, x, y);
DeadFlowers.add(delegate);
}
delegate.update();
}
I am not really sure what you want to achieve with this method. You probably want to remove the condition if that is just code to repaint.
public void removeFlowers() {
if (age == 400) {
delegate.update();
}
}
Most like, your actual problem is here:
for(GameObject obj : DeadFlowers) {
((SpawnFlowers)obj).removeFlowers();
DeadFlowers.remove(obj);
}
You turned your flowers into a DeadFlower when it has age 300. I assume that you also add that new DeadFlower object to your list of dead flowers. In the next game loop, the above code calls checks: is the age 400, if so ... do nothing. Next, your code will removes that dead flower object from the dead flower list!
In other words: when the flower gets to 300, you turn it into a dead flower. Right afterwards, you remove that dead flower from the list of dead flowers. Thus that list will always be emptied immediately.
Long story short: your whole logic is quite screwed up. You have to step back and clearly outline (for yourself first) what buckets you have, and how you want to process them. As in:
if (age == 400) {
delegate.update();
}
This code does nothing specific for that 400 case. Compare it to the 300 case. There you create a new object at least. Something changes. But in the 400 case, well, you update. What is that supposed to do?!
Beyond that: it seems you are adding your dead flowers to that list implicitly, within the constructor of that class. Super bad idea. The class that holds that list of dead flowers should be the only place where new flowers are added to that list, or removed. I assume your DeadFlowers class knows that list, and adds new instances to that list. That is dead wrong.
And another minor thing: ArrayList<GameObject>DeadFlowers = new ArrayList<GameObject>(); should better be List<GameObject> deadFlowers = new ArrayList<>(); . There is no need to express the specific type (ArrayList) on the left hand side, there is no need to use the generic type on the right hand side. And of course, DeadFlowers violates java naming conventions (should start lower case).
If I'm not wrong, after your flowers is dead it doesn't seems like you change there age So why should the get to age of 400 ?
I am doing a JavaFX application and I have a board with multiple shape (circles and rectangle) added to a Pane. I don't want circle to be moved accross rectangle.
Circle are allowed to be dragged using Mouse Event (OnMousePressed,Dragged,Released) while rectangle are not allowed to move.
I am using this code to detect when my circle are colliding with the rectangles.
private void checkIntersection(Shape block) {
boolean collisionDetected = false;
for (Shape static_bloc : nodes) {
if (static_bloc != block) {
Shape intersect = Shape.intersect(block, static_bloc);
if (intersect.getBoundsInLocal().getWidth() != -1) {
collisionDetected = true;
}
}
}
if (collisionDetected) {
System.out.println("Collision detected");
} else {
System.out.println("Collision non deteted");
}
}
What I need to do is make my rectangle impossible to drag over while dragging circles. I don't want to send the shape back to his initial location.
Is there a way to do this using intersect or am I missing something?
It's not so easy to answer. You can have a class for instance GameObject. This class contains your Shape. In this GameObject class you have your drag&drop logic. Then u will have a class GameObjectManager which contains list of all GameObjects. And every instance of GameObject will have a reference to this GameObjectManager so knows about all GameObjects as well. So in your move logic you can check if there is some collision between specific GameObject types and if, u can stop moving.
For collision assessment class GameObject contains method like:
protected boolean isInCollision() {
for (GameObject gameObject : gameObjectManager.getAllGameObjects()) {
if (!gameObject.equals(this)) {
if (getView().getBoundsInParent().intersects(gameObject.getView().getBoundsInParent())) {
return true;
}
}
}
return false;
}
In your case you need to loop just some types of objects in this isInCollision method.
Just wanted to share my solution.
I wanted to check the node before the movement was done. So I modified the previous solution, to create the following.
Node Class: I am working with a custom Node class that extends Label. The methods used here are those inherited from Label.
private boolean hasNoCollision(Node dragged, double x, double y) {
// For each node
for (Node n : nodes) {
// If it is not the same, and future position overlaps
if (!n.equals(dragged) &&
n.getBoundsInParent().intersects(x, y, dragged.getWidth(), dragged.getHeight())) {
// Then prevent collission
return false;
}
}
// Otherwise all is good!
return true;
}
so i have JXButton[][] array (gridLayout) and each JXButton holds an icon, a piece,which player belongs to and has a mouseListener.
I am currently trying to make the Stratego Game(Two Players-I handle both).
I set up the icons,pieces and how a piece should move alright.
Now i wish to make it play by turn.
For example when is Player1 Turn i need all Players2' pieces to change icon to Hidden(hidden.png) and vice versa.
I have tried something like this.
tmp1, tmp2 are Icon arrays
pieceimgsB,R hold the Hidden Icon
allbuttons is my JXButton[][] array
public void makeHidden(int iD){
if(iD==1){
for (int i=0;i<8;i++){
for(int y=0;y<10;y++){
if(allbuttons[i][y].getPlayerID()==iD){
tmp1[i][y]=allbuttons[i][y].getIcon();
allbuttons[i][y].setIcon(new ImageIcon(pieceimgsB[12]));
}
}
}
}
else if(iD==2){
for (int i=0;i<8;i++){
for(int y=0;y<10;y++){
if(allbuttons[i][y].getPlayerID()==iD){
tmp2[i][y]=allbuttons[i][y].getIcon();
allbuttons[i][y].setIcon(new ImageIcon(pieceimgsR[12]));
}
}
}
}
}
public void restoreHidden(int iD){
if(iD==1){
for (int i=0;i<8;i++){
for(int y=0;y<10;y++){
if(allbuttons[i][y].getPlayerID()==iD){
allbuttons[i][y].setIcon(tmp1[i][y]);
}
}
}
}
else if(iD==2){
for (int i=0;i<8;i++){
for(int y=0;y<10;y++){
if(allbuttons[i][y].getPlayerID()==iD){
allbuttons[i][y].setIcon(tmp2[i][y]);
}
}
}
}
}
I my mind makeHidden Player2 pieces hidden when its Players1 turn.
And restoreHidden should change back the Icons when its Players2 turn.
If these two methods seem ok , where my problem lies is how to implement the turns.
I must say that (When i click on a JXButton and then click on another one, the
piece moves on the board as it should). I tried having a flag in my mouseListener that when one actually moves the turn changes, but i cant make it work by turns.
I have wrote this :
public void letsPlay(){
switch (turn){
case 1:
getsb().makeHidden(2);
//getsb().restoreHidden(1);
if(getsb().getPlayerMoved()==true){
setTurn(2);
}
break;
case 2:
getsb().makeHidden(1);
//getsb().restoreHidden(2);
if(getsb().getPlayerMoved()==true){
setTurn(1);
//;
}
break;
}
}
I need to know if these two methods seem ok according to what they should do and a little insight on how to get it to work by turns.
Should i have the getPlayerMoved() (which returns the flag in the mouseListener in a while outside the switch case)?
Maybe i am tired and i dont see it but any insight would be helpful.
If someone needs it i can provide my mouseListener Code too although its a bit messy.
This seems to be an XY problem, the main point is not to specialize your listener to manage such behavior (and other inherent behaviors) but how to design something that is modular and easily maintainable.
I'd suggest you to try to workaround your problem by thinking how you could design your game and UI structure. Let's make a simple example:
First of all you have a game piece which has a type and a player, so why don't you use a specific object type for this? Eg:
class PieceType {
String name;
String iconName;
}
class Player {
String name;
}
class Piece {
PieceType type;
Player owner;
class BoardCell {
Piece piece;
}
Then you surely need a Board class able to manage the game board, eg:
class Board {
private BoardCell [][] pieces = new Piece[10][10];
public BoardCell cellAtPiece(int x, int y) { return pieces[x][y]; }
/* other functions */
}
Finally you should have a Game class which manages the whole thing, eg:
class Game {
Board board;
Player[] players = new Player[2];
Player currentPlayer;
Player getCurrentPlayer() { return currentPlayer; }
/* other methods, eg turn advance, check for correct position, eat piece etc */
}
Now you reached a point in which you have the structure of the game, and you can think about the UI, which should rely on the Game instance without the need of additional inputs (and Game shouldn't even know about the UI). You could extend a JXButton and provide custom behavior, eg:
class BoardButton extends JXButton {
final private Game game;
final private BoardCell cell;
public BoardButton(Game game, int x, int y) {
this.game = game;
this.cell = game.cellAtPiece(x,y);
}
public void refreshIcon() {
if (cell.piece == null) { setIcon(null); }
else if (cell.piece.owner != game.getCurrentPlayer()) { setIcon(hidden); }
else setIcon(cell.piece.type.icon);
}
/* other utilities, like checking if a piece can be moved from here for current player and such */
Mind, I didn't answer directly to your question, but I explained some tools which would allow it to be solved easily together with all problems that you could find in implementation.
I should to implmenets an application to control a race of car.
So in a race I have for example 5 car. I want to know the position of this car in every turn, the last time, and best round for all car. Now I wanto to know what structure of data is the best solution for this.
I have create this object:
package Auto;
import java.security.Timestamp;
public class Macchina {
Integer corsia;
Integer giro;
Timestamp ultimoTempo;
Timestamp migliorTempo;
public void setCorsia(Integer corsia) {
this.corsia = corsia;
}
public void setGiro(Integer giro) {
this.giro = giro;
}
public Timestamp getUltimoTempo() {
return ultimoTempo;
}
public void setUltimoTempo(Timestamp ultimoTempo) {
this.ultimoTempo = ultimoTempo;
}
public Timestamp getMigliorTempo() {
return migliorTempo;
}
public void setMigliorTempo(Timestamp migliorTempo) {
this.migliorTempo = migliorTempo;
}
public Macchina(int c, int g)
{
this.corsia=c;
this.giro=g;
}
public int getCorsia(){
return corsia;
}
public int getGiro(){
return giro;
}
}
This class is used to stored the information for the car in the race.
Keep in mind that A car has a speed.
The track has the distance and cars on it.
Your object design should reflect that.
Depending on how many properties a car has, you might not need a car object.
If you plan on extending your car racing program, you might want an abstract vehicle class. Especially if tracks become complicated, and cars become highly varied.
If you just want to find something like the position of a car at a discrete time and when a car reaches a certain distance then following might work for your purposes.
Pseudo code:
track {
int length, time, Maxtime;
array<int> carSpeeds, carPositions;
main(){
Maxtime=100;
for(time=1; time<MaxTime; time++){
for(int j= 0; j < carSpeeds.size(); j++){
carPositions[j] = time*careSpeed // reset for each lap.
// if position is greater than track length, you might have a winner or a tie.
}
}
}
}
You can add in a max distance and other things.
If you want to eventually model warp capable space ship racing to various waypoints, submarine racing between underwater cities, and dirtbike racing with shortcuts, the code should have high cohesion, and low coupling. But the first of many iterations would probably look similar to the above.