Error using method from another class - java

I think this might be a scope issue but it's been bugging me for a while. Whenever I try to add ReplayData to the frame I recieve a null pointer error, nor can I use my add data method without it throwing a null pointer error. p.Setx is defintely setting the right values, but once it hits "replaydata.add" an error gets thrown and the loop cannot continue.
public ReplayData replayData;
frame = new JFrame();
frame.setBounds(100, 100, 1920, 1080);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
// ERROR HERE WHEN ADDING TO FRAME, APPLICATION RUNS FINE IF COMMENTED
//frame.add(replayData); // Add replay data to jframe
JButton button_KMeans = new JButton("View K-Means");
button_KMeans.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
kMeans.initialize();
kMeans.kMeanCluster();
kMeans.PrintResults();
//for (Point p : kMeans.getPoints() )
Point temp = new Point();
for (int i = 0; i < kMeans.TOTAL_DATA; i++)
{
//JOptionPane.showMessageDialog(new JFrame(),kMeans.TOTAL_DATA, "Dialog",
// JOptionPane.ERROR_MESSAGE);;
p.setX((int)TrackerData.getRecordNumber(i).getEyeX());
p.setY((int)TrackerData.getRecordNumber(i).getEyeY());
JOptionPane.showMessageDialog(new JFrame(),p.getX(), "Dialog",
JOptionPane.ERROR_MESSAGE);
JOptionPane.showMessageDialog(new JFrame(),p.getY(), "Dialog",
JOptionPane.ERROR_MESSAGE);
// GET ERROR HERE when adding these points to replayData. everything look fine in that class unless i'm missing something
// java.lang.NullPointerException at MainWindow$3.actionPerformed(MainWindow.java:189)
replayData.addPoint(p); // Add points to JPanel
}
//replayData.draw();
}
});
That is my button class, I get errors whenever I try to add data using my replaydata class
Heres the other 2 ReplayData + DataPoint class
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import javax.swing.JPanel;
public class ReplayData extends JPanel {
public ArrayList<DataPoint> points;
// Initialise records
public ReplayData()
{
points = new ArrayList<DataPoint>();
}
public void ReplaceData() {
points = new ArrayList<DataPoint>();
}
public void addPoint(DataPoint point) {
points.add(point);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (DataPoint p : points)
g.fillRect(p.x, p.y, 2, 2);
}
public void draw() {
repaint();
}
}
public class DataPoint{
public DataPoint(int X, int Y)
{
x = X;
y = Y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
int x,y;
}
Any help would be much appreciated.
Copy of my project if anyone wants to open it on eclipse (I've included the .csv you will need to get it working aswell in the zip) : http://www.filedropper.com/eyetrackeranalysis_1

You declare the variable:
public ReplayData replayData;
but never initialize it. Your line above is equivalent to this:
public ReplayData replayData = null;
You need to assign an object to the variable for it to be non-null.
public ReplayData replayData = new ReplayData();
More importantly, you need to learn the general concepts of how to debug a NPE (NullPointerException). You should critically read your exception's stacktrace to find the line of code at fault, the line that throws the exception, and then inspect that line carefully, find out which variable is null, and then trace back into your code to see why. You will run into these again and again, trust me.

Related

Slick2d how to check if a shape contains any object? Java

i'm new to Slick2d and to this page too, i tried asking the slick forums, but there aren't many people so i couldn't get an answer
Anyway, i've been trying to create a platformer engine in Slick2d java game library, and i was thinking of using the contains and intersects methods of the Shape class.
The thing is, if I want to check if a shape contains any object of any kind (or any object from a specific class), Is there a way to do that? all tutorials i've found explain how to test collision with one single shape, but what if i want to check for any object?
package juegoconslick;
import java.util.ArrayList;
import org.newdawn.slick.*;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Shape;
public class JuegoConSlick extends BasicGame {
Jugador player;
Input entrada;
Shape hitbox;
bloque bloq;
ArrayList<bloque> bloques = new ArrayList<>();
public JuegoConSlick(){
super("Mi prueba");
}
public static void main(String[] args) {
AppGameContainer juegito;
try{
juegito = new AppGameContainer(new JuegoConSlick());
juegito.setDisplayMode(630,400,false);
juegito.setMaximumLogicUpdateInterval(60);
juegito.setMaximumLogicUpdateInterval(50);
juegito.setAlwaysRender(true);
juegito.setVSync(true);
juegito.start();
}catch(Exception ex){
System.exit(0);
}
}
#Override
public void init(GameContainer gc) throws SlickException {
player = new Jugador();
hitbox = new Rectangle(player.X, player.Y, 10, 10);
bloq = new bloque(50,50,50,50);
}
#Override
public void update(GameContainer gc, int i) throws SlickException {
intersecta();
Input entrad = gc.getInput();
if(entrad.isKeyDown(Input.KEY_RIGHT) && player.X<600){
player.X+=3;
player.sprite.update(1);
hitbox.setX(player.X);
}
if(entrad.isKeyDown(Input.KEY_LEFT) && player.X>0){
player.X-=3;
player.sprite.update(1);
hitbox.setX(player.X);
}
if(entrad.isKeyDown(Input.KEY_UP) && player.Y>0){
player.Y-=3;
player.sprite.update(1);
hitbox.setY(player.Y);
}
if(entrad.isKeyDown(Input.KEY_DOWN) && player.Y<370){
player.Y+=3;
player.sprite.update(1);
hitbox.setY(player.Y);
}
}
#Override
public void render(GameContainer gc, Graphics grphcs) throws SlickException {
grphcs.draw(bloq.bloque);
grphcs.draw(hitbox);
}
public void intersecta(){
try{
if(hitbox.contains(null)){//i tried checking if it didnt contain any object,
}else{
System.exit(0);
}
}catch(Exception ex){
}
}
}
EDIT: i think i have found a solution, though im not sure if its the most efficient.
basiaclly, i'll save all objects of the same class in an ArrayList:
ArrayList<bloque> bloques = new ArrayList<>();
bloques.add(new bloque(50,50,100,100));
bloques.add(new bloque(100,100,100,100));
Then, what im going to do is check the entire arraylist each time i call the intersects method:
public boolean intersecta(){
boolean devuelve=false;
for(int i=0; i<bloques.size(); i++){
if(hitbox.intersects(bloques.get(i).bloque)){
devuelve=true;
}
}
return devuelve;
}
then im going to use the value i get from intersects to decide whether the player can move or not
public void update(GameContainer gc, int i) throws SlickException {
Input entrad = gc.getInput();
if(entrad.isKeyDown(Input.KEY_RIGHT) && player.X<600 && intersecta()==false){
player.X+=3;
player.sprite.update(1);
hitbox.setX(player.X);
}
and so on with the other keys....
so im not sure if its the best solution, but as far as i have seen it seems to be working. I hope this results useful for others.
I recommend to create a new Class.
This class Needs to inherit an Slick2d Shape, so for instance:
public class ShapeWithReference extends Rectangle{}
This class can have a list or a single object reference:
public class ShapeWithReference Rectangle{
Object reference = new String("hello"); //This is dirty and can be replaced by any object.
}
Since your new class is a Slick2D shape you can now find out whether it is contained by another shape:
Rectangle rec = new Rectangle();
if(rec.contains(ShapeWithReference)){
if(ShapeWithReference.reference instanceof String){
System.out.println((String)ShapeWithReference.reference);
}
}
Contains checks whether the shape really contains another shape. So they are not just intersecting. So that's the first part you check, the second one is whether the reference Attribute of the Shape is for e.g. a String. So if our first rectangle contains our new class and the reference of this class is type of a String this String is supposed to be written in to the console.
Hope this helps or gives you a hint.
EDIT:
public class SlickGame extends BasicGame {
static AppGameContainer appgc;
Rectangle rec;
ShapeWithReference swr;
public SlickGame(String title) {
super(title);
}
#Override
public void render(GameContainer container, Graphics g) throws SlickException {
}
#Override
public void init(GameContainer container) throws SlickException {
rec = new Rectangle(0, 0, 64, 64);
swr = new ShapeWithReference(0, 0, 1, 1);
}
#Override
public void update(GameContainer container, int delta) throws SlickException {
if(rec.intersects(swr)){
if(swr.reference instanceof String){
System.out.println((String)swr.reference);
}
else if(swr.reference instanceof Integer){
System.out.println((Integer)swr.reference);
}
else if(swr.reference instanceof Shape){
Shape temp = (Shape)swr.reference;
System.out.println(temp.getWidth());
}
}
}
public static void main(String[] args) {
try {
appgc = new AppGameContainer(new SlickGame("title"));
appgc.setDisplayMode(800, 600, false);
appgc.setTargetFrameRate(60);
appgc.setFullscreen(false);
appgc.start();
} catch (SlickException ex) {
ex.printStackTrace();
}
}
}
This is the code you should be able to copy & paste directly.
It does work for me, I'm not sure if I got your problem right but after the instanceof Operator you can just add the Class Name and check for it, I added some examples with an Integer and a Shape.
This is the 2nd class:
public class ShapeWithReference extends Rectangle {
private static final long serialVersionUID = 1L;
public ShapeWithReference(float x, float y, float width, float height) {
super(x, y, width, height);
}
Object reference = new String("hello");
}
Does this work for you?

Java Physics loop (repaint on interval) is choppy unless mouse is moving

I have a simple physics loop that does a calculation for a time interval, waits for the interval to pass, and then renders the results on the screen. It's very simple code (even though the timing is probably wrong, but that's exactly what I'm trying to learn about) and works well when I am moving the mouse around the screen.
package physicssim;
import java.awt.Graphics;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PhysicsSim extends JFrame {
private static class PhysicsObject {
public PhysicsObject(double x, double y, double v_x, double v_y) {
this.x = x;
this.y = y;
this.v_x = v_x;
this.v_y = v_y;
}
public double x;
public double y;
public double v_x;
public double v_y;
}
PhysicsObject particle;
boolean running = true;
DrawPane drawPane;
public PhysicsSim() {
particle = new PhysicsObject(10,10, .1, .2);
drawPane = new DrawPane(particle);
this.setSize(800,600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setContentPane(drawPane);
this.setVisible(true);
}
private static class DrawPane extends JPanel {
PhysicsObject p;
public DrawPane(PhysicsObject p) {
this.p = p;
}
#Override
public void paint(Graphics g) {
super.paint(g); //To change body of generated methods, choose Tools | Templates.
g.fillOval((int)p.x, (int) p.y, 10, 10);
}
}
public void start() {
int FPS = 60;
long TIME_BETWEEN_FRAMES_NS = 1000000000/FPS;
// Initial draw
drawPane.repaint();
long lastDrawTime = System.nanoTime();
while(running) {
// Update physics
particle.x+=particle.v_x*(TIME_BETWEEN_FRAMES_NS*.0000001);
particle.y+=particle.v_y*(TIME_BETWEEN_FRAMES_NS*.0000001);
// While there is time until the next draw wait
while(TIME_BETWEEN_FRAMES_NS > (System.nanoTime()-lastDrawTime)) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(PhysicsSim.class.getName()).log(Level.SEVERE, null, ex);
}
}
drawPane.repaint();
long currentTime = System.nanoTime();
System.out.println(currentTime - lastDrawTime);
lastDrawTime = currentTime;
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
PhysicsSim sim = new PhysicsSim();
sim.start();
}
}
The last bit about printing the time difference was just a sanity check to make sure that it was in fact calling around the requested interval. The results are fairly consistent so I don't see why there should be any choppiness.
As I mentioned above, this code works great if I a moving the mouse around the screen, everything is smooth.
If I am not moving the mouse it becomes very choppy until I start moving the mouse over the application.
I assume this is something simple, but I hope that you guys can help me. Thank you.
Alright, it looks like my problem was I was drawing directly to g in paint(). After replacing with the following everything worked correctly.
#Override
public void paint(Graphics g) {
BufferedImage img = new BufferedImage(800, 600, BufferedImage.TYPE_3BYTE_BGR);
img.getGraphics().fillOval((int) p.x, (int) p.y, 10, 10);
g.drawImage(img, 0, 0, null);
}
I was considering deleting this code snippet because it's rough and shameful, but maybe it will help someone else. Happy coding.

java.lang.NullPointerException Issue When Attempting to Run Program [duplicate]

This question already has answers here:
Class.getResource() returns null
(2 answers)
Closed 8 years ago.
This is my first question, I hope it's not too poorly made.
I'm definitely beginner level at java, probably lower. I'm taking most of my code from a tutorial in fact, hoping I'll learn what all the things do soon enough.
Anyway, so far, I have 3 .java files in my program, and it shows the exception to be at all 3 of them, plus one I never made.
Here's the full error:
Exception in thread "main" java.lang.NullPointerException
at javax.swing.ImageIcon.<init>(ImageIcon.java:205)
at Emilia.<init>(Emilia.java:17)
at Board.<init>(Board.java:26)
at TestGame.<init>(TestGame.java:7)
at TestGame.main(TestGame.java:18)
Here's all the code:
TestGame.java
import javax.swing.JFrame;
public class TestGame extends JFrame {
public TestGame() {
add(new Board());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 300);
setLocationRelativeTo(null);
setTitle("Project Obcasus");
setResizable(false);
setVisible(true);
}
public static void main(String[] args) {
new TestGame();
}
}
Board.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Board extends JPanel implements ActionListener {
private Timer timer;
private Emilia emilia;
public Board() {
addKeyListener(new TAdapter());
setFocusable(true);
setBackground(Color.BLACK);
setDoubleBuffered(true);
emilia = new Emilia();
timer = new Timer(5, this);
timer.start();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(emilia.getImage(), emilia.getX(), emilia.getY(), this);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
public void actionPerformed(ActionEvent e) {
emilia.move();
repaint();
}
private class TAdapter extends KeyAdapter {
public void keyReleased(KeyEvent e) {
emilia.keyReleased(e);
}
public void keyPressed(KeyEvent e) {
emilia.keyPressed(e);
}
}
}
Emilia.java
import java.awt.Image;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
public class Emilia {
private String emilia = "emiliasprite.png";
private int dx;
private int dy;
private int x;
private int y;
private Image image;
public Emilia() {
ImageIcon ii = new ImageIcon(this.getClass().getResource(emilia));
image = ii.getImage();
x = 40;
y = 60;
}
public void move() {
x += dx;
y += dy;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Image getImage() {
return image;
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_A) {
dx = -1;
}
if (key == KeyEvent.VK_D) {
dx = 1;
}
if (key == KeyEvent.VK_W) {
dy = -1;
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_A) {
dx = 0;
}
if (key == KeyEvent.VK_D) {
dx = 0;
}
if (key == KeyEvent.VK_W) {
dy = 0;
}
}
}
ImageIcon.java - Line 205
this(location, location.toExternalForm());
Again, I'm beginner level so if you guys could explain it as you would to a newcomer to java (or any programming language for that matter)
Thanks for any help. - Niblexis
path of .png file:
C:\Users\Damon\workspace\TestGame\Resources\Sprites\Player
The .png file is in the player folder. I tried to run the program via the run button in Eclipse. At least, I think it's the run button because it's what showed me the errors in the first place.
Looks like the problem is in this line:
ImageIcon ii = new ImageIcon(this.getClass().getResource(emilia));
which means most likely that you haven't placed your .png file in the right place for Java to find it.
Could you post the exact path of the .png file on disk?
More specifically: a null pointer in this line of ImageIcon.java:
this(location, location.toExternalForm());
would imply that the URL location is null (causing an exception in the method call .toExternalForm(). If you look at the docs for Class.getResource() you will see it says:
Returns: A URL object or null if no resource with this name is found
which implies that Java can't find the resource in question.
For us to help, you will need to describe your runtime environment (are you running your program from .class files or in a .jar? at the command-line or in a debugger in Eclipse / Netbeans?) so we can help you figure out why the resource isn't being found.
You're effectively calling Emilia.class.getResource("emiliasprite.png") with Emilia.java in the default (root) package, which means that you need to tell your IDE / build process to copy this file into the root of the classpath. (in the same directory that Emilia.class ends up) Otherwise, Java has no idea where to find it.
If you want to place the resource somewhere else, you need to change the path accordingly, as well as the mechanism that copies the resource from the source directory to the appropriate place on the classpath.
See this stackoverflow answer: Java in Eclipse: Where do I put files on the filesystem that I want to load using getResource? (e.g. images for an ImageIcon)

How to create a function to remove a button [Beginner]

I am currently using this function to create and display a button.
Button(String nm, int x, int y, int w, int h)
{
super(nm, x, y, w, h);
}
void display()
{
if(currentImage != null)
{
float imgWidth = (extents.y*currentImage.width)/currentImage.height;
pushStyle();
imageMode(CORNER);
tint(imageTint);
image(currentImage, pos.x, pos.y, imgWidth, extents.y);
stroke(bgColor);
noFill();
rect(pos.x, pos.y, imgWidth, extents.y);
noTint();
popStyle();
}
else
{
pushStyle();
stroke(lineColor);
fill(bgColor);
rect(pos.x, pos.y, extents.x, extents.y);
fill(lineColor);
textAlign(CENTER, CENTER);
text(name, pos.x + 0.5*extents.x, pos.y + 0.5* extents.y);
popStyle();
}
}
I would like to create a function such as:
void hide()
so that I could remove or hide the function when I need to, after it is clicked. How should I approach this? am I basically setting everything to null? to remove it?
I can´t be sure now as you haven´t posted the actual class definition but I´m assuing you either extend java.awt.Button or javax.swing.JButton.
In that case, you can just use the setVisible method:
public void hide(){
this.setVisible(false);
}
This works on every GUI-Component that extends java.awt.Component.
In a very simple example (that is a one-way thing since you can´t get the button back ;)) this would look like:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class DemoFrame extends JFrame {
private JButton buttonToHide;
public DemoFrame() {
this.setSize(640, 480);
buttonToHide = new JButton();
buttonToHide.setText("Hide me!");
buttonToHide.addActionListener(new ButtonClickListener());
this.getContentPane().add(buttonToHide);
}
public class ButtonClickListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (buttonToHide.isVisible()) {
buttonToHide.setVisible(false);
}
}
}
public static void main(String[] args){
new DemoFrame().setVisible(true);
}
}
While writing up that example I found that java.awt.Component even defines a method "hide()" but this is marked as deprecated with the hint to use setVisible instead.
I hope this helps!
Maybe a simple boolean show wrapping the display statements... And a key or what ever to toogle it.
like:
void display(){
if(show){
//all stuff
}
}
void toogleShow(){
if(/*something, a key an event...*/){
show = !show;
}
}
You would need to wrap functionality of the button as well.

How to delete an JPanel Object?

Im on to create a little "game", something like an 2d AirForce Shooter.
So, i have a problem with deleting unused enemys.
An Enemy is an simple JPanel, which is saved in the main logic as an array List.
public static ArrayList<Enemy> enemys = new ArrayList<Enemy>();
The Enemy run logic does the following:
while(!destroyed){
if(Game.running){
x--;
if(getBounds().intersects(Field.player.getBounding())){
Player.death = true;
}
if(x < 0){
Field.deleteEnemy(this);
}
setBounds((int) x, (int) y, 100, 50);
try{Thread.sleep(10);}catch(InterruptedException e){}
}
}
So you can seem there i already tried to call the method deleteEnemy, and just give it the unused Enemy.
But it isnt possible - when i just do this:
public static void deleteEnemy(Enemy e){
System.out.println("test");
enemys.remove(e);
}
It will be just removed from the list, but coninues existing on the Main JPanel.
And i cannot say
remove(e);
Because then i try to call a non static function in a static.
So, how could i delete an Enemy? Someone knows?
Thanks for help!
The hole code: (Game.java)
And, Enemy.java:
package Game;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class Field extends JPanel implements Runnable{
public static Player player = new Player();
public static ArrayList<Enemy> enemys = new ArrayList<Enemy>();
private Thread moveBackground = new Thread(this);
private boolean bgMoving = false;
public static boolean addMob = false;
private int x = 0;
private int bgSpeed = -1;
public Field(){
setBounds(0, 0, 800, 600);
setFocusable(true);
setLayout(null);
addKeyListener(new Handler());
add(player);
}
public void paintComponent(Graphics g){
Field.super.paintComponent(g);
g.drawImage(Images.images[0], x, 0, this);
}
public static void deleteEnemy(Enemy e){
System.out.println("test");
enemys.remove(e);
}
public void run(){
while(!Player.death){
if(bgMoving){
bgMoving = true;
x += bgSpeed;
if(x < -(Images.images[0].getWidth(this) - this.getWidth() - 20)){
bgMoving = false;
}
repaint();
try { Thread.sleep(20); } catch (InterruptedException e) {}
}
if(addMob){
enemys.add(new Enemy());
add(enemys.get(enemys.size() - 1));
addMob = false;
}
}
JOptionPane.showMessageDialog(null, "DIED!");
}
public class Handler extends KeyAdapter {
public void keyPressed(KeyEvent e) {
player.KeyPressed(e);
if(!bgMoving){
if(Game.running){
bgMoving = true;
if(moveBackground.getState().toString() == "NEW"){
moveBackground.start();
}
}
}
}
public void keyReleased(KeyEvent e) {
player.KeyReleased(e);
}
}
}
And, Enemy.java:
package Game;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Enemy extends JPanel implements Runnable{
Thread t = new Thread(this);
private double x = Game.width();
private double y = Math.random() * Game.height();
private double xF = 0, yF = 0;
private boolean destroyed = false;
public Enemy(){
setBounds((int) x, (int) y, 100, 50);
setOpaque(false);
t.start();
}
public void paintComponent(Graphics g){
Enemy.super.paintComponent(g);
g.setColor(Color.GREEN);
g.drawImage(Images.images[2], 0, 0, this);
}
public void run() {
while(!destroyed){
if(Game.running){
x--;
if(getBounds().intersects(Field.player.getBounding())){
Player.death = true;
}
if(x < 0){
Field.deleteEnemy(this);
}
setBounds((int) x, (int) y, 100, 50);
try{Thread.sleep(10);}catch(InterruptedException e){}
}
}
}
}
After removing you will need to call revalidate() and repaint()
[Too long for a comment]
I think the problem is in your logic on removing an Enemy/JPanel:
You are removing it from the ArrayList only, what about the containing JPanel/JFrame you added it to?
You must remove the JPanel from its container (maybe another JPanel or the JFrame) not just the ArrayList via Component#remove(Component c).
If you drew the Enemy images directly in paintComponent(...) of your container via iterating the ArrayList; removing it from the ArrayList would be sufficient, as it will no longer be in the Array and thus no longer drawn on the next repaint().
+1 to #Optional, you may need to call revalidate() and repaint() on the container for the affects of the removed JPanel/Enemy to be shown.
Also as #darijan mentioned, the use of static variables along with instance is not really a great design (though for certain designs this may be fine).
In your case if you need access to an instance method of another class, within another class, simply pass the instance of the class whos method you would like to access to the object which will access it.
Here is some psuedo code expressing much of the above mentioned problems / solutions:
public class Field extends JPanel {
private ArrayList<Enemy> enemies;
public Field() {
...
enemies.add(new Enemy(this));//create a new enemy and pas it the JPanel instance so it may access instance methods of this class
}
//ONLY USED IF JPanel for Enemy is ommited and Enemy class created which represents Enemy object and not Enemy object and aJPanel
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
ArrayList<Enemy> enemiesClone = new ArrayList<>(enemies);//copy array into another so we don't get a ConcurrentModificaton exception if removeEnemy is called while iterating the list
if(!enemiesClone.isEmpty())
for(Enemy e:enemiesClone) {//iterate through array of images
draw(e.getImage(),e.getX(),e.getY(),this);
}
}
public void removeEnemy(Enemy e) {
enemies.remove(e);//remove from the array
//ONLY USED IF JPanels are used as Enemy
remove(e);//remove from the JPanel
//so the changes of removed panel can be visible seen
revalidate();
repaint();
}
}
class Enemy extends JPanel //extends JPanel should be ommited for paintComponent method of drawing an enemy onscreen
{
private int x,y;
private BufferedImage image;
private Field f;
public Enemy(Field f) {//constructor accepts Field instance to access instance method for the class
this.f=f;
}
public void update() {
if(offscreen||dead) {
f.removeEnemy(this);//call removeEnemy which is an instance method of Field
}
}
//BELOW METHODS ONLY USED WHEN Enemy represents object and not a JPanel which can draw its image itself (and update position by simply changing co-ordinates)
public BufferedImage getImage() {
return image;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
For a more detailed look check Game Development Loop, Logic and Collision detection Java Swing 2D I made which will give you the basics needed for most 2D games. However I do not use JPanels rather draw directly to a container.
Where do you add an Enemy to JPanel?
Basically, you should call remove on Field JPanel:
public void deleteEnemy(Enemy e){
System.out.println("test");
enemys.remove(e);
this.remove(e);
}
The method should not be static.

Categories