Java free spot pieces - java

I have a piece that needs to get surrounded by other grey pieces if the coordinate around the piece is not used.
I tried to do the following:
public List<Piece> boardPiece(){
List<Piece> boardPieces = new ArrayList<>();
for (Piece pieces : listToPiece) {
if (pieces.getCoordinate() != null){
boardPieces.add(pieces);
}
}
return boardPieces;
}
public List<Coordinate> getSurroundings() {
List<Coordinate> surroundings = new ArrayList<>();
for (Piece boardpieces : boardPiece()) {
for (Coordinate coordinate : makeDirections()) {
surroundings.add(new Coordinate(boardpieces.getCoordinate().getRow() + coordinate.getRow(), boardpieces.getCoordinate().getColumn() + coordinate.getColumn()));
}
}
return surroundings;
}
public List<Coordinate> makeDirections(){
directions.add(new Coordinate(1,-1));
directions.add(new Coordinate(-1,1));
directions.add(new Coordinate(-1,0));
directions.add(new Coordinate(1,0));
directions.add(new Coordinate(0,-1));
directions.add(new Coordinate(0,1));
return directions;
}
A boardpiece is a piece that is on the board and that has a coordinate. A boardpiece who doesn't have a coordinate shouldn't be surrounded by other grey pieces. In my drawer the following I have written the following code:
public void drawEmptyPieces() {
for (Coordinate emptyPiece : emptyPieces) {
EmptyPiece emptyPiece1 = new EmptyPiece(new Coordinate(emptyPiece.getRow(), emptyPiece.getColumn()));
emptyPiece1.setFill(Color.LIGHTGRAY);
emptyPiece1.setStroke(Color.BLACK);
gameField.getChildren().add(emptyPiece1);
}
}
I tried to avoid that grey pieces are drawed over boardpieces:
public void drawEmptyPieces() {
for (Coordinate emptyPiece : emptyPieces) {
for (Piece pieceObjects : pieces){
if (pieceObjects.getCoordinate().getRow() != emptyPiece.getRow() && pieceObjects.getCoordinate().getColumn() != emptyPiece.getRow()){
EmptyPiece emptyPiece1 = new EmptyPiece(emptyPiece);
emptyPiece1.setFill(Color.LIGHTGRAY);
emptyPiece1.setStroke(Color.BLACK);
gameField.getChildren().add(emptyPiece1);
}
}
}
}
But this code doesn't work.

I don't know that you have provided enough information to answer your problem. But here are a few thoughts.
makeDirections() is either broken (missing declaration of directions local variable), or broken because it keeps adding 6 new Coordinate objects to a directions field each time it is called. In either case, it is doing more work than needed. Consider instead:
private final static List<Coordinate> directions;
static {
List<Coordinate> dirs = new ArrayList<>();
dirs.add(new Coordinate(1,-1));
dirs.add(new Coordinate(-1,1));
dirs.add(new Coordinate(-1,0));
dirs.add(new Coordinate(1,0));
dirs.add(new Coordinate(0,-1));
dirs.add(new Coordinate(0,1));
directions = Collections.immutableList(dirs);
}
public static List<Coordinate> makeDirections() { // or getDirections()
return directions;
}
getSurroundings() looks like it can (will?) add the same Coordinate to surroundings multiple times. If a piece is at [5,5], and another piece is at [7,5], you will add [5,5]+[1,0] and [7,5]+[-1,0] to surroundings. There may even be a piece at [6,5] which will also add [5,5] and [7,5] to surroundings as well.
Instead ...
Ensure Coordinate implements equals and hashCode, so two Coordinate objects with the same row and column are equal, and both hash to the same value. Then, in getSurroundings() use:
Set<Coordinate> surroundings = new HashSet<>();
So that surroundings only contains each coordinate once. Before returning, you could remove all "occupied" coordinates from the surroundings.
for (Piece piece : pieces) {
surroundings.remove(piece.getCoordinate());
}
You could return the set instead of a list, or if you want to keep it as a list:
return new ArrayList<>(surroundings);
Without "surroundings" containing duplicates and coordinates where existing pieces are, you may find drawing your board much, much easier.
Unless you game board is infinite in extents, you will be creating Coordinate objects beyond the edges of you board. Consider adding the method getNeighbours() to the Coordinate class:
class Coordinate {
public Collection<Coordinate> getNeighbours() {
List<Coordinate> neighbours = new ArrayList<>(6);
for (Coordinate dir: getDirections()) {
Coordinate n = new Coordinate(getRow() + dir.getRow(), getColumn() + dir.getColumn());
if (n.isValid()) {
neighbours.add(n);
}
}
return neighbours;
}
}
Then getSurroundings becomes a little simpler, with:
for (Piece boardpieces : boardPiece()) {
surroundings.addAll(boardpieces.getCoordinate().getNeighbours());
}
Without any "surroundings" being off the board.
A "Direction" is not a Coordinate. They are used for different things. A Coordinate is a position on the board, where as your "Direction" is a relative offset. The board may have constraints that row and column values must be between (say) 0 and 20; your "Direction" objects have negative row and column values; which would violate those constraints. This means you could not add proper checking and throw new IllegalArgumentException("Invalid coordinate") in the constructor of Coordinate if given a bad value.
I would create a new class for Direction objects. Actually, I'd use enum Direction { ... }. Then Direction.values() would return the set of all directions -- you wouldn't need to create the set yourself. This is a much larger change than other ones, and may have consequences beyond the small subset of code you provided. A good change, but perhaps a lot of work.
Hope that helps.

Related

How do I detect the collision between the bullet and the enemy? [duplicate]

This question already has answers here:
Ball to Ball Collision - Detection and Handling
(15 answers)
Closed last year.
I'm creating a shooter game and im unsure on how to make it detect the fact that the bullet has hit the enemy. This is the boolean that was given
boolean isShot(Bullet bullet) //is shot sequence
{
if (bullet!=null)
{
if (abs(this.x - bullet.x) < 20 &&
abs(this.y - bullet.y) < 20)
return true;
}
return false;
}
and this is the part where i try make it detect the collision and make the enemy disappear but it keeps giving me errors no matter what i try.
import java.util.ArrayList;
int score;
Player p1;
Enemy[] e= new Enemy[4];
ArrayList<Bullet> bullet = new ArrayList<Bullet>();
void setup()
{
size (1000, 1000);
p1= new Player(500,5, 40);
e[1]= new Enemy(100,1000,3);
e[2]= new Enemy(500,800,3);
e[3]= new Enemy(700,700,3);
// b1= new Bullet(500,500,-5);
}
void draw()
{
background(255);
p1.render();
e[1].render();
e[1].move();
e[2].render();
e[2].move();
e[3].render();
e[3].move();
text("Score:" + score,50,50);
for (Bullet b: bullet)
{
b.render();
b.move();
}
if (e[1].isShot(Bullet))
{
e[1]=null;
}
Its at the bottom of this peice of code. When i try put bullet in lowercase it says "the function isShot() expects paramaters like "isShot(Bullet)" but when i capitalise the B in bullet it tells me that bullet isnt a variable.
"bullet" with lowercase b is an array of Bullets, but isShot() expects a single Bullet object. And "Bullet" with capital B is not a variable, but a class (I suppose).
So, you either need to create another object of Bullet or use one of the Bullet object in your "bullet" ArrayList.
You are almost there.
I suggest you use more meaningful names for your parameters.
First of all, you have to populate the ArrayList bullet in your setup() or elsewhere you want in your code.
After this, if you want to check that condition using isShot function you should pass to it an instance of an Object, not the class Object itself.
This can be easily achieved by including the function in your for loop.
While it is always good to practice, I suggest you to first understand the basics of the language and then move to more complex examples (custom classes, arrays iterations and so on).
void setup()
{
size (1000, 1000);
p1= new Player(500,5, 40);
e[1]= new Enemy(100,1000,3);
e[2]= new Enemy(500,800,3);
e[3]= new Enemy(700,700,3);
bullet.add(new Bullet(500,500,-5)); // e.g. to populate array
}
void draw()
{
background(255);
p1.render();
e[1].render();
e[1].move();
e[2].render();
e[2].move();
e[3].render();
e[3].move();
text("Score:" + score,50,50);
for (Bullet b: bullet)
{
b.render();
b.move();
if (e[1].isShot(b)) // now you can use b which is an instance of Bullet
{
e[1]=null;
}
}

How to switch between the classes, in JavaFX?

I have a game template which has two classes as its levels.
The game has a player, enemies, treasure chests, and walls.
When I run the program, it loads Level 1, successfully. I have designed the code so if a certain condition is met, Level 2 must load. Now, Level 2 loads. But certain elements from Level 1 remain on screen, ignoring certain elements from Level 2.
To be exact:
From Level 2, it loads the player's initial coordinates, the treasure chests, and the final destination, ignoring the enemies and the walls.
It brings with itself from Level 1 to Level 2: the walls, the treasure chests, and the enemies. The latter two are in a frozen state. They don't function.
//Instance variables:
private int lvlCount = 1;
// Game() method
public Game(Stage stage) {
this.score = new SimpleIntegerProperty(0);
this.mobs = new ArrayList<>();
this.hitBoxes = new ArrayList<>();
this.treasure = new ArrayList<>();
this.newLevel = new ArrayList<>();
this.enemyCount = 0;
bg();
loadLevel(1);
living();
stuff();
mob2();
finalText();
stage.setOnShown(e -> this.run());
}
//The switch for loading the Levels:
void loadLevel(int in) {
switch (in) {
case 1:
this.level = new Level1();
break;
case 2:
this.level = new Level2(); // placeholder for second level
break;
}
hitBoxes.clear(); // clear the list of hitboxes
mobs.clear(); // remove any existing old mobs
this.getChildren().addAll(hitBoxes); // add all the hitboxes for the walls to the scene
background.setImage(level.getImage()); // get the background image
hitBoxes.addAll(level.getWalls()); // get all the wall hitboxes
enemyCount = level.getEnemyCount(); // get the enemy count from the level
chestCount = level.treasureCount(); // get the treasure count from the level
this.initTreasure(chestCount); // add the treasure chests for the level
this.initMobs(enemyCount); // initialize our mobs
lvlCount = level.lvlCount();
this.initLevel(lvlCount);
}
//The collision check:
private void collisionCheck() {if (r.getFill().equals(Color.WHITE)){lvlCount--;}
//Main Game loop method:
private void play() {
AnimationTimer gameLoop = new AnimationTimer() {
public void handle(long arg0) {
for (int i = 0; i < mobs.size(); i++) {
MOB m = mobs.get(i);
if (m instanceof Enemy) {
((Enemy) m).moveCheck(arg0);
}
}
collisionCheck();
if (lvlCount == 0){
loadLevel(2);} //The condition that loads Level 2
gameLoop.start();
}
Please help me to figure out how I can load Level 2, successfully.
Please note that it does not produce any errors in the console. So, I am having a very hard time figuring out where the problem lies.
I only pasted the code that I thought is necessary to achieve my goal. Here you can see the full code, for veiwing purposes only, no download necessary:
http://paste.mooc.fi/955c6d30
Thank you very much in advance.

JavaFX rectangle mouseonclick grid return

I am writing a board game which has a 20x20 grid.
This is in my board class:
private final Position[][] grid = new Position[GRID_SIZE][GRID_SIZE];
each position has :
public class Position {
private final Coordinates pos;
private Player player;
private final static double RECTANGLE_SIZE = 40.0;
private final Rectangle rect = new Rectangle(RECTANGLE_SIZE, RECTANGLE_SIZE);
}
so basically I have 20x20 Positions and each positions has a Rectangle
This is what I do to display the grid
for (int cols = 0; cols < GRID_SIZE; ++cols) {
for (int rows = 0; rows < GRID_SIZE; ++rows) {
grid.add(gameEngine.getBoard().getGrid()[cols][rows].getRect(), cols, rows);
}
}
Anyway, the grid is initialized and works properly. What I want to do is to make the rectangle objects clickable and to be able to return their Coordinates when they are clicked.
This is how I handle the mouse click
private void setUpRectangle() {
rect.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
rect.setFill(Color.BLACK);
}
});
}
What this code does is to change the color of the rectangle to black, but how could I return the Coordinates.
Basically, I can edit the onclick function to return the coordinates of this position, but how can I acquire them later?
This is not a JavaFX question as much as it is a design question. You have a container (Position) of 2 objects (Coordinates and Rectangle) and you want one of them to know about the other. That is, the rectangle should know the coordinates of its position.
There are a few approaches here, and depending on the bigger picture, one might be better than the others. James_D mentioned a couple in a comment.
Keep a reference of the position object in the rectangle object. This is useful if rectangle needs to access various datum in the container from various places. You would do something like rectangle.getPosition().getCoordinates() or .getPlayer().
Keep a reference of the coordinates object in the rectangle object. This is a more specific approach of 1 useful if you only need that object. You would do something like rectangle.getCoordinates().
Pass the coordinates to your setUpRectangle method. This is useful if you rectangle doesn't need access to this data from various places, it's a local solution. Then in the handle method you would return the coordinates you passed to setUpRectangle, though we can't see what class this method is in.
Use external help. You can keep something like Map<Rectangle, Coordinates> and then call map.get(rectangle). You can hide this map in a method Coordinates getCoordinatesForRectangle(Rectangle rectangle) instead of calling it directly.
You could store this data as userData (or use properties in case userData is preserved for something else in your program):
private final Rectangle rect;
public Position() {
rect = new Rectangle(RECTANGLE_SIZE, RECTANGLE_SIZE);
rect.setUserData(this);
}
rect.setOnMouseClicked((MouseEvent event) -> {
Position pos = (Position) ((Node) event.getSource()).getUserData();
...
});
You could also use a listener that knows about the position:
class CoordinateAwareListener implements EventHandler<MouseEvent> {
private final int coordinateX;
private final int coordinateY;
public CoordinateAwareListener(int coordinateX, int coordinateY) {
this.coordinateX = coordinateX;
this.coordinateY = coordinateY;
}
#Override
public void handle(MouseEvent event) {
// do something with the coordinates
}
}

Need help figuring out Basic Chess movement logic

Sorry for wall of text, but currently stumped. I'm not asking to be "spoon feed" since I have the basic idea down for each piece, it's just I'm having a difficult time on how to finish determining my move logic. Allow me to further explain. I'll be posting my code as well for better reference.
I'm coding with a MVC structure. I have a Model which is a 2D array of BoardSquares. Which those BoardSquares keep track of it's location on the board, what piece is in it (if there is one), what color that piece is (if there is one), and if it's empty. Here's the code for it:
public class BoardSquare {
// Private information stored in each BoardSquare
private boolean isSquareEmpty;
private int row;
private int col;
private String space;
private String pColor;
// Constructor to make an empty space on the board
public BoardSquare(int row, int col) {
space = "";
pColor = "";
this.row = row;
this.col = col;
SquareEmpty();
}
//Constructor to get the information of a space with a piece
public BoardSquare(BoardPiece piece, int row, int col) {
this.space = piece.getModelName();
this.pColor = Character.toString((piece.getModelName().charAt(0)));
this.row = row;
this.col = col;
SquareNotEmpty();
}
public String getpColor() {
String temp = getPieceColor(pColor);
return temp;
}
//A bunch of auto generated getters/setters...
// Gets the correct color label for the piece
public String getPieceColor(String info){
String temp;
if(info.equalsIgnoreCase("b")){
temp = "Black";
}
else {
temp = "White";
}
return temp;
}
Currently all my Pieces extend an abstract BoardPiece class which has several abstract methods as well, but my piece knows of it's location on the board, it's name, it's color, and the 2D board array for the way I'm generating the valid moves.
I'm generating them by checking the spaces it can move to and seeing if they are empty and adding them to an ArrayList and comparing and seeing if that list contains the inputted destination.
However I'm having problems thinking of how to stop checking if say Black Rook was on the left side of the board and wanted to move all the way to the Right, but there was a Black Pawn to the right of the Rook preventing it from doing so. I'm trying to generically think of it to make my life easier and I can implement it in the other piece classes as well So here's the Rook's code:
public class Rook extends BoardPiece{
private String name = "Rook";
private String color;
private String modelName;
BoardSquare board[][];
// Both should remain 0 - 7
private int row;
private int col;
public Rook (String modelName, int row, int col, String color, BoardSquare[][] field) {
this.modelName = modelName;
this.row = row;
this.col = col;
this.color = color;
this.board = field;
}
#Override
void move(BoardSquare target) {
if(!getPossibleMove(board).contains(target)){
//Sysout false move
}
}
#Override
Collection<BoardSquare> getPossibleMove(BoardSquare[][] board) {
ArrayList<BoardSquare> validMoves = new ArrayList<BoardSquare>();
for(int i = 0; i < 8; i++){
// Checks every column of the row that the piece is on
if(moveValidator(board[row][i])){
validMoves.add(board[row][i]);
}
// Checks every row of the column that the piece is on
if(moveValidator(board[i][col])){
validMoves.add(board[i][col]);
}
}
return validMoves;
}
#Override
boolean moveValidator(BoardSquare space) {
// Removes the current square the piece is on as a valid move
if(space.getRow() == getRow() && space.getCol() == getCol()){
return false;
}
//Checks if the space is not empty and the piece in the spot is the same color as the piece itself
if(!space.isEmptySquare() && space.getpColor().equalsIgnoreCase(color)){
return false;
}
return true;
}
Like I said any help or push toward the right direction would be appreciated. Sorry for the wall of text but trying to be as clear as I can so that whoever wants to help can fully understand and see my logic.
EDIT: Forgot to note that the Rook has Auto-generated Getters and Setters as well.
I would approach it the most brute-force and intuitive way possible: think of moving the rook one square at a time as it takes its turn and see if it collides with anything. That is, hop it across every square until it gets to the desired spot and check if it's a valid move at each square.
This is a fine approach because
it's easy to understand
it's not expensive until your chess board gets massively huge, so brute force isn't a problem.
it generalizes to all pieces: rooks have to "slide" to their destination, but knights can "jump" or "teleport" over other pieces to their new location, so don't need the intermediate hops.
This sounds close to your current implementation, but you need to stop tracing when you collide. That is, if there is a black pawn in the way, the columns after that pawn are no longer valid spaces, right? In other words, think of the move as an action that the rook takes instead of an independent state space of possible moves, since some spaces are legal moves except that the rook was previously blocked. You need to know where the rook is from and where it is going to determine valid moves, not just if the space is in the same row.
So, reading your code (thanks for posting the context, by the way, it's quite helpful) really all you need to do is not iterate on each square, but iterate moving through each square, and stop the iteration when you get blocked.

Adding colours to custom edges

I want to add colours to the edges of the graph which I created using the JUNG library. I have edges which are in the type of custom edges where I set the labels and weights to the edges.
Transformer<CustomEdge, Paint> edgesPaint = new Transformer<CustomEdge, Paint>() {
private final Color[] palette = {Color.GREEN,
Color.YELLOW, Color.RED};
public Paint transform(CustomEdge edgeValue) {
String stringvalue=edgeValue.toString();
stringvalue=stringvalue.replaceAll("%","");
int value=Integer.valueOf(stringvalue);
if (value<= 10) {
return palette[0];
}
if (value> 10 && value<=20 ) {
return palette[1];
}
else {
return palette[2];
}
}
};
The following line returns an error message saying that the type of the edgesPaint should be (string,Paint):
visualizationViewer.getRenderContext().setEdgeFillPaintTransformer(edgesPaint);
Please help me with this.
Offhand I'd guess that your VisualizationViewer was declared to have edge type "String" (i.e., VisualizationViewer. But without more context it's hard to be sure.
Please print the exact error message and stack trace. Showing the declaration of the VisualizationViewer would also probably be helpful.

Categories

Resources