JavaFX - 移动射弹
JavaFX - move projectiles
首先,这是我第一次post来这里。大家好!
我是 Java/JavaFX 的初学者。目前我写了一些简单的“游戏”来学习游戏开发的一些基本知识,现在只是为了好玩。
到目前为止,我得到了一个移动到 left/right 的玩家(移动不受限制,但现在不用担心)并发射射弹。我完成了这个,代码如下:
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);
}
}
现在是奇怪的部分。
如果我注释掉 moveEnemy() 方法,一切似乎都正常 - “敌人”(黑色矩形)出现在根顶部沿 x 轴的随机位置。
我想我会用移动弹丸的相同方法移动敌人。但是,如果我真的使用它,我的敌人会一直出现在左上角,然后几乎立即消失。
这是为什么?
非常感谢!
编辑:可能我没说清楚。我不期待一个现成的解决方案,而是一个解释。
好的,我搞定了,感谢 kleopatra 的帮助!可能还有改进的余地,但还是有一些进步:
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);
}
}
现在我会玩一下代码,尝试检测碰撞、限制移动、添加更多内容等。
首先,这是我第一次post来这里。大家好!
我是 Java/JavaFX 的初学者。目前我写了一些简单的“游戏”来学习游戏开发的一些基本知识,现在只是为了好玩。 到目前为止,我得到了一个移动到 left/right 的玩家(移动不受限制,但现在不用担心)并发射射弹。我完成了这个,代码如下:
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);
}
}
现在是奇怪的部分。 如果我注释掉 moveEnemy() 方法,一切似乎都正常 - “敌人”(黑色矩形)出现在根顶部沿 x 轴的随机位置。
我想我会用移动弹丸的相同方法移动敌人。但是,如果我真的使用它,我的敌人会一直出现在左上角,然后几乎立即消失。 这是为什么?
非常感谢!
编辑:可能我没说清楚。我不期待一个现成的解决方案,而是一个解释。
好的,我搞定了,感谢 kleopatra 的帮助!可能还有改进的余地,但还是有一些进步:
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);
}
}
现在我会玩一下代码,尝试检测碰撞、限制移动、添加更多内容等。