Home > Software engineering >  Information is not passed from one class to another in Java. How can I solve it?
Information is not passed from one class to another in Java. How can I solve it?

Time:04-24

I'm currently making a snake game in java. First I created a class named GamePanel for my snake. And here I wrote the codes of the apple eaten by the snake, the codes of the snake, and the movements of the snake in this class. Now I want to create another class by taking some codes from them. So I created a separate Data class for this and put the information I wrote at the beginning of the GamePanel.

There was a method in the GamePanel that I called newApple. I placed it in a separate class called SnakeFoodApple. After that, come to GamePanel and

public SnakeFoodApple apple = new SnakeFoodApple();

I wrote this code. Where there is newApple, I said apple.newApple.

I'm running the game now and I'm not getting any errors. But it does not perform the event of throwing apples at random different places, which is the feature of newApple. So the apple is always in the same coordinates. How can I solve this?

Also, how is it possible to transfer information on both sides in this transition between classes? So, can I switch from class A to class B and from class B to class A? If I can, with what code can I do it? Thank you for your interest in advance.

My code;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;

public class GamePanel extends JPanel implements ActionListener {
    public SnakeFoodApple apple = new SnakeFoodApple();

    static final int SCREEN_WIDTH = 600;
    static final int SCREEN_HEIGHT = 600;
    static final int UNIT_SIZE = 25;
    static final int GAME_UNITS = (SCREEN_WIDTH * SCREEN_HEIGHT) / UNIT_SIZE;
    static final int DELAY = 75;
    final int X[] = new int[GAME_UNITS];
    final int Y[] = new int[GAME_UNITS];
    int bodyParts = 6;
    int applesEaten;
    int appleX;
    int appleY;
    char direction = 'R';
    boolean running = false;
    Timer timer;
    Random random = new Random();
    
    GamePanel() {
        random = new Random();
        this.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
        this.setBackground(Color.black);
        this.setFocusable(true);
        this.addKeyListener(new MyKeyAdapter());
        startGame();
    }
    public void startGame() {
        apple.newApple();
        running = true;
        timer = new Timer(DELAY, this);
        timer.start();
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        draw(g);
    }

    public void draw(Graphics g) {
        if (running) {
            g.setColor(Color.red);
            //g.fillOval(int X, int Y, Width, Height)
            g.fillOval(appleX, appleY, UNIT_SIZE, UNIT_SIZE);

            for (int i = 0; i < bodyParts; i  ) {
                if (i == 0) {
                    g.setColor(Color.green);
                    g.fillRect(X[i], Y[i], UNIT_SIZE, UNIT_SIZE);
                } else {
                    g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
                    g.fillRect(X[i], Y[i], UNIT_SIZE, UNIT_SIZE);
                }
            }
            g.setColor(Color.red);
            g.setFont(new Font("Ink Free", Font.BOLD, 40));
            FontMetrics metrics = getFontMetrics(g.getFont());
            g.drawString("SCORE: "   applesEaten, (SCREEN_WIDTH - metrics.stringWidth("SCORE: "   applesEaten)) / 2, g.getFont().getSize());
        } else {
            gameOver(g);
        }
    }

    

    public void move() {
        for (int i = bodyParts; i > 0; i--) {
            X[i] = X[i - 1];
            Y[i] = Y[i - 1];
        }
        switch (direction) {
            case 'U':
                Y[0] = Y[0] - UNIT_SIZE;
                break;
            case 'D':
                Y[0] = Y[0]   UNIT_SIZE;
                break;
            case 'L':
                X[0] = X[0] - UNIT_SIZE;
                break;
            case 'R':
                X[0] = X[0]   UNIT_SIZE;
                break;
        }
    }

    public void checkApple() {
        if ((X[0] == appleX) && (Y[0] == appleY)) {
            bodyParts  ;
            applesEaten  ;
            apple.newApple();
        }
    }
    public void checkCollisions() {
        for (int i = bodyParts; i > 0; i--) {
            if ((X[0] == X[i]) && (Y[0] == Y[i])) {
                running = false;
            }
        }
        if (X[0] < 0) {
            running = false;
        }
        if (X[0] > SCREEN_WIDTH) {
            running = false;
        }
        if (Y[0] < 0) {
            running = false;
        }
        if (Y[0] > SCREEN_HEIGHT) {
            running = false;
        }
        if (!running) {
            timer.stop();
        }
    }

    public void gameOver(Graphics g) {
        g.setColor(Color.red);
        g.setFont(new Font("Ink Free", Font.BOLD, 40));
        FontMetrics metrics1 = getFontMetrics(g.getFont());
        g.drawString("SCORE: "   applesEaten, (SCREEN_WIDTH - metrics1.stringWidth("SCORE: "   applesEaten)) / 2, g.getFont().getSize());
        g.setColor(Color.red);
        g.setFont(new Font("Ink Free", Font.BOLD, 75));
        FontMetrics metrics2 = getFontMetrics(g.getFont());
        g.drawString("GAME OVER", (SCREEN_WIDTH - metrics2.stringWidth("GAME OVER")) / 2, SCREEN_HEIGHT / 2);

    }

//class GamePanel' ı implements (implıments) ettiğimiz için otomotik olarak geldi
    @Override
    public void actionPerformed(ActionEvent e) {
        if (running) {
            move();
            checkApple();
            checkCollisions();
        }
        repaint(); 
    }

    public class MyKeyAdapter extends KeyAdapter {

        @Override
        public void keyPressed(KeyEvent e) {
            switch (e.getKeyCode()) {
                case KeyEvent.VK_LEFT:
                    if (direction != 'R') {
                        direction = 'L';
                    }
                    break;
                case KeyEvent.VK_RIGHT:
                    if (direction != 'L') {
                        direction = 'R';
                    }
                    break;
                case KeyEvent.VK_UP:
                    if (direction != 'D') {
                        direction = 'U';
                    }
                    break;
                case KeyEvent.VK_DOWN:
                    if (direction != 'U') {
                        direction = 'D';
                    }
                    break;

            }
        }
    }

}





public class SnakeFoodApple extends Data{

    public void newApple(){
        appleX = random.nextInt((int) (SCREEN_WIDTH / UNIT_SIZE)) * UNIT_SIZE;
        appleY = random.nextInt((int) (SCREEN_HEIGHT / UNIT_SIZE)) * UNIT_SIZE;
    }
}




    import java.util.Random;
    import javax.swing.Timer;
    
    public class Data {
        static final int SCREEN_WIDTH = 600;
        static final int SCREEN_HEIGHT = 600;
        static final int UNIT_SIZE = 25;
        static final int GAME_UNITS = (SCREEN_WIDTH * SCREEN_HEIGHT) / UNIT_SIZE;
        static final int DELAY = 75;
        final int X[] = new int[GAME_UNITS];
        final int Y[] = new int[GAME_UNITS];
        int bodyParts = 6;
        int applesEaten;
        int appleX;
        int appleY;
        char direction = 'R';
        boolean running = false;
        Timer timer;
        Random random = new Random();
    }

CodePudding user response:

I might be missing something, but it looks as though you have forgotten to fillOval using apple here:

public void draw(Graphics g) {
    if (running) {
        g.setColor(Color.red);
        //g.fillOval(int X, int Y, Width, Height)
        g.fillOval(appleX, appleY, UNIT_SIZE, UNIT_SIZE);

Should probably be:

g.fillOval(this.apple.appleX, this.apple.appleY, this.apple.UNIT_SIZE, this.apple.UNIT_SIZE);

I'm not clear why you have all this in GamePanel still, is this not supposed to be happening in Data (SnakeFoodApple) now?

static final int SCREEN_WIDTH = 600;
static final int SCREEN_HEIGHT = 600;
static final int UNIT_SIZE = 25;
static final int GAME_UNITS = (SCREEN_WIDTH * SCREEN_HEIGHT) / UNIT_SIZE;
static final int DELAY = 75;
final int X[] = new int[GAME_UNITS];
final int Y[] = new int[GAME_UNITS];
int bodyParts = 6;
int applesEaten;
int appleX;
int appleY;
char direction = 'R';
boolean running = false;
Timer timer;
Random random = new Random();

In general, it is good practice to set fields as private and use getters and setters. It would be good to look at that.

I'm not sure what you mean by your second question.

CodePudding user response:

Your code is a bit of a mess - sorry to be that harsh, but could not find a "softer" expression:

  • You have the same member fields in GamePanel and in Data.
  • You extend Data with SnakeFoodApple but the only thing you add or change in the extended class is a method to set some member fields of the parent class.
  • You did not declare any field with a visibility other than default (aka package private).

What you see is cause from a combination of the three topics above. You have to get rid of the class SnakeFoodApple, that single method can easily go into Data (you can rename Data afterwards back to SnakeFoodApple if you like that name.

Also all those static fields in Data should not be static, but normal member fields, and initialized in a constructor rather than having fixed initializers.

Finally you must not store appleX and appleY in your main class GamePanel but access them from Data every time you need the values. Create getters for that.

Also clean up Data from all values you are not actually using inside there. Don't forget to remove unnecessary imports.

  • Related