First of all, this is my very first post here. Hello everyone!
I am a beginner in Java/JavaFX. Currently I wrote some simple “game” to learn some basic stuff in game development, doing that just for fun right now. So far I get a player which moves to the left/right (movement is unrestricted, but never mind that now) and fires projectiles. I got this done, code below:
package tester; import java.util.ArrayList; import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.input.KeyCode; import javafx.scene.layout.AnchorPane; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; public class Tester extends Application { private int dx, x = 150, y = 470, projectileSpeed = 10; private int counter = 0, spawnTime = 180, enemySpeed = 4; private boolean goLeft, goRight, isShooting; public final static int APP_WIDTH = 300; public final static int APP_HEIGHT = 500; private AnchorPane root; private Scene scene; private Rectangle projectile; private Circle player = new Circle(x, y, 10, Color.RED); private Rectangle enemy; private ArrayList<Rectangle> projectiles = new ArrayList(); private ArrayList<Rectangle> enemies = new ArrayList(); @Override public void start(Stage primaryStage) { root = new AnchorPane(); scene = new Scene(root, APP_WIDTH, APP_HEIGHT, Color.GHOSTWHITE); primaryStage.setTitle("Hello World!"); primaryStage.setScene(scene); primaryStage.setResizable(false); primaryStage.show(); root.getChildren().addAll(player); loop(); } private void controls() { scene.setOnKeyPressed(event -> { KeyCode key = event.getCode(); switch (key) { case LEFT: goLeft = true; break; case RIGHT: goRight = true; break; case SPACE: projectiles.add(projectile = new Rectangle(3, 3, Color.BLUE)); projectile.relocate(x + player.getRadius(), y); root.getChildren().add(projectile); break; } }); scene.setOnKeyReleased(event -> { KeyCode key = event.getCode(); switch (key) { case LEFT: goLeft = false; break; case RIGHT: goRight = false; break; case SPACE: isShooting = false; break; } }); } private void shoot() { for (int i = 0; i < projectiles.size(); ++i) { if (projectiles.get(i).getLayoutY() > (root.getBoundsInParent().getMinY() - projectile.getHeight())) { projectiles.get(i).relocate(projectiles.get(i).getLayoutX(), (projectiles.get(i).getLayoutY() - projectileSpeed)); } else { projectiles.remove(i); root.getChildren().remove(i); } } } private void spawnEnemy() { double spawnPosition = Math.random(); int eWidth = 20; int eHeight = 40; double ex = (APP_WIDTH - eWidth) * spawnPosition; int ey = (int) (root.getBoundsInParent().getMinY()); if (counter % spawnTime == 0) { enemies.add(enemy = new Rectangle(ex, ey, eWidth, eHeight)); root.getChildren().add(enemy); } } public void moveEnemy() { for (int i = 0; i < enemies.size(); ++i) { if (enemies.get(i).getLayoutY() < (root.getBoundsInParent().getMaxY() + enemy.getHeight())) { enemies.get(i).relocate(enemies.get(i).getLayoutX(), (enemies.get(i).getLayoutY() + enemySpeed)); } else { enemies.remove(i); } } } private void loop() { AnimationTimer timer = new AnimationTimer() { @Override public void handle(long now) { controls(); if (goLeft) { dx = -5; } if (goRight) { dx = 5; } if (!goLeft && !goRight) { dx = 0; } player.relocate(x += dx, y); shoot(); counter++; spawnEnemy(); moveEnemy(); } }; timer.start(); } public static void main(String[] args) { launch(args); } }
Now the weird part. If I comment the moveEnemy() method out, everything seems OK – the “enemies” (black rectangles) appear in random places along the x axis on the top of the root.
I thought I’ll move enemies by means of the same method which I used to move projectiles. However, if I actually use this, my enemies keep appearing at the left top corner and dissappear almost instantly. Why is that?
Many thanks!
Edit: maybe I wasn’t clear. I don’t expect a ready-made solution, but an explanation.
Advertisement
Answer
Ok, I got it sorted out, thanks kleopatra for help! Probably there is still a room for improvement, but nonetheless its some progress:
package tester; import java.util.ArrayList; import java.util.Iterator; import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.input.KeyCode; import javafx.scene.layout.AnchorPane; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; public class Tester extends Application { private int dx, x = 150, y = 470, projectileSpeed = 10; private int counter = 0, spawnTime = 180, enemySpeed = 4; private boolean goLeft, goRight, isShooting; public final static int APP_WIDTH = 300; public final static int APP_HEIGHT = 500; private AnchorPane root; private Scene scene; private Rectangle projectile; private Circle player = new Circle(x, y, 10, Color.RED); private Rectangle enemy; private ArrayList<Rectangle> projectiles = new ArrayList(); private ArrayList<Rectangle> enemies = new ArrayList(); @Override public void start(Stage primaryStage) { root = new AnchorPane(); scene = new Scene(root, APP_WIDTH, APP_HEIGHT, Color.GHOSTWHITE); primaryStage.setTitle("Hello World!"); primaryStage.setScene(scene); primaryStage.setResizable(false); primaryStage.show(); root.getChildren().addAll(player); controls(); loop(); } private void controls() { scene.setOnKeyPressed(event -> { KeyCode key = event.getCode(); switch (key) { case LEFT: goLeft = true; break; case RIGHT: goRight = true; break; case SPACE: if (!isShooting) { projectiles.add(projectile = new Rectangle(2, 10, Color.ORANGERED)); projectile.relocate(x + player.getRadius(), y); root.getChildren().add(projectile); isShooting = true; break; } } }); scene.setOnKeyReleased(event -> { KeyCode key = event.getCode(); switch (key) { case LEFT: goLeft = false; break; case RIGHT: goRight = false; break; case SPACE: isShooting = false; break; } }); } private void shoot() { for (int i = 0; i < projectiles.size(); ++i) { projectiles.get(i).relocate(projectiles.get(i).getLayoutX(), (projectiles.get(i).getLayoutY() - projectileSpeed)); } Iterator<Rectangle> iterator = projectiles.iterator(); while (iterator.hasNext()) { projectile = iterator.next(); if (projectile.getLayoutY() < root.getLayoutY()) { iterator.remove(); root.getChildren().remove(projectile); } } } private void spawnEnemy() { double spawnPosition = Math.random(); int eWidth = 20; int eHeight = 40; double ex = (int) ((APP_WIDTH - eWidth) * spawnPosition); int ey = (int) (root.getLayoutY()); if (counter % spawnTime == 0) { enemy = new Rectangle(eWidth, eHeight); enemy.relocate(ex, ey); enemies.add(enemy); root.getChildren().add(enemy); } } public void moveEnemy(int delta) { for (int i = 0; i < enemies.size(); ++i) { enemies.get(i).setY(enemies.get(i).getY() + delta); } Iterator<Rectangle> iterator = enemies.iterator(); while (iterator.hasNext()) { enemy = iterator.next(); if (enemy.getLayoutY() < root.getLayoutY()) { iterator.remove(); root.getChildren().remove(enemy); } } } private void loop() { AnimationTimer timer = new AnimationTimer() { @Override public void handle(long now) { if (goLeft) { dx = -5; } if (goRight) { dx = 5; } if (!goLeft && !goRight) { dx = 0; } player.relocate(x += dx, y); shoot(); counter++; spawnEnemy(); moveEnemy(4); } }; timer.start(); } public static void main(String[] args) { launch(args); } }
Now I’ll play with the code a bit, try detecting collisions, restricting movement, adding some more stuff etc.