Javafx how to put shape above another shapes - java

Trying to write a snake game. I want to mark place where the snake bites itself in red ,but the snake body overlaping it.
I tried to put the shape from the head over the body with getHead().shape.toFront() command, but it didn't work. Possibly because the snake is added to paneGame.getChildren() as a list and toFront doesn't allow changing the order in which the elements list are drawn.
I solved this problem change color overlaping body part. Can somebody advise more simply solution?
public class Draw extends Application {
Pane paneGame;
static Snake snake;
static final public int xLField = 50;
static final public int yLField = 53;
static final public int yLFieldGame = 50;
static public int sizeCell = 10;
int speed = 100;
#Override
public void start(Stage stage) {
BorderPane borderPane = new BorderPane();
paneGame = new Pane();
borderPane.setCenter(paneGame);
Scene scene = new Scene(borderPane, xLField * sizeCell, yLField * sizeCell, Color.GRAY);
setOnKey(scene);
snake = Snake.generatedSnake();
Timeline timeline = new Timeline(
new KeyFrame(Duration.millis(speed),
event -> gameProcessing()));
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
stage.setTitle("Snake");
stage.setScene(scene);
stage.show();
}
void gameProcessing() {
paneGame.getChildren().clear();
snake.move();
if (snake.getHead().hasIntersection(snake.getBody())) {
snake.snakeDead();
}
paneGame.getChildren().addAll(snake.getBodyShapes());
}
public static void main(String[] args) {
launch(args);
}
void setOnKey(Scene scene) {
scene.setOnKeyPressed(key -> {
if (key.getCode() == KeyCode.UP) snake.setDirection(Direction.UP);
if (key.getCode() == KeyCode.DOWN) snake.setDirection(Direction.DOWN);
if (key.getCode() == KeyCode.LEFT) snake.setDirection(Direction.LEFT);
if (key.getCode() == KeyCode.RIGHT) snake.setDirection(Direction.RIGHT);
});
}
}
enum Direction {
UP, DOWN, LEFT, RIGHT
}
public class Snake {
private final ArrayList<Body> body;
private Body head;
public ArrayList<Shape> getBodyShapes() {
ArrayList<Shape> shapeListFromBody = new ArrayList<>();
for (Body body : this.body) {
shapeListFromBody.add(body.getShape());
}
return shapeListFromBody;
}
public ArrayList<Body> getBody(){return body;}
Body getHead() {
return head;
}
public void move() {
int x = head.getX();
int y = head.getY();
switch (direction) {
case UP -> y -= 1;
case DOWN -> y += 1;
case LEFT -> x -= 1;
case RIGHT -> x += 1;
}
body.add(0, new Body(x, y));
Cell.cellPool.remove((body.get(body.size() - 1).cellId));
body.remove(body.size() - 1);
head = body.get(0);
}
public Snake() {
direction = Direction.RIGHT;
this.body = new ArrayList<>();
for (int i = 0; i < 10; i++) {
body.add(new Body(Draw.xLField/2 - i, Draw.yLFieldGame/2));
}
head = this.body.get(0);
}
private Direction direction;
public static Snake generatedSnake(){
return new Snake();
}
public void snakeDead(){
getHead().shape.setFill(RED);
getHead().shape.toFront();
/*for(Body body: body){
if(getHead().hasIntersection(body)) {
body.shape.setFill(RED);
}
}*/
}
public void setDirection(Direction direction) {
this.direction = direction;
}
static class Body extends Cell {
private final Shape shape;
public Body(int x, int y) {
super(x, y);
shape = new Rectangle(getPixelsX(), getPixelsY(), size, size);
shape.setFill(GREEN);
}
public Shape getShape() {
return shape;
}
}
}
public class Cell {
int x;
int y;
String cellId;
final int size = Draw.sizeCell;
public static HashSet<String> cellPool = new HashSet<>();
public int getPixelsX() {
return x * size;
}
public int getPixelsY() {
return y * size;
}
public Cell(int x, int y) {
this.x = x;
this.y = y;
this.cellId = x + "_" + y;
Cell.cellPool.add(this.cellId);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public boolean hasIntersection(Cell otherCell) {
return otherCell != this && this.cellId.equals(otherCell.cellId);
}
public boolean hasIntersection(List<? extends Cell> cells) {
for (Cell otherCell : cells) {
if (this.hasIntersection(otherCell)) {
return true;
}
}
return false;
}
}
public class Cell {
int x;
int y;
String cellId;
final int size = Draw.sizeCell;
public static HashSet<String> cellPool = new HashSet<>();
public int getPixelsX() {
return x * size;
}
public int getPixelsY() {
return y * size;
}
public Cell(int x, int y) {
this.x = x;
this.y = y;
this.cellId = x + "_" + y;
Cell.cellPool.add(this.cellId);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public boolean hasIntersection(Cell otherCell) {
return otherCell != this && this.cellId.equals(otherCell.cellId);
}
public boolean hasIntersection(List<? extends Cell> cells) {
for (Cell otherCell : cells) {
if (this.hasIntersection(otherCell)) {
return true;
}
}
return false;
}
}

I solved the problem using setViewOrder with -1 parameter (before I used a positive value)

Related

Finding if the x and y coordinate is within a view is enclosed by two intersecting rectangles, in java

Say I have this view with two subviews A and B, A and B has a color property mColor,
I want a function in the parent view that has this signature: int getColor(int x, int y), which for any given x and y coordinate, return the color at that position, if the x and y coordinates land and the two shapes are overlapped, return the average color of A and B
The problem I am running into is i see myself doing a lot of conditional checks, checking if A is left of B or if A is right of B etc. I feel like I am missing some key intuition
I have a Point class that handles the coordinates"
public class Point {
private final int mX;
private final int mY;
public Point(int mX, int mY) {
this.mX = mX;
this.mY = mY;
}
public int getX() {
return mX;
}
public int getY() {
return mY;
}
}
Here is my subview class:
public class Chart {
private int mColor;
private Point mTopLeft;
private Point mBottomRight;
public Point getTopLeft() {
return mTopLeft;
}
public Point getBottomRight() {
return mBottomRight;
}
public Chart(int mColor, Point topLeft, Point bottomRight) {
this.mColor = mColor;
this.mTopLeft = topLeft;
this.mBottomRight = bottomRight;
}
public int getColor() {
return mColor;
}
public Point getTopRightCorner() {
return new Point(getBottomRight().getX(), getTopLeft().getY());
}
public Point getBottomLeftCorner() {
return new Point(getTopLeft().getX(), getBottomRight().getY());
}
}
My parent view class:
public class View {
private Chart mChartA;
private Chart mChartB;
public View(Chart chartA,
Chart chartB) {
mChartA = chartA;
mChartB = chartB;
}
public boolean doChartsOverlap() {
boolean isOverlapped = true;
if(isChartALeftOfChartBInX() || isChartARightOfChartBInX()) {
isOverlapped = false;
}
if(isChartABottomOfChartBInY() || isChartATopOfChartBInY()) {
isOverlapped = false;
}
return isOverlapped;
}
public final boolean isChartALeftOfChartBInX() {
return mChartA.getBottomRight().getX() <= mChartB.getTopLeft().getX();
}
public final boolean isChartARightOfChartBInX() {
return mChartA.getTopLeft().getX() >= mChartB.getBottomRight().getX();
}
public final boolean isChartATopOfChartBInY() {
return mChartA.getBottomRight().getY() <= mChartB.getTopLeft().getY();
}
public final boolean isChartABottomOfChartBInY() {
return mChartA.getTopLeft().getY() >= mChartB.getBottomRight().getY();
}
public void setChartA(Chart mChartA) {
this.mChartA = mChartA;
}
public void setChartB(Chart mChartB) {
this.mChartB = mChartB;
}
}
Logically, you want to test if the point is in both rectangles; so test if it is in one rectangle and also in the other rectangle. Everything else about whether one rectangle is above, below, left or right of the other is a red herring.
Add this method to the Chart class (use < instead of <= if you only want to paint the interiors):
public boolean contains(Point p) {
return mTopLeft.getX() <= p.getX() && p.getX() <= mBottomRight.getX()
&& mTopLeft.getY() <= p.getY() && p.getY() <= mBottomRight.getY();
}
And this method to the View class:
public int getColor(Point p) {
boolean inA = mChartA.contains(p), inB = mChartB.contains(p);
if(inA && inB) {
// ...
} else if(inA) {
// ...
} else if(inB) {
// ...
} else {
// ...
}
}
You can then overload public int getColor(int x, int y) to return getColor(new Point(x, y)).
Rectangle r1 = new Rectangle(x1, y1, width1, height1 );
Rectangle r2 = new Rectangle(x2, y2, width2, height2);
if ( r1.contains( x3, y3 ) && r2.contains( x3, y3 ) ) {
// (x3,y3) is in both rectangles
}

How can I have access to one item's variables in another class that is not related with it?

I'm new to java and i was searching about this for a long time. How can I have access to the item's b variables in class Player??(the cod i'm posting is a part of my full programm so don't mind if you see methods or variables that are not declared in the following code)
import java.util.Random;
public abstract class Player {
private int x, y;
private String name;
private int pNumber;
private int mLine;
private int tLine;
private boolean possession;
private int c;
private int f = 0;
private int i = 0;
public int getPlx() {
return x;
}
public void setPlx(int x) {
this.x = x;
}
public int getPly() {
return y;
}
public void setPly(int y) {
this.y = y;
}
public String getPName() {
return name;
}
public void setPName(String name) {
this.name = name;
}
public int getPNum() {
return pNumber;
}
public void setPNum(int pNumber) {
this.pNumber = pNumber;
}
public int getMLine() {
return mLine;
}
public void setMLine(int mLine) {
this.mLine = mLine;
}
public int getLine() {
return tLine;
}
public void setTLine(int tLine) {
this.tLine = tLine;
}
public boolean getPos() {
return possession;
}
public void setPos(boolean possession) {
this.possession = possession;
}
private Random rand = new Random();
public void Move() { //me8odos metakinisis
c = rand.nextInt(2);
if (c == 0) {
y++;
} else {
y--;
}
}
public void Pass() {
if (this.possession == true) {
c = rand.nextInt(10);
while ((f == 0) && (i < 10)) {
if (main.barcelona.get(i).name == this.name) {}
}
}
}
public abstract void SpecialMove();
}
public class Ball {
private int x, y;
private Player formerP = null;
private Player currentP = null;
public Ball(int x, int y, Player formerP, Player currentP) {
this.x = x;
this.y = y;
this.formerP = formerP;
this.currentP = currentP;
}
public int getBX() {
return x;
}
public void setBX(int x) {
this.x = x;
}
public int getBY() {
return y;
}
public void setBY(int y) {
this.y = y;
}
void Assign(Player playerP) {
int px = playerP.getPlx();
if (this.currentP == null) {
if (((this.x - px <= 1) || (px - this.x) <= 1)
&& ((this.x - px <= 1) || (px - this.x) = 1)) {
this.currentP = playerP;
this.formerP.possession = false;
playerP.possession = true;
if (this.currentP.team == this.formerP.team) {
int pass = this.currentP.getPasses();
pass++;
this.currentP.setPasses(pass);
} else {
int mistake = this.currentP.getMistakes();
mistake++;
this.currentP.setMistakes(mistake);
}
}
}
this.formerP = this.currentP;
this.currentP = null;
this.formerP = null;
}
}
try BallClassName.getX();
You may have to make getX static
If you don't want to instantiate the class Ball in the Player class and you would like to ensure that all players are playing with the one and only ball, then consider making Ball a Singleton.
In software engineering, the singleton pattern is a design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system.
public class Ball {
private static Ball singletonBall;
private int x;
private int y;
private Player formerP;
private Player currentP;
public static Ball getSingletonBall() {
if(singletonBall == null){
singletonBall = new Ball();
}
return singletonBall;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public Player getFormerP() {
return formerP;
}
public void setFormerP(Player formerP) {
this.formerP = formerP;
}
public Player getCurrentP() {
return currentP;
}
public void setCurrentP(Player currentP) {
this.currentP = currentP;
}
}
If there is something that you need inside Player that you will be using often that won't change throughout the life of the Player object (or sub object in your case), then you might as well pass it to a local variable through the Player constructor.
Let's assume Item B is the Ball and you have a Ball class.
So in player (or sub player) declare your object you want access to:
class Player {
Ball ball;
public Player(Ball ball) {
this.ball = ball;
}
Or if it's just something that you'll be using infrequently or something that's value will change (more likely with a ball), then create a method to perform what you need on the Player object.
class Player {
.
.
.
.
.
public void dribble(Ball ball) {
// do something with the ball
ball.setPosition(10, 20);
ball.update();
}
}
Then whatever instantiates Player can access that method.
public static void main(String[] args) {
Player player = new Player();
Ball ball = new Ball();
player.dribble(ball);
}

How can I get value from one class to another without extends it?

I am newbie in programming and may be this will be stupid question but here it is:
This is my class board:
public class Board {
public static final int COLOR_WHITE = 1;
public static final int COLOR_BLACK = 2;
PlayingPiece[][] board;
private boolean isFirstMove;
private int color;
public Board() {
this.setBoard(new PlayingPiece[8][8]);
this.isFirstMove = true;
this.initializePieces();
}
// Initialize the chess pieces
public void initializePieces() {
for (int i = 0; i < 8; i++) {
board[1][i] = new Pawn(1, i, COLOR_WHITE);
}
for (int i = 0; i < 8; i++) {
board[6][i] = new Pawn(6, i, COLOR_BLACK);
}
board[0][0] = new Rook(0, 0, COLOR_WHITE);
board[0][7] = new Rook(0, 7, COLOR_WHITE);
board[7][0] = new Rook(7, 0, COLOR_BLACK);
board[7][7] = new Rook(7, 7, COLOR_BLACK);
board[0][1] = new Knight(0, 1, COLOR_WHITE);
board[0][6] = new Knight(0, 6, COLOR_WHITE);
board[7][1] = new Knight(7, 1, COLOR_BLACK);
board[7][6] = new Knight(7, 6, COLOR_BLACK);
board[0][2] = new Officer(0, 2, COLOR_WHITE);
board[0][5] = new Officer(0, 5, COLOR_WHITE);
board[7][2] = new Officer(7, 2, COLOR_BLACK);
board[7][5] = new Officer(7, 5, COLOR_BLACK);
board[0][3] = new Queen(3, 0, COLOR_WHITE);
board[0][4] = new King(4, 0, COLOR_WHITE);
board[7][3] = new Queen(7, 3, COLOR_BLACK);
board[7][4] = new King(7, 4, COLOR_BLACK);
this.printBoard();
}
public boolean play(int color, int fromX, int fromY, int toX, int toY) {
boolean isTrue = false;
// Check if this is the first turn and only white can move
if (isFirstMove && color == COLOR_WHITE) {
isTrue = true;
} else if (isFirstMove && color == COLOR_BLACK) {
return false;
}
// check if player plays 2 times in a raw and if you move the piece from
// current possition
if (color == this.color || (toX == fromX && toY == fromY)) {
return false;
}
isTrue = true;
if (isTrue == true) {
this.isFirstMove = false;
// Check if player plays with his own color
if (((board[fromX][fromY]).getColor() != color)) {
return false;
}
// Check the isLegal movement of every chess piece
if ((board[fromX][fromY]).move(toX, toY)) {
board[toX][toY] = board[fromX][fromY];
board[fromX][fromY] = null;
}
this.printBoard();
}
return isTrue;
}
public PlayingPiece[][] getBoard() {
return board;
}
public void setBoard(PlayingPiece[][] board) {
this.board = board;
}
I want to get the value of this:
board[toX][toY];
OK after that here is the other my class for chess pieces:
public class PlayingPiece {
public static final int COLOR_WHITE = 1;
public static final int COLOR_BLACK = 2;
public static final char BLACK_PAWN = '\u265F';
public static final char BLACK_ROOK = '\u265C';
public static final char BLACK_KNIGHT = '\u265E';
public static final char BLACK_BISHOP = '\u265D';
public static final char BLACK_QUEEN = '\u265B';
public static final char BLACK_KING = '\u265A';
public static final char WHITE_PAWN = '\u2659';
public static final char WHITE_ROOK = '\u2656';
public static final char WHITE_KNIGHT = '\u2658';
public static final char WHITE_BISHOP = '\u2657';
public static final char WHITE_QUEEN = '\u2655';
public static final char WHITE_KING = '\u2654';
public static final char NO_PIECE = ' ';
private int x, y;
private boolean isAlive;
private int color;
private char symbol;
protected PlayingPiece (int newX, int newY, int newColor) {
this.setX(newX);
this.setY(newY);
this.color = newColor;
this.isAlive = true;
}
protected PlayingPiece(int newX, int newY) {
this.setX(newX);
this.setY(newY);
}
protected PlayingPiece() {
}
public int getX() {
return x;
}
public void setY(int y) {
this.y = y;
}
public int getY() {
return y;
}
public void setX(int x) {
this.x = x;
}
protected boolean moveIsLegal (int newX, int newY) {
boolean isLegal = false;
if ((0 <= newX && newX <= 7) && (0 <= newY && newY <= 7)){
isLegal = true;
}
return isLegal;
}
public boolean move (int newX, int newY) {
if (moveIsLegal(newX, newY)) {
setX(newX);
setY(newY);
return true;
}
return false;
}
public int getColor() {
return color;
}
public boolean isAlive() {
return isAlive;
}
public void setAlive(boolean isAlive) {
this.isAlive = isAlive;
}
public char getSymbol() {
return symbol;
}
public void setSymbol(char symbol) {
this.symbol = symbol;
}
}
And now this is Pawn class which extends PlayingPieces:
public class Pawn extends PlayingPiece {
private boolean hasBeenMoved;
protected Pawn(int newX, int newY, int color) {
super(newX, newY, color);
this.hasBeenMoved = false;
if (color == COLOR_BLACK) {
this.setSymbol(BLACK_PAWN);
} else {
this.setSymbol(WHITE_PAWN);
}
}
#Override
public boolean move(int newX, int newY) {
if (super.move(newX, newY)) {
this.hasBeenMoved = true;
return true;
}
return false;
}
#Override
protected boolean moveIsLegal(int newX, int newY) {
boolean isLegal = false;
int newPositionX = newX - this.getX();
if (super.moveIsLegal(newX, newY)) {
if ((hasBeenMoved == false)
&& (((Math.abs(newPositionX) <= 2) && getY() == newY))) {
isLegal = true;
} else if ((hasBeenMoved == true)
&& (((Math.abs(newPositionX) <= 1) && getY() == newY)) && isValidTrace(newX, newY)) {
isLegal = true;
}
}
return isLegal;
}
public boolean isValidTrace(int newX, int newY) {
PlayingPiece[][] array = new PlayingPiece[8][8];
if (array[newX][newY].equals(new PlayingPiece())) {
return false;
}
return true;
}
}
Now in this method isValidTrace() I want to get the value of board[toX][toY] from class Board and how can I do this without any extends here ?
Another solution (assuming you won't need multiple Board instances) is making board static.
public static PlayingPiece[][] board;
Then you can access it from your Pawn class using Board.board
I do not know if I understand your question but..
If you have got 2 classes A and B instead of using inheritance you can use aggregation. For example, you want to use some method from object B in class A you go with:
class A {
private B b;
}
and then inside methods of class A you go with b.nameOfTheMethod()
You can create a method to return the array and call it in the class you want the data.
public PlayingPiece getBoard()
{
return board;
}

How come the collision detection only works sometimes?

I am creating an android app and I am creating a game and the droid has to be able to bounce off the walls and the edge of the screen. Here is my update method in my MainGamePanel.java file where I call the collision detection.
It works when it just has to bounce off the edge of the screen. However when I try to get it bounce off the wall objects it sometimes works. When it doesn't, it goes through the wall sometimes, although this only happens when it moves up and down. It also sometimes gets stuck in the wall. How would I modify the collision detection so I won't have these issues. Any help would be much appreciated.
public void update()
{
// check collision with right wall if heading right
if (droid.getSpeed().getxDirection() == Speed.DIRECTION_RIGHT
&& droid.getX() + droid.getBitmap().getWidth() / 2 >= getWidth()) {
droid.getSpeed().toggleXDirection();
}
// check collision with left wall if heading left
else if (droid.getSpeed().getxDirection() == Speed.DIRECTION_LEFT
&& droid.getX() - droid.getBitmap().getWidth() / 2 <= 0) {
droid.getSpeed().toggleXDirection();
droid.getSpeed().setYv(0);
}
// check collision with bottom wall if heading down
else if (droid.getSpeed().getyDirection() == Speed.DIRECTION_DOWN
&& droid.getY() + droid.getBitmap().getHeight() / 2 >= getHeight()) {
droid.getSpeed().toggleYDirection();
droid.getSpeed().setXv(0);
}
// check collision with top wall if heading up
else if (droid.getSpeed().getyDirection() == Speed.DIRECTION_UP
&& droid.getY() - droid.getBitmap().getHeight() / 2 <= 0) {
droid.getSpeed().toggleYDirection();
droid.getSpeed().setXv(0);
}
for (int i = 0 ; i < listOfWs.length ; i++)
{
if (droid.getX() +(droid.getBitmap().getWidth()/2)+1 > listOfWs [i].giveLeft ()
&& droid.getX()-(droid.getBitmap().getWidth()/2)-1 < listOfWs [i].giveRight ()
&& droid.getY()+(droid.getBitmap().getHeight()/2)+1 > listOfWs [i].giveTop ()
&& droid.getY()-(droid.getBitmap().getHeight()/2)-1 < listOfWs [i].giveBottom () )
{
if(droid.getSpeed().getYv()==0){
droid.getSpeed().toggleXDirection();//Takes the speed and multiplies it by -1 so it changes direction
}
else{
droid.getSpeed().toggleYDirection();
}
}
}
// Update the lone droid
droid.update();
}
Here is my droid.java file that I used.
public class Droid {
private Bitmap bitmap; // the actual bitmap
private int x; // the X coordinate
private int y; // the Y coordinate
public Speed speed;
public Droid(Bitmap bitmap, int x, int y) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
speed= new Speed();
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void draw(Canvas canvas) {
canvas.drawBitmap(bitmap, x - (bitmap.getWidth() /2), y - (bitmap.getHeight() / 2), null);
}
public void update() {
x += (int)(speed.getXv() * speed.getxDirection());
y += (int)(speed.getYv() * speed.getyDirection());
}
public Speed getSpeed(){
return speed;
}
}
This is the speed.java file.
public class Speed {
public static final int DIRECTION_RIGHT = 4;
public static final int DIRECTION_LEFT = -4;
public static final int DIRECTION_UP = -4;
public static final int DIRECTION_DOWN = 4;
private float xv = 1; // velocity value on the X axis
private float yv = 1; // velocity value on the Y axis
private int xDirection = DIRECTION_RIGHT;
private int yDirection = DIRECTION_DOWN;
public Speed() {
this.xv = 1;
this.yv = 1;
}
public Speed(float xv, float yv) {
this.xv = xv;
this.yv = yv;
}
public float getXv() {
return xv;
}
public void setXv(float xv) {
this.xv = xv;
}
public float getYv() {
return yv;
}
public void setYv(float yv) {
this.yv = yv;
}
public int getxDirection() {
return xDirection;
}
public void setxDirection(int xDirection) {
this.xDirection = xDirection;
}
public void setRight() {
xDirection = DIRECTION_RIGHT;
}
public void setLeft() {
xDirection = DIRECTION_LEFT;
}
public void setUp() {
yDirection = DIRECTION_UP;
}
public void setDown() {
yDirection = DIRECTION_DOWN;
}
public int getyDirection() {
return yDirection;
}
public void setyDirection(int yDirection) {
this.yDirection = yDirection;
}
// changes the direction on the X axis
public void toggleXDirection() {
xDirection = xDirection * -1;
}
// changes the direction on the Y axis
public void toggleYDirection() {
yDirection = yDirection * -1;
}
}
in the update method, in for circulation, it seems you make your logical operation there, would you make it more specific?

Please Help:Grid of JButtons in a JPanel shows one JButton instead of 400 when GridLayout(20,20) is used

Thank you for trying to help me.
I want to create a grid of 20*20 squares.It is for my A-Star Algorithm Demo.
For experiment purpose I wrote the following code:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class Node extends JButton {
Node(){
super();
setSize(new Dimension(20,20));
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0,0,getHeight(),getWidth());
}
}
public class Map
{
static final int n = 20;
JPanel p;
public JPanel init() {
p=new JPanel();
p.setLayout(new GridLayout(n, n));
p.setBackground(Color.black);
p.setFont(new Font("SansSerif", Font.BOLD, 24));
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
p.add(new Node());
}
}
return p;
}
}
public class Display extends JApplet{
public void init(){
Map m=new Map();
add(m.init());
}
}`
I got the following output:
Please load the code & check.I cannot post image since I lack 10 reputation
However,when I am trying to add the experiment code with my original code for the demo
it is not showing the desired output.My original code is as follows:
import java.util.ArrayList;
import javax.swing.*;
import java.awt.*;
public class Node extends JButton implements Comparable<Node> {
/* Nodes that this is connected to */
private Node north;
private Node east;
private Node south;
private Node west;
private ArrayList<Node> neighbourList;
private boolean visited;
private float g;
private float h;
private Node parent;
private int x;
private int y;
private boolean isObstacle;
private boolean isStart;
private boolean isGoal;
Node(int x, int y) {
super();
neighbourList = new ArrayList<Node>();
this.x = x;
this.y = y;
this.visited = false;
this.g = Integer.MAX_VALUE;
this.isObstacle = false;
this.isStart = false;
this.isGoal = false;
}
public void setNorth(Node north) {
//replace the old Node with the new one in the neighbourList
if (neighbourList.contains(this.north))
neighbourList.remove(this.north);
neighbourList.add(north);
//set the new Node
this.north = north;
}
public void setEast(Node east) {
//replace the old Node with the new one in the neighbourList
if (neighbourList.contains(this.east))
neighbourList.remove(this.east);
neighbourList.add(east);
//set the new Node
this.east = east;
}
public void setSouth(Node south) {
//replace the old Node with the new one in the neighbourList
if (neighbourList.contains(this.south))
neighbourList.remove(this.south);
neighbourList.add(south);
//set the new Node
this.south = south;
}
public void setWest(Node west) {
//replace the old Node with the new one in the neighbourList
if (neighbourList.contains(this.west))
neighbourList.remove(this.west);
neighbourList.add(west);
//set the new Node
this.west = west;
}
public ArrayList<Node> getneighbourList() {
return neighbourList;
}
public boolean isVisited() {
return visited;
}
public void setVisited(boolean visited) {
this.visited = visited;
}
public float getG() {
return g;
}
public void setG(float f) {
this.g = f;
}
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public float getH() {
return h;
}
public void setH(float h) {
this.h = h;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public boolean isObstacle() {
return isObstacle;
}
public void setObstacle(boolean isObstacle) {
this.isObstacle = isObstacle;
}
public boolean isStart() {
return isStart;
}
public void setStart(boolean isStart) {
this.isStart = isStart;
}
public boolean isGoal() {
return isGoal;
}
public void setGoal(boolean isGoal) {
this.isGoal = isGoal;
}
public boolean equals(Node node) {
return (node.x == x) && (node.y == y);
}
public int compareTo(Node otherNode) {
float thisTotalDistanceFromGoal = h + g;
float otherTotalDistanceFromGoal = otherNode.getH() + otherNode.getG();
if (thisTotalDistanceFromGoal < otherTotalDistanceFromGoal)
return -1;
else if (thisTotalDistanceFromGoal > otherTotalDistanceFromGoal)
return 1;
else
return 0;
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0,0,getHeight()-1,getWidth()-1);
}
}
public class Map {
private int mapWidth;
private int mapHeight;
private ArrayList<ArrayList<Node>> map;
private int startLocationX = 0;
private int startLocationY = 0;
private int goalLocationX = 0;
private int goalLocationY = 0;
private int[][] obstacleMap;
private JPanel p;
private Logger log = new Logger();
Image buffer;
Map(int mapWidth, int mapHeight, int[][] obstacleMap) {
this.mapWidth = mapWidth;
this.mapHeight = mapHeight;
this.obstacleMap = obstacleMap;
createMap();
log.addToLog("\tMap Created");
registerEdges();
log.addToLog("\tMap Node edges registered");
}
private void createMap() {
Node node;
map = new ArrayList<ArrayList<Node>>();
for (int x=0; x<mapWidth; x++) {
map.add(new ArrayList<Node>());
for (int y=0; y<mapHeight; y++) {
node = new Node(x,y);
if (obstacleMap[x][y] == 1)
node.setObstacle(true);
map.get(x).add(node);
}
}
}
/**
* Registers the nodes edges (connections to its neighbours).
*/
private void registerEdges() {
for ( int x = 0; x < mapWidth-1; x++ ) {
for ( int y = 0; y < mapHeight-1; y++ ) {
Node node = map.get(x).get(y);
if (!node.isObstacle()){
if (!(y==0))
node.setNorth(map.get(x).get(y-1));
if (!(x==mapWidth))
node.setEast(map.get(x+1).get(y));
if (!(y==mapHeight))
node.setSouth(map.get(x).get(y+1));
if (!(x==0))
node.setWest(map.get(x-1).get(y));
}
}
}
}
public ArrayList<ArrayList<Node>> getNodes() {
return map;
}
public void setObstacle(int x, int y, boolean isObstacle) {
map.get(x).get(y).setObstacle(isObstacle);
}
public Node getNode(int x, int y) {
return map.get(x).get(y);
}
public void setStartLocation(Node start) {
map.get(startLocationX).get(startLocationY).setStart(false);
map.get(start.getX()).get(start.getY()).setStart(true);
startLocationX = start.getX();
startLocationY = start.getY();
}
public void setStartLocation(int x, int y) {
map.get(startLocationX).get(startLocationY).setStart(false);
map.get(x).get(y).setStart(true);
startLocationX = x;
startLocationY = y;
}
public void setGoalLocation(Node goal) {
map.get(goalLocationX).get(goalLocationY).setGoal(false);
map.get(goal.getX()).get(goal.getY()).setGoal(true);
goalLocationX = goal.getX();
goalLocationY = goal.getY();
}
public void setGoalLocation(int x, int y) {
map.get(goalLocationX).get(goalLocationY).setGoal(false);
map.get(x).get(y).setGoal(true);
goalLocationX = x;
goalLocationY = y;
}
public int getStartLocationX() {
return startLocationX;
}
public int getStartLocationY() {
return startLocationY;
}
public Node getStartNode() {
return map.get(startLocationX).get(startLocationY);
}
public int getGoalLocationX() {
return goalLocationX;
}
public int getGoalLocationY() {
return goalLocationY;
}
public Node getGoalLocation() {
return map.get(goalLocationX).get(goalLocationY);
}
public float getDistanceBetween(Node node1, Node node2) {
//if the nodes are on top or next to each other, return 1
if (node1.getX() == node2.getX() || node1.getY() == node2.getY()){
return 1;
} else { //if they are diagonal to each other return diagonal distance: sqrt(1^2+1^2)
return (float) 1.4;
}
}
public int getMapWidth() {
return mapWidth;
}
public int getMapHeight() {
return mapHeight;
}
public JPanel init(){
int n=20;
p=new JPanel();
p.setLayout(new GridLayout(n, n));
p.setSize(400,400);
p.setFont(new Font("SansSerif", Font.BOLD, 24));
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
p.add(map.get(j).get(i));
}
}
return p;
}
public void clear() {
startLocationX = 0;
startLocationY = 0;
goalLocationX = 0;
goalLocationY = 0;
createMap();
registerEdges();
}
}
public class Display extends JApplet
{
private static int[][] M = {{0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0},
{0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0},
{0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,0,0,0},
{0,1,1,1,1,0,0,1,1,0,0,0,0,0,1,1,0,0,0,0},
{0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,0,0},
{1,1,1,1,1,1,1,1,0,0,0,0,1,1,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0},
{0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0},
{0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
public void init()
{
JRootPane rootPane = this.getRootPane();
rootPane.putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE);
Map m=new Map(20,20,M);
add(m.init());
}
}
This is the output that I got from the above code:
Please load the code & check.I cannot post image since I lack 10 reputation
Within the Node class, the methods getParent, getX, and getY are overriding methods in the super class JButton. When the layout manager calls getX and getY your methods get called which confuses the layout manager. Rename your three methods to anything else, for example nodeGetParent, nodeGetX, and nodeGetY.
The lesson to learn here is that you must be careful when extending a class that you don't accidentally override the super class' methods.

Categories

Resources