为什么我的函数没有做它应该做的事情,改变了 javafx 中球的速度方向?
Why is my function not doing what its supposed to, changing the direction of the velocity of a ball in javafx?
所以我做了一个小程序,其中我有一个球,它应该在跌落时缓慢加速,并在再次跳起时缓慢减速。同时它应该向左和向右移动,基本上是左右弹跳。
我现在遇到的问题是,当球击中 canvas 底部时,应该使球改变 y 轴速度的方法停止改变代数符号,在第一次成功 jump/bounce 球在底部出现故障。
我尝试打印一些东西,如果它进入函数 moveBubbleUp() 并且它在屏幕底部出现故障并且应该向上移动时打印出来再次,为什么代数符号不会改变?打印速度时,它变得越来越大,即使 moveBubbleUp() 中有 bubbleVelocity-=5。
所以该方法被调用,通过在它进入时打印一个随机字符串来证明,但没有做任何我想要它做的事情,同时也完全按照它的对应 moveBubbleDown() 应该做的。
当故障发生时它不会被调用,因为我也尝试在那里打印一些东西。
改变速度的方法如下:
void moveBubbleDown() {
bubbleSpeedY += 5;
bubbleVelocityY = bubbleSpeedY;
}
void moveBubbleUp() {
bubbleSpeedY -= 5;
bubbleVelocityY = -bubbleSpeedY;
}
这里是调用函数然后根据函数更改 y-Pos 的方法:
//calculates YPos of bubble
//changes which method should be called, if the ball has left the border
//and sets him on the edge of it
if (bubble.getTranslateY()>=heightPane-radiusBubble) {
bubble.setTranslateY(heightPane-radiusBubble);
moveDown=false;
} else if (bubble.getTranslateY() <= maxHeight) {
bubble.setTranslateY(maxHeight);
moveDown=true;
}
if (moveDown) {
moveBubbleDown();
} else {
moveBubbleUp();
}
final double deltaYBubble = elapsedSeconds * bubbleVelocityY;
bubble.setTranslateY(bubble.getTranslateY() + deltaYBubble);
为了不遗漏任何内容,我将 post 其余代码,以便您也可以自己尝试:
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Main extends Application {
//Global Variables
private static final int widthPane = 1000;
private static final int heightPane = 650;
long lastUpdateTime = 0;
//canvas
private Pane root = new Pane();
//Enemy
int bubbleSpeedY = 30;
int bubbleVelocityY = bubbleSpeedY;
final int bubbleSpeedX = 200;
int bubbleVelocityX = 0;
int radiusBubble = 25;
boolean moveDown=true;
boolean moveRight=true;
int maxHeight = 50;
private Circle bubble = new Circle(radiusBubble, Color.CADETBLUE);
private Parent createContent() {
root.setPrefSize(widthPane, heightPane);
root.getChildren().addAll(bubble);
return root;
}
@Override
public void start(Stage stage) throws Exception{
bubble.setTranslateY(maxHeight);
bubble.setTranslateX((int)(Math.random()*widthPane));
Scene scene = new Scene(createContent());
final AnimationTimer gameAnimation = new AnimationTimer() {
@Override
public void handle(long timestamp) {
update(timestamp);
}
};
gameAnimation.start();
stage.setScene(scene);
stage.show();
}
/**
* changes velocity so that the bubble goes to the right
*/
void moveBubbleRight() {
bubbleVelocityX = bubbleSpeedX;
}
/**
* changes velocity so that the bubble goes to the left
*/
void moveBubbleLeft() {
bubbleVelocityX =-bubbleSpeedX;
}
void moveBubbleDown() {
bubbleSpeedY += 5;
bubbleVelocityY = bubbleSpeedY;
}
void moveBubbleUp() {
bubbleSpeedY -= 5;
bubbleVelocityY = -bubbleSpeedY;
}
/**
* updates the pos of the bubble depending on the velocity,
* looks if it's about to leave the border,
* and sets it on the edge if it is
*
* @param timestamp helps calculate the time that has passed since the last update / frame
*/
private void update(long timestamp) {
if (lastUpdateTime > 0) {
final double elapsedSeconds = (timestamp - lastUpdateTime) / 1_000_000_000.0 ;
//bubble
//calculates YPos of bubble
//changes which method should be called, if the ball has left the border
//and sets him on the edge of it
if (bubble.getTranslateY()>=heightPane-radiusBubble) {
bubble.setTranslateY(heightPane-radiusBubble);
moveDown=false;
} else if (bubble.getTranslateY() <= maxHeight) {
bubble.setTranslateY(maxHeight);
moveDown=true;
}
if (moveDown) {
moveBubbleDown();
} else {
moveBubbleUp();
}
final double deltaYBubble = elapsedSeconds * bubbleVelocityY;
bubble.setTranslateY(bubble.getTranslateY() + deltaYBubble);
//calculates XPos of Bubble
if (bubble.getTranslateX() >= widthPane - radiusBubble) {
bubble.setTranslateX(widthPane - radiusBubble);
moveRight=false;
} else if (bubble.getTranslateX() - radiusBubble <= 0) {
moveRight=true;
}
if (moveRight) {
moveBubbleRight();
} else {
moveBubbleLeft();
}
final double deltaXBubble = elapsedSeconds * bubbleVelocityX;
bubble.setTranslateX(bubble.getTranslateX() + deltaXBubble);
}
lastUpdateTime=timestamp;
}
public static void main(String[] args) {
launch(args);
}
}
感谢大家的帮助,因为我对编码还不是很熟悉,而且我认为这个问题远远超出了我的代码知识范围。好吧,也许这是我忽略的一个愚蠢的小错误,这会毁了一切。
这与你撞到“地板”时的速度有关。简单的时间更改可以使它不会发生。我认为速度是这样的,气泡不能正确地离开地板,所以它被卡住了,触发了撞到地板的情况。我在 moveUp/Down 调用后立即添加了垂直气泡速度的打印,然后它不再卡住了!
我对您的代码做了一些小改动以简化垂直移动,现在情况似乎更好了:
package Whosebug.answers.demo;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Main extends Application {
//Global Variables
private static final int widthPane = 1000;
private static final int heightPane = 650;
long lastUpdateTime = 0;
//canvas
private Pane root = new Pane();
//Enemy
double bubbleAccelerationY = 300;
double bubbleSpeedY = 30;
double bubbleVelocityY = bubbleSpeedY;
final int bubbleSpeedX = 200;
int bubbleVelocityX = 0;
int radiusBubble = 25;
boolean moveDown = true;
boolean moveRight = true;
int maxHeight = 50;
private Circle bubble = new Circle(radiusBubble, Color.CADETBLUE);
private Parent createContent() {
root.setPrefSize(widthPane, heightPane);
root.getChildren().addAll(bubble);
return root;
}
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
bubble.setTranslateY(maxHeight);
bubble.setTranslateX((int) (Math.random() * widthPane));
Scene scene = new Scene(createContent());
final AnimationTimer gameAnimation = new AnimationTimer() {
@Override
public void handle(long timestamp) {
update(timestamp);
}
};
gameAnimation.start();
stage.setScene(scene);
stage.show();
}
/**
* changes velocity so that the bubble goes to the right
*/
void moveBubbleRight() {
bubbleVelocityX = bubbleSpeedX;
}
/**
* changes velocity so that the bubble goes to the left
*/
void moveBubbleLeft() {
bubbleVelocityX = -bubbleSpeedX;
}
void accelerateBubble(double secs) {
bubbleVelocityY += (secs * bubbleAccelerationY);
}
void bounceBubble() {
bubbleVelocityY = -bubbleVelocityY;
}
/**
* updates the pos of the bubble depending on the velocity, looks if it's about to leave the border, and sets it on
* the edge if it is
*
* @param timestamp helps calculate the time that has passed since the last update / frame
*/
private void update(long timestamp) {
if (lastUpdateTime > 0) {
final double elapsedSeconds = (timestamp - lastUpdateTime) / 1_000_000_000.0;
//bubble
//calculates YPos of bubble
//changes which method should be called, if the ball has left the border
//and sets him on the edge of it
if (bubble.getTranslateY() >= heightPane - radiusBubble) {
bubble.setTranslateY(heightPane - radiusBubble);
bounceBubble();
} else if (bubble.getTranslateY() <= maxHeight) {
bubble.setTranslateY(maxHeight);
}
accelerateBubble(elapsedSeconds);
final double deltaYBubble = elapsedSeconds * bubbleVelocityY;
bubble.setTranslateY(bubble.getTranslateY() + deltaYBubble);
//calculates XPos of Bubble
if (bubble.getTranslateX() >= widthPane - radiusBubble) {
bubble.setTranslateX(widthPane - radiusBubble);
moveRight = false;
} else if (bubble.getTranslateX() - radiusBubble <= 0) {
moveRight = true;
}
if (moveRight) {
moveBubbleRight();
} else {
moveBubbleLeft();
}
final double deltaXBubble = elapsedSeconds * bubbleVelocityX;
bubble.setTranslateX(bubble.getTranslateX() + deltaXBubble);
}
lastUpdateTime = timestamp;
}
}
所以我做了一个小程序,其中我有一个球,它应该在跌落时缓慢加速,并在再次跳起时缓慢减速。同时它应该向左和向右移动,基本上是左右弹跳。
我现在遇到的问题是,当球击中 canvas 底部时,应该使球改变 y 轴速度的方法停止改变代数符号,在第一次成功 jump/bounce 球在底部出现故障。
我尝试打印一些东西,如果它进入函数 moveBubbleUp() 并且它在屏幕底部出现故障并且应该向上移动时打印出来再次,为什么代数符号不会改变?打印速度时,它变得越来越大,即使 moveBubbleUp() 中有 bubbleVelocity-=5。
所以该方法被调用,通过在它进入时打印一个随机字符串来证明,但没有做任何我想要它做的事情,同时也完全按照它的对应 moveBubbleDown() 应该做的。 当故障发生时它不会被调用,因为我也尝试在那里打印一些东西。
改变速度的方法如下:
void moveBubbleDown() {
bubbleSpeedY += 5;
bubbleVelocityY = bubbleSpeedY;
}
void moveBubbleUp() {
bubbleSpeedY -= 5;
bubbleVelocityY = -bubbleSpeedY;
}
这里是调用函数然后根据函数更改 y-Pos 的方法:
//calculates YPos of bubble
//changes which method should be called, if the ball has left the border
//and sets him on the edge of it
if (bubble.getTranslateY()>=heightPane-radiusBubble) {
bubble.setTranslateY(heightPane-radiusBubble);
moveDown=false;
} else if (bubble.getTranslateY() <= maxHeight) {
bubble.setTranslateY(maxHeight);
moveDown=true;
}
if (moveDown) {
moveBubbleDown();
} else {
moveBubbleUp();
}
final double deltaYBubble = elapsedSeconds * bubbleVelocityY;
bubble.setTranslateY(bubble.getTranslateY() + deltaYBubble);
为了不遗漏任何内容,我将 post 其余代码,以便您也可以自己尝试:
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Main extends Application {
//Global Variables
private static final int widthPane = 1000;
private static final int heightPane = 650;
long lastUpdateTime = 0;
//canvas
private Pane root = new Pane();
//Enemy
int bubbleSpeedY = 30;
int bubbleVelocityY = bubbleSpeedY;
final int bubbleSpeedX = 200;
int bubbleVelocityX = 0;
int radiusBubble = 25;
boolean moveDown=true;
boolean moveRight=true;
int maxHeight = 50;
private Circle bubble = new Circle(radiusBubble, Color.CADETBLUE);
private Parent createContent() {
root.setPrefSize(widthPane, heightPane);
root.getChildren().addAll(bubble);
return root;
}
@Override
public void start(Stage stage) throws Exception{
bubble.setTranslateY(maxHeight);
bubble.setTranslateX((int)(Math.random()*widthPane));
Scene scene = new Scene(createContent());
final AnimationTimer gameAnimation = new AnimationTimer() {
@Override
public void handle(long timestamp) {
update(timestamp);
}
};
gameAnimation.start();
stage.setScene(scene);
stage.show();
}
/**
* changes velocity so that the bubble goes to the right
*/
void moveBubbleRight() {
bubbleVelocityX = bubbleSpeedX;
}
/**
* changes velocity so that the bubble goes to the left
*/
void moveBubbleLeft() {
bubbleVelocityX =-bubbleSpeedX;
}
void moveBubbleDown() {
bubbleSpeedY += 5;
bubbleVelocityY = bubbleSpeedY;
}
void moveBubbleUp() {
bubbleSpeedY -= 5;
bubbleVelocityY = -bubbleSpeedY;
}
/**
* updates the pos of the bubble depending on the velocity,
* looks if it's about to leave the border,
* and sets it on the edge if it is
*
* @param timestamp helps calculate the time that has passed since the last update / frame
*/
private void update(long timestamp) {
if (lastUpdateTime > 0) {
final double elapsedSeconds = (timestamp - lastUpdateTime) / 1_000_000_000.0 ;
//bubble
//calculates YPos of bubble
//changes which method should be called, if the ball has left the border
//and sets him on the edge of it
if (bubble.getTranslateY()>=heightPane-radiusBubble) {
bubble.setTranslateY(heightPane-radiusBubble);
moveDown=false;
} else if (bubble.getTranslateY() <= maxHeight) {
bubble.setTranslateY(maxHeight);
moveDown=true;
}
if (moveDown) {
moveBubbleDown();
} else {
moveBubbleUp();
}
final double deltaYBubble = elapsedSeconds * bubbleVelocityY;
bubble.setTranslateY(bubble.getTranslateY() + deltaYBubble);
//calculates XPos of Bubble
if (bubble.getTranslateX() >= widthPane - radiusBubble) {
bubble.setTranslateX(widthPane - radiusBubble);
moveRight=false;
} else if (bubble.getTranslateX() - radiusBubble <= 0) {
moveRight=true;
}
if (moveRight) {
moveBubbleRight();
} else {
moveBubbleLeft();
}
final double deltaXBubble = elapsedSeconds * bubbleVelocityX;
bubble.setTranslateX(bubble.getTranslateX() + deltaXBubble);
}
lastUpdateTime=timestamp;
}
public static void main(String[] args) {
launch(args);
}
}
感谢大家的帮助,因为我对编码还不是很熟悉,而且我认为这个问题远远超出了我的代码知识范围。好吧,也许这是我忽略的一个愚蠢的小错误,这会毁了一切。
这与你撞到“地板”时的速度有关。简单的时间更改可以使它不会发生。我认为速度是这样的,气泡不能正确地离开地板,所以它被卡住了,触发了撞到地板的情况。我在 moveUp/Down 调用后立即添加了垂直气泡速度的打印,然后它不再卡住了!
我对您的代码做了一些小改动以简化垂直移动,现在情况似乎更好了:
package Whosebug.answers.demo;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Main extends Application {
//Global Variables
private static final int widthPane = 1000;
private static final int heightPane = 650;
long lastUpdateTime = 0;
//canvas
private Pane root = new Pane();
//Enemy
double bubbleAccelerationY = 300;
double bubbleSpeedY = 30;
double bubbleVelocityY = bubbleSpeedY;
final int bubbleSpeedX = 200;
int bubbleVelocityX = 0;
int radiusBubble = 25;
boolean moveDown = true;
boolean moveRight = true;
int maxHeight = 50;
private Circle bubble = new Circle(radiusBubble, Color.CADETBLUE);
private Parent createContent() {
root.setPrefSize(widthPane, heightPane);
root.getChildren().addAll(bubble);
return root;
}
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
bubble.setTranslateY(maxHeight);
bubble.setTranslateX((int) (Math.random() * widthPane));
Scene scene = new Scene(createContent());
final AnimationTimer gameAnimation = new AnimationTimer() {
@Override
public void handle(long timestamp) {
update(timestamp);
}
};
gameAnimation.start();
stage.setScene(scene);
stage.show();
}
/**
* changes velocity so that the bubble goes to the right
*/
void moveBubbleRight() {
bubbleVelocityX = bubbleSpeedX;
}
/**
* changes velocity so that the bubble goes to the left
*/
void moveBubbleLeft() {
bubbleVelocityX = -bubbleSpeedX;
}
void accelerateBubble(double secs) {
bubbleVelocityY += (secs * bubbleAccelerationY);
}
void bounceBubble() {
bubbleVelocityY = -bubbleVelocityY;
}
/**
* updates the pos of the bubble depending on the velocity, looks if it's about to leave the border, and sets it on
* the edge if it is
*
* @param timestamp helps calculate the time that has passed since the last update / frame
*/
private void update(long timestamp) {
if (lastUpdateTime > 0) {
final double elapsedSeconds = (timestamp - lastUpdateTime) / 1_000_000_000.0;
//bubble
//calculates YPos of bubble
//changes which method should be called, if the ball has left the border
//and sets him on the edge of it
if (bubble.getTranslateY() >= heightPane - radiusBubble) {
bubble.setTranslateY(heightPane - radiusBubble);
bounceBubble();
} else if (bubble.getTranslateY() <= maxHeight) {
bubble.setTranslateY(maxHeight);
}
accelerateBubble(elapsedSeconds);
final double deltaYBubble = elapsedSeconds * bubbleVelocityY;
bubble.setTranslateY(bubble.getTranslateY() + deltaYBubble);
//calculates XPos of Bubble
if (bubble.getTranslateX() >= widthPane - radiusBubble) {
bubble.setTranslateX(widthPane - radiusBubble);
moveRight = false;
} else if (bubble.getTranslateX() - radiusBubble <= 0) {
moveRight = true;
}
if (moveRight) {
moveBubbleRight();
} else {
moveBubbleLeft();
}
final double deltaXBubble = elapsedSeconds * bubbleVelocityX;
bubble.setTranslateX(bubble.getTranslateX() + deltaXBubble);
}
lastUpdateTime = timestamp;
}
}