I am making a game, I have got several different classes as I dont like to put everything in one. I have a GameView class and a players class. The problem is that I am calling a method in players class from GameView. But its giving me an null pointer error. Below is my code:
GameVie class:
Panel p2 = new Panel();
p2.setLayout(new BorderLayout());
JLabel player1Lbl = new JLabel("Player 1");
p2.add(player1Lbl, BorderLayout.WEST);
player.enterNameP1(); //Having an error here.
player1Lbl.setText(player.enterNameP1());
Players Class:
public class Players
{
//storing the player 1 name
private String p1name;
//storing the player 2 name
private String p2name;
/**
* Constructor for objects of class Players
*/
public Players()
{
this.p1name = p1name;
this.p2name = p2name;
}
/**
*Enter the player 1 name in a dialog box
*/
public String enterNameP1() //It was public void before but it wasnt accepting a void method in the gameView so I changed it to String
{
this.p1name = JOptionPane.showInputDialog("Please enter player 1 name","Specify name");
return p1name;
}
you should initialized player first..... ?
Players player = new Players();
Your player isn't initialised at the moment you call:
player.enterNameP1(); //Having an error here.
To solve this, you have to make sure that the reference player actually points to a real instance of Player. This should be done by adding at a logic place in your code this:
player = new Players();
That is the reason why you got a NullPointerException. When you call a method from a specific object, the object must be initialised (which means that the pointer player points to an actual instance of the class Players).
You did not instantiated player
So it is null causing a NPE
Related
I am currently working on my exam-project for uni. The task is to create the boardgame ludo. After writing some code and doing some testing, I ran into a StackOverflowError.
So here is the structure (5 classes are essential):
Main.class GUI.class Game.class Player.class Piece.class
Main creates a new object of type GUI called mainGUI. This creates the visuals for the game, including a small settings area with a start button.
On the press of the Start button, a new object of the type Game is created which then creates 4 new Objects of the type Player (4 players obviously).
When creating an object of type Player, this type gets the argument 'nmbr' which just states the Number of the Player (Player1, Player2 and so on).
Each Player has 4 pieces to move around on the board, so each of those 4 Players create another 4 objects of type Piece.
Now when pressing the Start button, what should happen is, that the pieces are displayed on the board. But that doesn't happen. Instead I get an errormessage stating, that there is a StackOverflowError on the call of the first Player object.
So I tried to read into the behaviour of Object creation in java and StackOverflow and stuff like that. But the only conclusion I can get right here, is that I've created too many objects inside one another.
public class Main {
public static void main(String[] args){
Main start = new Main();
start.activate();
}
static GUI mainGui;
public Main() {
mainGui = new GUI();
}
Inside the GUI there is the JButton 'submit'
This button is supposed to start the game by creating the an object of the type Game.
submit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object btn = e.getSource();
boolean ACTIVE = ((JButton) btn).isEnabled();
if (ACTIVE) {
submit.setVisible(false);
cancel.setVisible(true);
Game spiel = new Game();
spiel.begin();
}
}
});
public class Game {
public Game() {
}
Player player1 = new Player(1); //this is where the Error occurs
Player player2 = new Player(2);
Player player3 = new Player(3);
Player player4 = new Player(4);
}
etc.
public class Player extends Game {
private String name;
private Color color;
private boolean artiPlayer;
private int playerNmbr, start, end;
private int[] startArea, endArea;
Piece piece1, piece2, piece3, piece4;
public Player(int nmbr){
if (nmbr == 1) {
System.out.println("1.1");
piece1 = new Piece(500,175, Color.BLUE, Main.mainGui);
piece2 = new Piece(550, 175, Color.BLUE, Main.mainGui);
piece3 = new Piece(500,125, Color.BLUE, Main.mainGui);
piece4 = new Piece(550, 125, Color.BLUE, Main.mainGui);
start = 0;
end = 64;
}
}
Type Piece => Piece(xPos, yPos, Color, GUI)
//and so on
Here is the exact error message:
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
at spielPackage.Player.<init>(Player.java:18)
at spielPackage.Game.<init>(Game.java:9)
Sorry if the code is a bit unclean. I am fairly new to java and this is still a work in progress.
At this point I am lost as to why Java throws a StackOverflowError
Your Player should not extend Game since a Player is not a Game.
Right now you create a game which creates four players with every one of them being a different "Game" and creating four more players which are games and create four new players each......
public class DictionaryClient implements ActionListener {
JFrame frame = new JFrame("Amazing CW");
JPanel panel = new JPanel();
JButton button = new JButton("Send");
JTextField text = new JTextField("Field");
Book book;
DictionaryService port;
public DictionaryClient() {
panel.add(button);
panel.add(text);
frame.add(panel);
button.addActionListener(this);
frame.setSize(300,300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args){
DictionaryClient client = new DictionaryClient();
DictionaryServiceService service = new DictionaryServiceService();
DictionaryService port = service.getDictionaryServicePort();
Book book = port.sendBook();
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button){
System.out.print(book.getAuthor() + " " + book.getTitle());
}
}
}
I understand what a NullPointerException is but don't understand by my code is giving me this error, when I move the
System.out.print(book.getAuthor() + " " + book.getTitle());
out of the actionPerformed I get no issue at all.
Book book = port.sendBook();
Creates a local variable named book. It does not affect the field book in your DictionaryClient class, which keeps its default value of null. Change it to this:
client.book = port.sendBook();
That will assign the value to the correct field on your DictionaryClient object.
As it is now, that value is lost as soon as the main method ends and the local variable goes out of scope. When you moved the print into the main method, it was able to reference the local variable but, in your actionPerformed method the only book in scope was the field, which was never initialized.
Your Book object only has local scope in the main method. You need to change its scope to be local to the class (which you've already referenced).
Simply change this line
Book book = port.sendBook();
to
client.book = port.sendBook();
This will set the class level book variable correctly. Your actionPerformed method will then refer to that instance variable accordingly.
Check this out:
the following declaration/initialization
Book book = port.sendBook();
was made inside of the static main method, and since your class DictionaryClient has a member with the same name, then this object in the main method is shadowing the book of the DictionaryClient, when the actionPerformed is triggered, you are not in the static main anymore, so you book defined and well initialized there is back for good...
the only book available in that scope is the defined in the class...
but is was never initialized therefore a NPE.
I am making a game in Java and I have a central(Engine) class which will render the scenery/player/etc.
In the Engine class I create my player object like so
public class Engine() {
public static Player player;
public Engine() {
RenderPlayer();
}
protected static void RenderPlayer() {
player = new Player();
}
}
I also have a Canvas class which handles the drawing of the player.
I want to be able to call the Players functions without having to create a new instance( since I created the player in the Engine class ). Whenever I try to use a function from the player, I get a null pointer expection.
This is how I call it.
Engine.player.tick();
I have spent a couple hours trying to figure it out, May someone tell me what I am doing wrong, and help me in the right direction? Thank you.
You need to call Engine.RenderPlayer() prior calling Engine.player.tick(); as this method assigns a new Player instance to the static player attribute. Before you call this method player is null and it is causing your NullPointerException.
You can fix this issue by simply changing:
public static Player player;
to:
public static Player player = new Player();
player is null if you never create an instance of Engine because RenderPlayer() is in the constructor of Engine.
You could just do
public static Player player = new Player();
or make sure to call RenderPlayer() explicitly before accessing player.
So I have this code:
package com.erikbalen.game.rpg;
import com.erikbalen.platform.*;
import javax.swing.JFrame;
public class World extends Engine {
public static void main(String[] args) {
Gui display = new Gui(/*takes a Player argument so i can get certain variables*/);
display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
display.setSize(300,220);
display.setVisible(true);
Player player1 = new Dps("ebalen", display);
Player player2 = new Healer("frankypanky", display);
}
}
package com.erikbalen.game.rpg;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Gui extends JFrame implements ActionListener {
/**
*
*/
private static final long serialVersionUID = -384241835772507459L;
private JLabel playerInfo;
private JTextField textField;
private final static String newline = "\n";
private JTextArea feed;
private JScrollPane scrollPane;
private Player player;
public Gui(Player currentPlayer) {
super("Erik's RPG");
this.player = currentPlayer;
setLayout(new FlowLayout());
playerInfo = new JLabel("<html>Health = " + currentPlayer.getHealth() + " | " + "Mana = " + currentPlayer.getMana() + "</html>");
playerInfo.setBorder(BorderFactory.createTitledBorder(currentPlayer.getName()));
textField = new JTextField(20);
textField.addActionListener(this);
feed = new JTextArea(5, 20);
scrollPane = new JScrollPane(feed);
feed.setEditable(false);
add(playerInfo);
add(feed);
add(textField);
add(scrollPane);
}
public void actionPerformed(ActionEvent textBox) {
String text = textField.getText();
this.player.chat(text);
}
public void printText(String text) {
feed.append(text + "\n");
feed.setCaretPosition(feed.getDocument().getLength());
}
}
My problem is that class Gui takes a Player as an argument and Player takes Gui as an argument. How do I let both objects take each other as arguments? Feel free to tell me if my code is inefficient.
Well, ideally you should try to break the circular dependency, but otherwise, you could:
Create the GUI, create the players by passing in the GUI, then add the players to the GUI
Create the players, create the GUI by passing in the players, then set the GUI for the players
Create the GUI within the player constructor:
Player(String name)
{
GUI gui = new GUi(this);
...
}
All of these are non-ideal:
You may well want your classes to be immutable, which makes the first two options nasty
Publishing the this reference before your constructor has finished executing has various issues, both in terms of thread safety and the memory model, as well as potentially allowing the GUI constructor to call back to the Player object before it's fully initialized.
This goes back to "try to break the dependency" - but if that's really impossible, I would probably favour the first option, without knowing anything else. It makes sense to be able to add players to a game - it makes less sense to set the GUI for a player after the fact, IMO.
Your stuck in what we call a circular dependency. This is almost everytime the result of a bad design.
There are still solutions, but there are not really pretty. For an elegant way, you should rethink your design.
Does the GUI really need the player ? Maybe you could create a method to set the player later on. If it's not possible, you could also create a setter in the player. You won't be able to set both at construction time.
Try giving the Gui class methods for updating what is displayed to the user/users. Make the directing code (main() for example) responsible for updating the Gui with the right information as events happen.
Neither Gui nor Player should have to take each other as constructor arguments - Gui should only be responsible for displaying information it is told to, and Player should only be a logical representation of a game piece. Event-driven functionality should be reserved for the directing code.
I'm trying to create a blackjack program for my final project in Java. I'm still very new to Java and OOD so I apologize if my problem seems very trivial to you :(
How my program works: I have three classes so far.
main.java
This class builds my frame and runs all the other methods.
cards.java
This class creates an array that holds the card values and location to picture. I have a for loop in there that auto-populates it.
hits.java
This class is meant to "randomly" generate a number that will represent the chosen card. The way this works is by taking the randomly created int and pointing it to a matching index location on the array.
I assign the value to string objects that I then try to add to a jlabel and then add that jlabel to my main frame. The code is as follows:
hits.java
// Import necessary classes.
import java.util.Random;
public class hits {
// Create random object.
Random rand = new Random();
// Declare variables.
int card;
String cardVal, cardPic;
// Instantiate the needed classes.
main s = new main();
cards t = new cards();
// Constructor for the class.
public hits() {
// Randomly generate a number (0 - 9).
card = rand.nextInt(10);
// Populate the array.
t.runCards();
// Assign the cards according to the num. generated.
cardVal = t.deck[card][0];
cardPic = t.deck[card][1];
}
// Run Method
public void runHits() {
// Add the card chosen to the GUI.
s.a.setText("hello");
s.dealerCards.add(s.a);
}
}
I have "hello" as the text for the label because I wanted to see if perhaps my array was not populating, but even that doesn't work. If it helps here is my main.java as well (constructor and main method):
// Constructor for the main class.
public main() {
// Setup the MAIN container.
f1.getContentPane().setLayout(new GridLayout(0, 1));
f1.setSize(200, 200);
f1.add(dealerName);
f1.add(dealerCards);
f1.add(userCards);
f1.add(userName);
// Setup the inner panels.
dealerCards.setLayout(new GridLayout(1, 2));
dealerCards.add(b);
userCards.setLayout(new GridLayout(1, 6));
userCards.add(c);
userCards.add(d);
}
// Build the frame.
public void GUILaunch() {
// Display Frame
f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f1.setVisible(true);
}
// Main method.
public static void main(String args[]) {
// Distribute the dealer's/player's starting hands.
hits deal = new hits();
deal.runHits();
// Launch the GUI
main gui = new main();
gui.GUILaunch();
}
Hopefully I have provided enough information to help you understand what's going on here. So to sum it all up: how can i add my jlabel(from another class) holding the randomly selected card to my main frame
Thanks in advance.
The deal.runHits() adds a label to the Main object that deal owns rather than the gui object.
I would suggest the following :
Make your main class have an instance of hits and hits have an instance of the cards object...
so you get something like this
public class main {
private hits hits_instance
//constructor
main(){ hits_instance = new hits(); }
//this method will add your cards
public void addCards(){
// frame = whatever frame you are using
frame.add(hits_instance.getCards());
}
}
public class hits {
private cards cards_instance;
hits(){ cards_instance= new cards();}
public JLabel getCards() {return cards_instance.getCard(randomNumber);}
}