Conways Game of Life in JavaFX [closed] - java

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I try to add a method that let a cell get alive if it's clicked by the left mouse button but I don't know how. I tried to add a MouseClickListener but I couldn't connect it to my code. I'm new to JavaFx so it's pretty hard to overview all the functions and how to use them. Every other function of my code works perfectly so far. I hope that anyone of you know how to implement this method. Here is my code:
import com.google.gson.reflect.TypeToken;
import javafx.application.Application;
import javafx.animation.AnimationTimer;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import com.google.gson.Gson;
import javax.swing.*;
public class conway extends Application {
private static final int width = 500;
private static final int height = 500;
private static final int cellsize = 10;
private static Gson gson = new Gson();
private static class Life{
private final int reihe;
private final int zeile;
private Boolean[][] rules;
private int[][] grid;
private Random random=new Random();
private final GraphicsContext graphics;
public Life(int reihe, int zeile, GraphicsContext graphics){
this.reihe =reihe;
this.zeile =zeile;
this.graphics=graphics;
grid=new int[reihe][zeile];
this.rules = new Boolean[][]{{false, false, false, true, false, false, false, false, false, false},
{false, false, true, true, false, false, false, false, false, false}};
}
public void init(){
for(int i = 0; i< reihe; i++){
for(int j = 0; j< zeile; j++){
grid[i][j]=random.nextInt(2);
}
}
draw();
}
private void draw(){
graphics.setFill(Color.LAVENDER);
graphics.fillRect(0,0,width,height);
for(int i=0; i<grid.length;i++){
for(int j=0; j<grid[i].length; j++){
if(grid[i][j]==1){
graphics.setFill(Color.gray(0.5,0.5));
graphics.fillRect(i*cellsize, j*cellsize,cellsize,cellsize);
graphics.setFill(Color.PURPLE);
graphics.fillRect((i*cellsize)+1, (j*cellsize)+1, cellsize-2, cellsize-2);
}
else{
graphics.setFill(Color.gray(0.5,0.5));
graphics.fillRect(i*cellsize,j*cellsize,cellsize, cellsize);
graphics.setFill(Color.WHITE);
graphics.fillRect((i*cellsize)+1,(j*cellsize)+1,cellsize-2,cellsize-2);
}
}
}
}
private int countNeighbors(int i, int j){
int sum=0;
int iStart=i==0?0:-1;
int iEnd=i==grid.length - 1 ? 0:1;
int jStart=j==0?0:-1;
int jEnd=j==grid[0].length - 1 ? 0:1;
for (int k=iStart; k<=iEnd;k++){
for(int l=jStart;l<=jEnd;l++){
sum+=grid[i+k][l+j];
}
}
sum-=grid[i][j];
return sum;
}
public void tick(){
int[][] next=new int[reihe][zeile];
for(int i = 0; i< reihe; i++){
for(int j = 0; j< zeile; j++){
int nachbar= countNeighbors(i,j);
if(rules[grid[i][j]][nachbar] == true){
next[i][j] = 1;
}
}
}
grid=next;
draw();
}
public void safe() throws IOException {
JsonArray to_safe = new JsonArray();
Path pfad = Paths.get("C:\\Users\\Frodo\\IdeaProjects\\gameoflife\\only_safe_file_for_now.json");
if(Files.exists(pfad) == false) {
Files.createFile(pfad);
}
for(int i = 0; i<grid.length; i++){
JsonArray helper = new JsonArray();
for (int j = 0; j<grid[0].length; j++){
helper.add(grid[i][j]);
}
to_safe.add(helper);
}
Files.writeString(pfad, gson.toJson(to_safe));
}
public void load() throws IOException{
int saved_grid[][];
Path pfad = Paths.get("C:\\Users\\Frodo\\IdeaProjects\\gameoflife\\only_safe_file_for_now.json");
if(Files.exists(pfad) == false) {
return;
}
else {
String array_string = Files.readString(pfad);
saved_grid = gson.fromJson(array_string, new TypeToken<int[][]>(){}.getType());
if (saved_grid.length == 0) {
return;
}
}
grid = saved_grid;
draw();
}
}
public static void main(String[] args) {
launch();
}
public void start(Stage primaryStage) {
VBox root = new VBox(10);
Scene scene = new Scene(root, width, height + 100);
final Canvas canvas = new Canvas(width, height);
final boolean[] leftclick = new boolean[1];
leftclick[0] =false;
scene.setOnMouseClicked(e->{
if(e.getButton().equals(MouseButton.PRIMARY)){
if(leftclick[0]){
leftclick[0] =false;
}
else leftclick[0] =true;
}
});
Button reset = new Button("Reset");
Button step = new Button("Step");
Button run = new Button("Run");
Button stop = new Button("Stop");
Button safe_state = new Button("Safe");
Button load_button = new Button("Load");
Button terminate = new Button("Terminate");
root.getChildren().addAll(canvas, new HBox(10, reset, step, run, stop, safe_state, load_button, terminate));
primaryStage.setScene(scene);
primaryStage.show();
int rows = (int) Math.floor(height / cellsize);
int cols = (int) Math.floor(width / cellsize);
GraphicsContext graphics = canvas.getGraphicsContext2D();
Life life = new Life(rows, cols, graphics);
life.init();
AnimationTimer Animation = new AnimationTimer() {
private long lastUpdate=0;
#Override
public void handle(long now) {
if ((now - lastUpdate) >= TimeUnit.MILLISECONDS.toNanos(100)) {
life.tick();
lastUpdate = now;
}
}
};
reset.setOnAction(l -> life.init());
run.setOnAction(l -> Animation.start());
step.setOnAction(l -> life.tick());
stop.setOnAction(l -> Animation.stop());
safe_state.setOnAction(l-> {
try {
life.safe();
} catch (IOException e) {
e.printStackTrace();
}
});
load_button.setOnAction(l -> {
try {
life.load();
} catch (IOException e) {
e.printStackTrace();
}
});
terminate.setOnAction(l -> {
Stage stage = (Stage) terminate.getScene().getWindow();
stage.close();
});
}
}

Something in this direction should do the trick:
canvas.addEventHandler(MouseEvent.MOUSE_CLICKED,
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
// is left click
if (t == MouseEvent.BUTTON1) {
grid[rows][cols] = 1;
draw();
}
}
});

Related

JavaFX: Way to change value of programmatically created buttons

I'm trying to change the value of buttons which are created in a for loop. The value of the buttons must be saved in a hashmap which contains the id of the button and the value.
This is what I currently have:
private void createMap(int blocksX, int blocksY) {
// blocksX and blocksY are the amount of buttons to be placed
for (int x = 0; x < blocksX; x++) {
for (int y = 0; y < blocksY; y++) {
Button btn = new Button();
btn.setText("0");
btn.setPrefSize(32, 32);
btn.setLayoutX(32 * x);
btn.setLayoutY(32 * y);
btn.setId(String.valueOf(button_id));
map_list.put(button_id, 0);
button_id+=1;
items.getChildren().addAll(btn);
// If the user clicks a button, change the value of it...
btn.setOnAction(click -> {
if(btn.getText() == "0"){
changeButtonValue(Integer.parseInt(btn.getId()), 1);
btn.setText("1");
} else if(btn.getText() == "1") {
changeButtonValue(Integer.parseInt(btn.getId()), 0);
btn.setText("0");
}
});
}
}
}
But now the only item in the HashMap to be updated is the last created button. How can I change this so it will update all button values?
I completed the code to a runnable example. And I can't see your problem.
import java.util.HashMap;
import java.util.Map;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class FX01 extends Application {
public int button_id = 0;
public Map<Integer, Integer> map_list = new HashMap<>();
public AnchorPane items;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
items = new AnchorPane();
createMap(5, 5);
Scene scene = new Scene(items);
stage.setScene(scene);
stage.show();
}
private void createMap(int blocksX, int blocksY) {
// blocksX and blocksY are the amount of buttons to be placed
for (int x = 0; x < blocksX; x++) {
for (int y = 0; y < blocksY; y++) {
Button btn = new Button();
btn.setText("0");
btn.setPrefSize(32, 32);
btn.setLayoutX(32 * x);
btn.setLayoutY(32 * y);
btn.setId(String.valueOf(button_id));
map_list.put(button_id, 0);
button_id+=1;
items.getChildren().addAll(btn);
// If the user clicks a button, change the value of it...
btn.setOnAction(click -> {
if(btn.getText() == "0"){
changeButtonValue(Integer.parseInt(btn.getId()), 1);
btn.setText("1");
} else if(btn.getText() == "1") {
changeButtonValue(Integer.parseInt(btn.getId()), 0);
btn.setText("0");
}
});
}
}
}
private void changeButtonValue(int id, int value) {
map_list.put(id, value);
System.out.println("map_list: " + map_list);
}
}

Opening java file with button (javafx) [duplicate]

This question already has answers here:
JavaFX launch another application
(3 answers)
Closed 4 years ago.
I've got an app made in javafx and another class with menu in this project. In this menu I've got two buttons and one works (exit buuton) and I want buttonStart to open my Main class. How to launch it?
Button buttonStart = new Button("START GAME");
Button buttonExit = new Button("EXIT");
buttonExit.setOnMouseClicked(event -> System.exit(0));
My menu:
package pl.main;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Menu extends Application {
private BorderPane layout;
private Scene scene;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage window) throws Exception {
layout = new BorderPane();
scene = new Scene(layout, 720, 480);
HBox hbox = new HBox();
hbox.setPadding(new Insets(15, 12, 15, 12));
hbox.setSpacing(10);
hbox.setStyle("-fx-background-color: #F9A825;");
Button buttonStart = new Button("START GAME");
buttonStart.setPrefSize(100, 20);
buttonStart.setStyle("-fx-background-color: #E65100;");
Button buttonExit = new Button("EXIT");
buttonExit.setPrefSize(100, 20);
buttonExit.setStyle("-fx-background-color: #E65100;");
buttonExit.setOnMouseClicked(event -> System.exit(0));
hbox.getChildren().addAll(buttonStart, buttonExit);
layout.setCenter(hbox);
window.setScene(scene);
window.show();
}
}
Class which I wanna launch:
package pl.main;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import java.util.ArrayList;
import java.util.HashMap;
public class Main extends Application {
private HashMap<KeyCode, Boolean> keys = new HashMap<KeyCode, Boolean>();
private ArrayList<Node> blocks = new ArrayList<Node>();
private Pane appRoot = new Pane();
private Pane gameRoot = new Pane();
private Pane uiRoot = new Pane();
private Node player;
private Point2D playerGoDown = new Point2D(0, 0);
private Point2D playerGoRight = new Point2D(0, 0);
private boolean canJump = true;
private int levelWidth;
private void initContent() {
Rectangle background = new Rectangle(720, 480);
// BackgroundFill(Color.WHITE);
levelWidth = LevelData.LEVEL1[0].length();
for (int i = 0; i < LevelData.LEVEL1.length; i++) {
String map = LevelData.LEVEL1[i] + LevelData.LEVEL2[i]+ LevelData.LEVEL1[i]+ LevelData.LEVEL2[i]+ LevelData.LEVEL1[i]+ LevelData.LEVEL2[i];
String line = map;
for (int j = 0; j < line.length(); j++) {
switch (line.charAt(j)) {
case '0':
break;
case '1':
Node block = createEntity(j * 30, i * 30, 30, 30, Color.ORANGE);
blocks.add(block);
break;
}
}
}
player = createEntity(0, 350, 40, 40, Color.YELLOW);
// a ????????????
player.translateXProperty().addListener((a, old, newValue) -> {
int offset = newValue.intValue();
//if (offset > 360 && offset < levelWidth - 360) {
gameRoot.setLayoutX(-(offset - 360));
//}
});
appRoot.getChildren().addAll(background, gameRoot, uiRoot);
}
private void update() {
if (isPressed(KeyCode.W) && player.getTranslateY() >= 0) {
jumpPlayer();
}
if (playerGoDown.getY() < 10) {
playerGoDown = playerGoDown.add(0, 1);
}
movePlayerY((int) playerGoDown.getY());
if (player.getTranslateX() <= levelWidth - 5) {
// movePlayerX(5);
movePlayerRight();
}
if (playerGoRight.getX() < 0) {
playerGoRight = playerGoRight.add(0, 1);
}
movePlayerX((int) playerGoRight.getX());
}
private void movePlayerX(int value) {
boolean movingRight = value > 0;
for (int i = 0; i < Math.abs(value); i++) {
for (Node block : blocks) {
if (player.getBoundsInParent().intersects(block.getBoundsInParent())) {
if (movingRight) {
if (player.getTranslateX() + 40 == block.getTranslateX()) {
return;
}
} else {
if (player.getTranslateX() == block.getTranslateX() + 60) {
return;
}
}
}
}
player.setTranslateX(player.getTranslateX() + (movingRight ? 1 : -1));
}
}
private void movePlayerY(int value) {
boolean movingDown = value > 0;
for (int i = 0; i < Math.abs(value); i++) {
for (Node block : blocks) {
if (player.getBoundsInParent().intersects(block.getBoundsInParent())) {
if (movingDown) {
if (player.getTranslateY() + 40 == block.getTranslateY()) {
canJump = true;
return;
}
} else {
if (player.getTranslateY() == block.getTranslateY() + 60) {
return;
}
}
}
}
player.setTranslateY(player.getTranslateY() + (movingDown ? 1 : -1));
}
}
private void jumpPlayer() {
if (canJump) {
playerGoDown = playerGoDown.add(0, -10);
canJump = false;
}
}
private void movePlayerRight() {
playerGoRight = playerGoRight.add(10, 0);
}
private Node createEntity(int x, int y, int w, int h, Color color) {
Rectangle entity = new Rectangle(w, h);
entity.setTranslateX(x);
entity.setTranslateY(y);
entity.setFill(color);
gameRoot.getChildren().add(entity);
return entity;
}
private boolean isPressed(KeyCode key) {
return keys.getOrDefault(key, false);
}
#Override
public void start(Stage primaryStage) throws Exception {
initContent();
Scene scene = new Scene(appRoot);
scene.setOnKeyPressed(event -> keys.put(event.getCode(), true));
scene.setOnKeyReleased(event -> keys.put(event.getCode(), false));
primaryStage.setTitle("Jetpack gameplay");
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setResizable(false);
AnimationTimer timer = new AnimationTimer() {
#Override
public void handle(long now) {
update();
}
};
timer.start();
}
public static void main(String[] args) {
launch(args);
}
}
In future I wanna change current Main.java into ordinary class because now I have two classes which works independently.
If you want to go on another page, you have to load the game scene.
Look at Scene class in JavaDoc.
Once you have your scene, you just have to add an ActionEvent to your button that will display your page.

JavaFX draw Multi shape using multiple points

I have an arraylist of Point. I want to draw lines out the points. Here is what I have done.
for (int i = 0; i < arrPoint.size(); i++) {
Point startPoint = arrPoint.get(i);
Point endPoint = null;
if (i == arrPoint.size()) {
endPoint = arrPoint.get(0);
} else {
endPoint = arrPoint.get(i + 1);
}
Line line = new Line();
line.setStartX(startPoint.getCoordinateX());
line.setEndX(endPoint.getCoordinateX());
line.setStartY(startPoint.getCoordinateY());
line.setEndY(endPoint.getCoordinateY());
box.getChildren().add(line);
}
My Point cass is like
public class Point {
private double coordinateX;
private double coordinateY;
public Point(double coordinateX, double coordinateY) {
this.coordinateX = coordinateX;
this.coordinateY = coordinateY;
}
public void setCoordinateX(double coordinateX) {
this.coordinateX = coordinateX;
}
public void setCoordinateY(double coordinateY) {
this.coordinateY = coordinateY;
}
public double getCoordinateX() {
return coordinateX;
}
public double getCoordinateY() {
return coordinateY;
}
}
My code is displayed blank. I am new to JavaFx. Can I get any help?
You need to have the points before you can loop over the points to draw.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Draw line");
Group g = new Group();
Scene scene = new Scene(g, 550, 550,Color.web("0x0000FF",1.0));
ObservableList<Point> arrPoint = FXCollections.observableArrayList();
Point point1 = new Point(100, 200);
Point point2 = new Point(300, 400);
arrPoint.addAll(point1, point2);
for (int i = 0; i < arrPoint.size()-1; i++) {
Point startPoint = arrPoint.get(i);
Point endPoint = null;
if (i == arrPoint.size()) {
endPoint = arrPoint.get(0);
} else {
endPoint = arrPoint.get(i + 1);
}
Line line = new Line();
line.setStartX(startPoint.getCoordinateX());
line.setEndX(endPoint.getCoordinateX());
line.setStartY(startPoint.getCoordinateY());
line.setEndY(endPoint.getCoordinateY());
g.getChildren().add(line);
}
primaryStage.setScene(scene);
primaryStage.show();
}
}
I hope it can help you some.

how to make onMouseClicked event work for labels inside an array in Java

I have an Array of labels and I want to add an onMouseClicked Event. I tried many ways. my last attempt was adding the mouse event inside of the For Loop block where I created the array of labels. But it still doesnt work. Could you guys please give me some help or advice...
This is my class Calculations, where I am trying to make this mouse event work: I surrounded the important part with hashtags and wrote a comment as well.
package application;
import javafx.scene.control.Label;
public class Calculations {
public Label[] test() {
Label label = new Label();
Label lbs[] = new Label[20*20];
//##################################################################
for (int i = 0 ; i < 400; i++) {
lbs[i] = new Label();
lbs[i].setOnMouseClicked(e -> { // <-- I tried this way,
label.setText("X"); // but it doesnt work
});
//##################################################################
}
lbs[10].setText("x");
return lbs;
}
}
My Main class: the part where the method from the above is called is surrounded in hashtags:
package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
GridPane grid = new GridPane();
Scene scene = new Scene(grid, (20 * 20), (20 * 20));
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
for(int i = 0; i < 20; i++) {
ColumnConstraints column = new ColumnConstraints(20);
grid.getColumnConstraints().add(column);
}
for(int i = 0; i < 20; i++) {
RowConstraints row = new RowConstraints(20);
grid.getRowConstraints().add(row);
}
//##################################################################
Calculations c = new Calculations();
int count = 0;
for (int x = 0; x < c.test().length/20; x++){
for (int y = 0; y < c.test().length/20; y++){
grid.add(c.test()[count], x, y);
count++;
}
}
//##################################################################
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}

Multiple animations(threads) in a JPanel

I am trying to code a board game in Java.
I have 11 classes including Main. Board class which extends JPanel and draws the board image as well as the dice image. The class Player which extends JCoponent and implements Runnable(Thread). Every player instance is a pawn-animation that it is moving across the board. The player class draws the pawn on the board.
Pattern
How the code it looks like :
Board b=new Board();
Player p=new Player();
b.add(p);
JPanel panel=new JPanel();
panel.add(b);
add(panel); //adding the panel to the frame.
The problem is that I can't have more than one pawn simultaneously on the board. I have already tried to re-paint all the players (as non-animation) in another class but it didn't work. I also tried JLayeredPane but maybe I am doing something wrong. Unfortunately, I can't change the above pattern so don't make this suggestion.
Thank you in advance for your help.
P.S: I can't post any code because its huge.
P.P.S: more clarifications will be given, if you ask me.
EDIT: I reform my question. Is it possible to have two animations simultaneously on the same panel? if the answer is a yes ..how I can do that?
It's most likely possible to have many components moving all at once. Either use javax.swing.Timer ou SwingWorker for this to work.
Here is a quick example showing you this. It puts 16 pawns on a board and moves them randomly from one place to another.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestAnimation {
private static final String PAWN_URL = "http://files.chesskidfiles.com/images_users/tiny_mce/BoundingOwl/bishop_happywhite.png";
private Image pawn;
private Map<Location, Pawn> pawnLocations = new HashMap<>();
private Board board;
private Timer timer;
private JLayeredPane glassPane;
public TestAnimation() {
try {
pawn = new ImageIcon(new URL(PAWN_URL)).getImage();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
private static class Location {
public final int row;
public final int col;
public Location(int row, int col) {
super();
this.row = row;
this.col = col;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + col;
result = prime * result + row;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Location other = (Location) obj;
return (col == other.col && row == other.row);
}
}
private static class Cell extends JPanel {
private final Location location;
public Cell(Location location) {
super(new BorderLayout());
this.location = location;
setOpaque(true);
setBackground(((location.row + location.col) % 2) == 0 ? Color.WHITE : Color.BLACK);
}
#Override
protected void addImpl(Component comp, Object constraints, int index) {
while (getComponentCount() > 0) {
remove(0);
}
super.addImpl(comp, constraints, index);
}
}
private static class Board extends JPanel {
private Map<Location, Cell> cells = new HashMap<>();
public Board() {
super(new GridLayout(8, 8));
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
Cell cell = new Cell(new Location(i, j));
add(cell);
cells.put(new Location(i, j), cell);
}
}
}
public void add(Pawn pawn, Location location) {
cells.get(location).add(pawn);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public Cell getCell(Location location) {
return cells.get(location);
}
}
private class Pawn extends JComponent {
public Pawn() {
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(pawn, 0, 0, getWidth(), getHeight(), this);
}
}
protected void initUI() {
JFrame frame = new JFrame(TestAnimation.class.getSimpleName());
board = new Board();
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 2; j++) {
Location location = new Location(i, j);
Pawn aPawn = new Pawn();
board.add(aPawn, location);
pawnLocations.put(location, aPawn);
}
}
for (int i = 0; i < 8; i++) {
for (int j = 6; j < 8; j++) {
Location location = new Location(i, j);
Pawn aPawn = new Pawn();
board.add(aPawn, location);
pawnLocations.put(location, aPawn);
}
}
timer = new Timer(7000, new Animation());
timer.setInitialDelay(0);
timer.setRepeats(true);
timer.setCoalesce(false);
glassPane = new JLayeredPane();
glassPane.setOpaque(false);
frame.add(board);
frame.setGlassPane(glassPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
timer.start();
glassPane.setVisible(true);
}
public class Animation implements ActionListener {
private Map<Location, Pawn> futureLocations;
private Random random = new Random();
private Timer subTimer;
private List<Pawn> movingPawns;
private Map<Pawn, Point> originalCoordinates = new HashMap<>();
private Map<Pawn, Point> futureCoordinates = new HashMap<>();
#Override
public void actionPerformed(ActionEvent e) {
futureLocations = new HashMap<>();
movingPawns = new ArrayList<>();
for (Pawn p : pawnLocations.values()) {
int row = random.nextInt(8);
int col = random.nextInt(8);
Location location;
while (futureLocations.containsKey((location = new Location(row, col)))) {
row = random.nextInt(8);
col = random.nextInt(8);
}
futureLocations.put(location, p);
Cell futureCell = board.getCell(location);
futureCoordinates.put(p, SwingUtilities.convertPoint(futureCell, 0, 0, glassPane));
movingPawns.add(p);
}
for (Pawn p : movingPawns) {
Point locationInGlassPane = SwingUtilities.convertPoint(p.getParent(), 0, 0, glassPane);
glassPane.add(p);
p.setLocation(locationInGlassPane);
originalCoordinates.put(p, locationInGlassPane);
}
subTimer = new Timer(50, new AnimationSteps());
subTimer.setInitialDelay(0);
subTimer.setCoalesce(true);
subTimer.setRepeats(true);
subTimer.start();
}
public class AnimationSteps implements ActionListener {
private int step = 0;
#Override
public void actionPerformed(ActionEvent e1) {
if (step < 50 + 1) {
for (Pawn p : movingPawns) {
Point p1 = originalCoordinates.get(p);
Point p2 = futureCoordinates.get(p);
int x = (int) (p1.x + ((p2.x - p1.x) * (double) step / 50));
int y = (int) (p1.y + ((p2.y - p1.y) * (double) step / 50));
p.setLocation(x, y);
}
} else {
for (Entry<Location, Pawn> e : futureLocations.entrySet()) {
board.add(e.getValue(), e.getKey());
}
board.revalidate();
subTimer.stop();
pawnLocations = futureLocations;
}
step++;
}
}
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestAnimation().initUI();
}
});
}
}
Maybe your problem is trying to develop a program with a thread for each object, most popular games run with a single thread, two at most. The reason: It will be very complex to synchronize threads with each other, not to mention that your performance will be poor. Even the graphics engine in Java is single threaded and that means you won't have two threads drawing at the same time.

Categories