0

I'm trying to make impassable walls on the edge of my screen (JFrame). So when I move my image to the left and it touches the left side of the frame, it forces the image to not move. I tried various things, but I just can't seem to find the right code for it, so I'm wondering how to do it based around my code.

import javax.swing.*;
import java.awt.event.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.net.URL;

public class MovingImages extends JPanel implements KeyListener, ActionListener
{
  Timer t = new Timer(5, this);
  int x = 0, y = 0; //coordinates for the image
  int imageScaleX = 100, imageScaleY = 100; //scale the size of the image 
  int velX = 0, velY = 0;  
//--------------------------------------------------------------------------------------- DISPLAYING IMAGE

  public MovingImages()
  {   
    t.start();
    addKeyListener(this); //enables the KeyListener so keys can be pressed
    setFocusable(true);
  }

  /** This code is only used for importing the image and runs the program even when there is no image
    * @param path is a String that is used to represent the the name or where your file is
    * @return is the tempImage which is the image that the program found
    */  
  public Image getImage(String path)
  {
    Image tempImage = null; 
    try
    {
      URL imageURL = MovingImages.class.getResource(path); //finds where the image is
      tempImage = Toolkit.getDefaultToolkit().getImage(imageURL); //loads image from file
    }
    catch (Exception e)
    {
    }
    return tempImage;
  } 

  /** This code is used to display the image in specified coordinates
    * @param g is a variable that uses the Graphics method
    */
  public void paint(Graphics g)
  {
    Image image = getImage("sprite.png"); //choose the file for your image    
    super.paintComponent(g); //everytime the image moves, it clears the previous image    
    Graphics2D g2 = (Graphics2D) g; //converts graphics into 2D
    g2.drawImage(image, x, y, imageScaleX, imageScaleY, this); //draws image in specific coordinates
  }
//--------------------------------------------------------------------------------------- KEYBOARD FUNCTIONS 

  public void actionPerformed(ActionEvent e)
  {
    x += velX;
    y += velY;
    repaint();    
  }  

  public void up()
  {
    velY = -2; 
  }

  public void down()
  { 
    velY = 2;
  }

  public void left()
  {   
    velX = -2;  
  }

  public void right()
  {   
    velX = 2;
  }

  public void keyPressed(KeyEvent e)
  {
    int keyCode = e.getKeyCode();
    if (keyCode == KeyEvent.VK_UP)
    {
      up();
    }
    if (keyCode == KeyEvent.VK_DOWN)
    {
      down();
    }
    if (keyCode == KeyEvent.VK_LEFT)
    {
      left();
    }
    if (keyCode == KeyEvent.VK_RIGHT)
    {
      right();
    }
  }

  public void keyTyped(KeyEvent e)
  {
  }

  public void keyReleased(KeyEvent e)
  {
    int keyCode = e.getKeyCode();
    if (keyCode == KeyEvent.VK_UP)
    {
      velY = 0;
    }
    if (keyCode == KeyEvent.VK_DOWN)
    {
      velY = 0;
    }
    if (keyCode == KeyEvent.VK_LEFT)
    {
      velX = 0;
    }
    if (keyCode == KeyEvent.VK_RIGHT)
    {
      velX = 0;
    }
  } 
//--------------------------------------------------------------------------------------- MAIN 

  public static void main(String args[])
  {
    MovingImages s = new MovingImages();
    JFrame f = new JFrame();
    f.add(s);
    f.setVisible(true);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setSize(1280, 720);
  }
}
Alan
  • 23
  • 5
  • So, this is basic collision detection, when you update the position of your object, you need to verifying the position of the object and determine if it's out of range – MadProgrammer May 22 '16 at 04:48

1 Answers1

2

The following answer explains the general principle behind forcing objects to stay within their container. Within your program's event loop you are updating an object's x and y coordinates, either directly in response to keyboard input or in a timer loop based on a saved velocity. In either case the basic principle is the same:

Detect when an object's edge bumps up against the container's boundary and don't apply any changes to the object coordinate that would move it so it is partially or completely outside the container.

The following pseudocode describes what has to happen every time you go to update an object's position. I show only the code for horizontal movement, vertical movement is left as an exercise. I assume the object's "position" is the coordinate of the lower left corner of its bounding box.

    int left_edge  = pos_x;
    int right_edge = pox_x + width;
    if (velocity_x < 0)
        pos_x += left_edge > 0 ? velocity_x : 0;
    else if (velocity_x > 0)
        pos_x += right_edge < container_width ? velocity_x : 0;

Some questions I have not addressed which are left as an exercise:

  1. Vertical movement
  2. What happens to velocity when the object bumps against a wall. Does (a) the object continue to "try" to move or (b) does the velocity in that direction drop to zero? The first option (a) might apply for instance if there's a barrier of some kind in the middle of the container. The object could bump up against it and stop horizontal movement while still having vertical movement and when eventually clearing the barrier vertically, then continue also moving horizontally.
  3. If velocity > 1 the above code can result in ending up partially outside the container (i.e. you start at x==1 with velocity==-2). You will need to enhance the code for this case, keeping in mind your answer to item 2 above.
Jim Garrison
  • 85,615
  • 20
  • 155
  • 190