I am making a simple game on JavaFX right now.
The picture of my program is here
So far, my code is generating random monsters using a random number generator, and my health will decrease a random number each time I hit the explore button.
I also added a stats box. This box will display my current health, hunger, and hydration levels.
My problem is, is that I am not sure how I am supposed to change the values in my stats box. Every time my character gets hit by a monster, I want the health text to change. When I do :
dStatBox.setText(mainCharacter.getHealthLevel());
It says that I must convert the int to a string. How can I go about doing this?
My whole code is below:
import java.util.Random;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
public class Game extends Application {
public static TextArea dialogue = new TextArea();
public static TextArea dStatBox = new TextArea();
Button exploreButton;
Random r = new Random();
int ogreDamage = r.nextInt(20) + 1;
public void start(Stage primaryStage) {
Character mainCharacter = new Character("Nikki");
BorderPane pane = new BorderPane();
HBox top = new HBox();
VBox gameBox = new VBox();
VBox explore = new VBox();
VBox statBox = new VBox();
exploreButton = new Button("Explore");
Label stats = new Label("Stats");
stats.setFont(Font.font(30));
stats.setFont(Font.font("Helvetica", FontWeight.BOLD, FontPosture.REGULAR, 24));
statBox.setPadding(new Insets(10,10,10,10));
statBox.setSpacing(10);
statBox.setMaxHeight(300);
statBox.setPrefWidth(300);
statBox.getChildren().addAll(stats, dStatBox);
statBox.setAlignment(Pos.TOP_CENTER);
dStatBox.setEditable(false);
dStatBox.setText("Health: 100/100\n");
Label label = new Label("Game Dialogue");
label.setFont(Font.font(30));
label.setFont(Font.font("Helvetica", FontWeight.BOLD, FontPosture.REGULAR, 24));
gameBox.setPadding(new Insets(10,10,10,10));
gameBox.setSpacing(10);
dialogue.setMaxHeight(200);
dialogue.setMaxWidth(470);
dialogue.setWrapText(true);
dialogue.setEditable(false);
gameBox.getChildren().addAll(label, dialogue, exploreButton);
gameBox.setAlignment(Pos.CENTER);
top.getChildren().addAll(gameBox, statBox);
top.setAlignment(Pos.TOP_LEFT);
pane.setTop(top);
dialogue.appendText("Welcome to Wild Berries - the Ultimate Survival Game\n");
dialogue.appendText("How long can you survive for? Only time will tell...\n");
exploreButton.setOnAction(e -> {
Random r = new Random();
int ogreDamage = r.nextInt(20) + 1;
int randomInt = r.nextInt(3) + 1;
dialogue.appendText("You begin to explore the wild...\n");
if(randomInt == 1) {
dialogue.appendText("A wild Ogre has appeared!\n");
dialogue.appendText("You have been hurt. -" + ogreDamage + " HP.\n");
mainCharacter.setHealthLevel(mainCharacter.getHealthLevel() - ogreDamage);
dialogue.appendText(mainCharacter.getHealthLevel());
if(mainCharacter.getHealthLevel() <= 0) {
dialogue.appendText("You have died. Thank you for playing.");
}
}
if(randomInt == 2) {
dialogue.appendText("A wild Goblin has appeared!\n");
}
if(randomInt == 3) {
dialogue.appendText("A wild Ghost has appeared!\n");
}
});
Scene scene = new Scene(pane, 800, 450);
primaryStage.setScene(scene);
primaryStage.setTitle("Wild Berries GUI");
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
I'm assuming that mainCharacter.getHealthLevel() is returning an int. You should do dStatBox.setText("Health: " + mainCharacter.getHealthLevel());
As simple as this:
int healthLevel = mainCharacter.getHealthLevel();
String.valueOf(healthLevel);
//or
Integer.toString(healthLevel);
Related
I am trying to use a text field to get an input which represents the radius to draw a circle.
I have tried creating the circle inside processreturn.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.control.TextField;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
public class Task5 extends Application {
int rad;
int x = 200;
private TextField input;
public void start(Stage stage) {
input = new TextField();
input.setPrefWidth(50);
input.setAlignment(Pos.CENTER);
input.setOnAction(this::processReturn);
System.out.print(rad);
Circle circle = new Circle();
// Setting the properties of the circle
circle.setCenterX(x);
circle.setCenterY(200);
circle.setRadius(rad);
// Creating a Group object
Group root = new Group(circle, input);
// Creating a scene object
Scene scene = new Scene(root, 600, 300, Color.LIGHTBLUE);
// Setting title to the Stage
stage.setTitle("Drawing a Circle");
// Adding scene to the stage
stage.setScene(scene);
// Displaying the contents of the stage
stage.show();
System.out.print(rad);
}
public void processReturn(ActionEvent event) {
rad = Integer.parseInt(input.getText());
System.out.println("rad is" + rad);
}
}
Currently it seems that the variable rad is changing but it is not updating the circle in the Group instance. Is it possible to update the group or create another group that has a the circle with the updated rad?
I have a problem with a rotation of a usercontrol in javafx. My setup is as follows:
I have a scene with in the center a 400 by 600 scrollpanel called scrollpane, later populated dynamically with a vbox that contains a list of labels with text.
What I want to do is add a rotation on this panel to make it look like the starwars introduction text. I've managed to get the animation that scrolls through the text working, but when trying to rotate the panel over the X_AXIS it won't do as I want.
Goal: Panel that is rotated as if it was this text
Currently My best attempt after spending hours transforming:
scrollpane.getTransforms().add(new Rotate(50, 300, 200, 20, Rotate.X_AXIS));
As you can see the text is aimed at the proper angle, but the control itself is not actually 3d rotated over the X-axis.
What do I need to add in order to go from what I currently have to the desired effect?
(That the top of the panel in absolute pixels is less wide compared to the bottom).
You've rotated it backwards; probably you're not seeing the rotation because you have something else wrong in your code.
This works for me:
import javafx.application.Application;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.text.Font;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
public class StarWarsScrollPane extends Application {
private final String text = "It is a period of civil war. Rebel spaceships, "
+ "striking from a hidden base, have won their first victory against the evil Galactic Empire."
+ " During the battle, Rebel spies managed to steal secret plans to the Empire's ultimate weapon,"
+ " the DEATH STAR, an armored space station with enough power to destroy an entire planet."
+ " Pursued by the Empire's sinister agents, Princess Leia races home aboard her starship,"
+ " custodian of the stolen plans that can save her people and restore freedom to the galaxy....";
#Override
public void start(Stage primaryStage) {
Label label = new Label(text);
label.setWrapText(true);
label.setFont(Font.font(18));
ScrollPane crawler = new ScrollPane(label);
crawler.setVbarPolicy(ScrollBarPolicy.NEVER);
crawler.setFitToWidth(true);
crawler.getTransforms().add(new Rotate(-50, 300, 200, 20, Rotate.X_AXIS));
Scene scene = new Scene(crawler, 400, 400);
scene.setCamera(new PerspectiveCamera());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Note that if you really want a scrolling "crawl" of text, you don't really need a scroll pane, but you can just use a text node and translate it in an animation. If you do this, be sure to add the translation after you add the rotation: transforms are applied in reverse order (as though you are right-multiplying the affine transformation matrices).
Here's an example of this ;)
import java.util.Random;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Rectangle2D;
import javafx.scene.Cursor;
import javafx.scene.DepthTest;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.util.Duration;
public class StarWarsCrawler extends Application {
private final String text = "It is a period of civil war. Rebel spaceships, "
+ "striking from a hidden base, have won their first victory against the evil Galactic Empire.\n\n"
+ "During the battle, Rebel spies managed to steal secret plans to the Empire's ultimate weapon,"
+ " the DEATH STAR, an armored space station with enough power to destroy an entire planet.\n\n"
+ "Pursued by the Empire's sinister agents, Princess Leia races home aboard her starship,"
+ " custodian of the stolen plans that can save her people and restore freedom to the galaxy....";
#Override
public void start(Stage primaryStage) {
Rectangle2D primaryScreenBounds = Screen.getPrimary().getBounds();
int width = (int) primaryScreenBounds.getWidth() ;
int height = (int) primaryScreenBounds.getHeight() ;
Text textNode = createText(width);
Translate translate = new Translate();
textNode.getTransforms().add(new Rotate(-60, 300, height/2, height/30, Rotate.X_AXIS));
textNode.getTransforms().add(translate);
Timeline animation = new Timeline(
new KeyFrame(Duration.seconds(45), new KeyValue(translate.yProperty(), -10*height))
);
textNode.setTranslateY(2*height);
StackPane root = new StackPane();
generateStarField(width, height, root);
root.getChildren().add(textNode);
Scene scene = createScene(root);
primaryStage.setFullScreenExitHint("");
primaryStage.setFullScreen(true);
primaryStage.setScene(scene);
primaryStage.show();
animation.play();
animation.setOnFinished(e -> Platform.exit());
}
private Scene createScene(StackPane root) {
Scene scene = new Scene(root, Color.BLACK);
PerspectiveCamera camera = new PerspectiveCamera();
camera.setDepthTest(DepthTest.ENABLE);
scene.setCamera(camera);
scene.setCursor(Cursor.NONE);
scene.setOnMouseClicked(e -> {
if (e.getClickCount() ==2) {
Platform.exit();
}
});
return scene;
}
private Text createText(int width) {
Text textNode = new Text(text);
textNode.setWrappingWidth(width*1.25);
textNode.setFont(Font.font("Franklin Gothic", width/12));
textNode.setFill(Color.rgb(229, 177, 58));
return textNode;
}
private void generateStarField(int width, int height, StackPane root) {
int numStars = width * height / 900 ;
Random rng = new Random();
for (int i = 1 ; i <= numStars ; i++) {
double hue = rng.nextDouble() * 360 ;
double saturation = rng.nextDouble() * 0.1 ;
Color color = Color.hsb(hue, saturation, 1.0);
Circle circle = new Circle(rng.nextInt(width), rng.nextInt(height), 2*rng.nextDouble(), color);
circle.setManaged(false);
circle.setTranslateZ(rng.nextDouble() * height * 1.25);
root.getChildren().add(circle);
}
}
public static void main(String[] args) {
launch(args);
}
}
I'm new to javaFX and I wanted to make a simple code that counted how many times a person pressed a button and displayed the count on the application itself. Currently I have my code printing the counter in my IDE and would just like to some how attach it to the scene(eg I click run and every time I click the button it prints how many times I've clicked it in my workbench). I looked around stack overflow and youtube but the closest I got to what I was looking for was printing it in my IDE. Thanks for any help.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class JavaFXTest extends Application {
private int counter = 0;
public static void main (String [] args){
Application.launch();
}
#Override
public void start(Stage primaryStage) throws Exception {
Stage stage = new Stage();
stage = primaryStage;
Pane pane = new Pane();
pane.setPrefSize(400,400);
Button button = new Button("Smash it!");
HBox root = new HBox(5, pane);
button.setOnAction(e -> {
counter();
});
root.getChildren().add(button);
Scene scene1 = new Scene(root,1000, 800, Color.AQUA);
stage.setScene(scene1);
stage.setTitle("ButtonSmash!");
stage.show();
}
public void counter(){
counter++;
System.out.println(counter);
}
}
Here is the full code:
package StackOverFlow;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class JavaFXTest extends Application {
private int counter = 0;
private Label label = new Label("Count: ");
public static void main (String [] args){
Application.launch();
}
#Override
public void start(Stage primaryStage) throws Exception {
Stage stage = new Stage();
stage = primaryStage;
Pane pane = new Pane();
pane.setPrefSize(400,400);
Button button = new Button("Smash it!");
HBox root = new HBox(5, pane);
button.setOnAction(e -> {
label.setText("Count: "+Integer.toString(counter));
counter();
});
root.getChildren().add(button);
label.relocate(0, 0); // You can put this label, wherever you want!
root.getChildren().add(label);
Scene scene1 = new Scene(root,1000, 800, Color.AQUA);
stage.setScene(scene1);
stage.setTitle("ButtonSmash!");
stage.show();
}
public void counter(){
counter++;
//System.out.println(counter);
}
}
You had to make one label and to add it to your pane.getChildren();
And whenever you press the button you need to change text from that label.
My JavaFx code does not work as it should do. I am trying to create 10X10 text matrix populated with either a 1 or 0, so it looks similar to a 2d array filled with 1's and 0's. When I put the code that is currently in the MatrixPane class in main it works fine, but with this code it just sets the scene but it looks like no pane is added or created.
If anyone can help me I would greatly appreciate it.
I realize I have Imported some unused things, I am using them for other parts of the program.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.layout.FlowPane;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javafx.scene.shape.Arc;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.geometry.Pos;
import javafx.collections.ObservableList;
public class Button1 extends Application
{
public void start(Stage primaryStage)
{
GridPane pane = new GridPane();
MatrixPane Matrix = new MatrixPane();
pane.getChildren().add(Matrix);
Scene scene = new Scene(pane, 700, 500);
primaryStage.setTitle("1 window "); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
public static void main(String[] args)
{
Application.launch(args);
}
}
class MatrixPane extends Pane
{
double HEIGHT = 500;
double WIDTH = 200;
private GridPane pane1 = new GridPane();
public MatrixPane()
{
}
public void fillmatrix()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
TextField text = new TextField(Integer.toString((int)(Math.random() * 2)));
text.setMinWidth(WIDTH / 8.0);
text.setMaxWidth(WIDTH / 10.0);
text.setMinHeight(HEIGHT / 8.0);
text.setMaxHeight(HEIGHT / 10.0);
this.pane1.add(text, j, i);
}
}
}
}
Call fillMatrix(); method from Button1.start()
Add GridPane to MatrixPane in MatrixPane construcor
private GridPane pane1 = new GridPane();
public MatrixPane() {
getChildren().add(pane1);
}
This will work.
Well I checked your code and you are excessively using GridPane. First you have a class named MatrixPane which inherits Pane, but also this class has a property GridPane. Finally, you use GridPane once again to add MatrixPane!
So, what I did is to use composition, but first I change the start method
public void start(Stage primaryStage) {
GridPane pane = new GridPane();
MatrixPane Matrix = new MatrixPane();
//pane.getChildren().add(Matrix);
Matrix.fillmatrix();
Scene scene = new Scene(Matrix.getPane1(), 700, 500);
...
So here the scene is going to receive the data of pane1, this attribute has the values stored when fillmatrix was called.
Then I add the getter method in MatrixPane for the attribute pane1
class MatrixPane {
double HEIGHT = 500;
double WIDTH = 200;
private GridPane pane1 = new GridPane();
public GridPane getPane1() {
return pane1;
}
...
I have a TextField in my program that will have data entered by the user, but I also have a variable value somewhere else that I need to permanently display at the end of my TextField. It cannot disappear when the user enters any data in the TextField. Can anyone give me a good implementation? Thanks.
[UserInput (miles)]
**Above is an example of what I am talking about. "Miles" needs to always be in the TextField while the UserInput is changing.
EDIT: "Implementation" was a bad choice of words. Let me rephrase, I can set up the field myself, but I am having trouble finding a way to set permanent text in a textfield. Just wondering if anyone knows an easy way.
You could put a transparent textfield over a label and bind the 2 together. Something like this but with better styling.
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Text extends Application {
#Override
public void start(Stage primaryStage) {
TextField txtUser = new TextField();
txtUser.setStyle("-fx-background-color: transparent;-fx-border-color:blue;");
Label txtBG = new Label(" (miles)");
Label labelUser = new Label();
labelUser.textProperty().bind(txtUser.textProperty());
Label labelAll = new Label();
labelAll.textProperty().bind(Bindings.concat(
labelUser.textProperty())
.concat(txtBG.textProperty()));
StackPane sp = new StackPane();
sp.getChildren().addAll(txtBG, txtUser);
sp.setPrefSize(100, 12);
VBox root = new VBox();
root.getChildren().addAll(sp,labelUser,labelAll);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("transparent text test");
primaryStage.setScene(scene);
primaryStage.show();
}
}
I would use a HBox instead of a stack pane but it's one way to satisfy the requirement that "miles" is 'inside' the texfield's borders.
This is a small example doing what you want ! I have used the focus property of textfield to add and remove miles from it !
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TextBinding extends Application {
#Override
public void start(Stage primaryStage) {
final TextField user = new TextField();
TextField demo = new TextField();
user.setStyle("-fx-background-color: transparent;-fx-border-color:blue;");
user.focusedProperty().addListener(new ChangeListener<Boolean>()
{
#Override
public void changed(ObservableValue<? extends Boolean> arg0, Boolean oldPropertyValue, Boolean newPropertyValue)
{
if (newPropertyValue)
{
user.setText(user.getText().replace(" miles", ""));
}
else
{
user.setText(user.getText().concat(" miles"));
}
}
});
VBox root = new VBox();
root.getChildren().addAll(user,demo);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("transparent text test");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String args[]) {
launch(args);
}
}