How do I prevent the object from exceeding the screen boundaries?

0

I started programming a little game where an object moves across the screen through the arrow keys. The difficulty I encountered is that the object exceeds JFrame , that is, there is nothing to block the passage at the limit of JFrame .

I would like to know how I can solve this problem, or at least an indication of a path I should take to achieve this goal.

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Jogo1 extends JFrame{ //Herda para usar JFrame

String n = "0";
JLabel labelFlappy = new JLabel(n);

int posPrincX = 300;
int posPrincY = 300;

public Jogo1(){
    editarJanela();
    editarComponentes();
    addMovimento();
}

public void addMovimento(){
    addKeyListener(new KeyListener(){ //Teclado
        public void keyPressed(KeyEvent e) {
            System.out.println(e.getKeyCode()); //Exibe código da tecla pressionada
            if(e.getKeyCode() == 38){
                posPrincY -= 20;
            }
            if(e.getKeyCode() == 40){
                posPrincY += 20;
            }
            if(e.getKeyCode() == 37){
                posPrincX -= 20;
            }
            if(e.getKeyCode() == 39){
                posPrincX += 20;
            }
            labelFlappy.setBounds(posPrincX, posPrincY, 180, 90); //Atualiza posição
        }
        public void keyReleased(KeyEvent e) {   

        }           
        public void keyTyped(KeyEvent e) {

        }
    });
    addMouseListener(new MouseListener() {

        public void mouseClicked(MouseEvent e) { //Ao clicar no objeto em questão
            posPrincX = (int)(Math.random() * 650);
            posPrincY = (int)(Math.random() * 700);
            labelFlappy.setBounds(posPrincX, posPrincY, 180, 90);
        }
        public void mouseEntered(MouseEvent e) {

        }
        public void mouseExited(MouseEvent e) {

        }
        public void mousePressed(MouseEvent e) {

        }
        public void mouseReleased(MouseEvent e) {

        }   
    });
}

public void editarComponentes(){
    labelFlappy.setBounds(posPrincX, posPrincY, 180, 90);
}

public void editarJanela(){
    setDefaultCloseOperation(EXIT_ON_CLOSE); //Encerra ao fechar 
    setSize(750, 700); //Tamanho 
    setLocationRelativeTo(null); //Centraliza
    setVisible(true); //Torna visível
    setLayout(null); //Permite redimensionamento de cada componente
    setResizable(false); //Impossibilita o redimensionamento pelo usuário
    setTitle("Magisterix"); //Título

    add(labelFlappy);
}

public static void main(String[] args){
    new Jogo1();
}}
    
asked by anonymous 06.05.2018 / 17:28

2 answers

2

I was able to do this:

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Jogo1 {

    private static final int KEY_CODE_DOWN = 38;
    private static final int KEY_CODE_UP = 40;
    private static final int KEY_CODE_LEFT = 37;
    private static final int KEY_CODE_RIGHT = 39;

    private static final int DISTANCIA_PASSO = 20;
    private static final int LARGURA_INICIAL_TELA = 750;
    private static final int ALTURA_INICIAL_TELA = 700;
    private static final int POSICAO_X_INICIAL = 300;
    private static final int POSICAO_Y_INICIAL = 300;
    private static final int LARGURA_FLAPPY_INICIAL = 180;
    private static final int ALTURA_FLAPPY_INICIAL = 90;

    private int posicaoX;
    private int posicaoY;

    public Jogo1() {
        JFrame tela = new JFrame("Magisterix");
        tela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Encerra ao fechar.
        tela.setSize(LARGURA_INICIAL_TELA, ALTURA_INICIAL_TELA); // Ajusta o tamanho.
        tela.setLocationRelativeTo(null); // Centraliza.
        tela.setVisible(true); // Torna visível.
        tela.setResizable(false); // Impossibilita o redimensionamento pelo usuário.
        tela.setLayout(null); // Permite redimensionamento de cada componente.

        JLabel labelFlappy = new JLabel("0");
        labelFlappy.setOpaque(true);
        labelFlappy.setBackground(Color.YELLOW);
        tela.add(labelFlappy);
        posicaoX = POSICAO_X_INICIAL;
        posicaoY = POSICAO_Y_INICIAL;
        labelFlappy.setBounds(posicaoX, posicaoY, LARGURA_FLAPPY_INICIAL, ALTURA_FLAPPY_INICIAL);

        tela.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                System.out.println(e.getKeyCode());
                if (e.getKeyCode() == KEY_CODE_DOWN) {
                    posicaoY -= DISTANCIA_PASSO;
                } else if (e.getKeyCode() == KEY_CODE_UP) {
                    posicaoY += DISTANCIA_PASSO;
                } else if (e.getKeyCode() == KEY_CODE_LEFT) {
                    posicaoX -= DISTANCIA_PASSO;
                } else if (e.getKeyCode() == KEY_CODE_RIGHT) {
                    posicaoX += DISTANCIA_PASSO;
                }
                posicaoX = limitar(0, posicaoX, tela.getContentPane().getWidth() - labelFlappy.getWidth());
                posicaoY = limitar(0, posicaoY, tela.getContentPane().getHeight() - labelFlappy.getHeight());
                labelFlappy.setBounds(posicaoX, posicaoY, labelFlappy.getWidth(), labelFlappy.getHeight());
            }
        });

        tela.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                posicaoX = (int) (Math.random() * (tela.getContentPane().getWidth() - labelFlappy.getWidth()));
                posicaoY = (int) (Math.random() * (tela.getContentPane().getHeight() - labelFlappy.getHeight()));
                labelFlappy.setBounds(posicaoX, posicaoY, labelFlappy.getWidth(), labelFlappy.getHeight());
            }
        });
    }

    private static int limitar(int min, int meio, int max) {
        return meio < min ? min : meio > max ? max : meio;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(Jogo1::new);
    }
}

The trick is to limit posPrincX and posPrincY to window size (or posicaoX and posicaoY , since I renamed the variables). For this, I use the limitar(int, int, int) method.

I made some other changes to your code:

  • Only create, interact, use and access Swing components within EDT. For this, I use EventQueue.invokeLater(Runnable) . See more about this on this question and in that response .

  • Prefer to use composition from inheritance, and therefore not inherit from JFrame . I'm talking about this on this answer . I also address this question (and many other things) in that other answer .

  • Using magic numbers is not a good programming practice. I made your code without using magic numbers and also in a way that if the size of the screen or the size of the label changes, it will not be messy and will adjust to the change alone.

  • I've painted the JLabel yellow so you can see exactly where it is and how big it is.

  • I changed the name of some variables to be more representative.

  • Use KeyAdapter and MouseAdapter instead of directly implementing KeyListener and MouseListener so as not to have that many empty methods.

06.05.2018 / 19:47
5

To prevent moving components from exceeding the screen area, you can use a method that checks whether the new X and Y positions added to the component's full width and height exceed the screen size in both directions, and when they exceed, do not move the component more or apply some negative value so it does not get stuck in the corner. The method for checking this, based on your code, can be something like this:

private boolean excedeuAreaDaTela(int posX, int posY) {
    return posX < 0 || posX + 180 > 750 || posY < 0 || posY + 90 > 700;
}

To use, simply wrap in a conditional line that changes the position of the component:

if (!excedeuAreaDaTela(posPrincX, posPrincY)) {
    labelFlappy.setBounds(posPrincX, posPrincY, 180, 90); // Atualiza posição
}

When the method returns true , it means that if the component moves to the given coordinates, it will exceed the size you set for the screen, the conditional will not allow movement in this case.

    
06.05.2018 / 18:39