0

I am trying to "teleport" objects to the opposite positions whenever they get out of screen. I've managed to do this with right & bottom sides, but for some reason, which I haven't figured out, the star objects won't go off screen on TOP & LEFT sides UNLESS the lerping speed is high enough.

Preview:
enter image description here

Main.java

package asteroids;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

import javax.swing.ImageIcon;
import javax.swing.JFrame;

public class Main extends Canvas implements KeyListener {   
    private boolean gameOver;
    private BufferStrategy backBuffer;  
    private Dimension dimension = new Dimension(Config.WINDOW_WH[0], Config.WINDOW_WH[1]);
    private List<Star> stars = new ArrayList<Star>();
    private HashMap<Integer,Boolean> keyDownMap = new HashMap<Integer, Boolean>();
    private Ship ship;
    private Image bg;
    private float starGoalX, starGoalY;

    public Main() {
        // Initialize Window
        initWindow();
        addKeyListener(this);

        this.createBufferStrategy(2);               
        backBuffer = this.getBufferStrategy();


        bg = new ImageIcon(getClass().getResource("/bg.png")).getImage();

        // init variables
        gameOver = false;

        // Generating stars
        generateStars();

        // Init spaceship
        ship = new Ship(25,36,"ship.png");

        // Init loop
        gameLoop();

    }

    public void initWindow(){
        JFrame window = new JFrame("Asteroids"); 
        setPreferredSize(dimension); 

        window.add(this);           
        window.pack();  
        window.setResizable(false);
        window.setVisible(true); 
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        window.requestFocus();

    }

    public float lerp(float starGoal, float vel, float speed) {
        return starGoal + speed * (vel - starGoal);
    }

    public void update() {

        if(keyDownMap.containsKey(KeyEvent.VK_ESCAPE)){
            gameOver = false;
            System.exit(0);
        }

        for(Star s: stars) {

            s.posx += lerp(this.starGoalX, s.velX, Config.lerpSpeed);
            s.velX += this.starGoalX * Config.lerpSpeed;

            s.posy += lerp(this.starGoalY, s.velY, Config.lerpSpeed);
            s.velY += this.starGoalY * Config.lerpSpeed;
            checkPos(s);


            s.update();
        }

    }

    public void checkPos(Star s) {

        if(s.posx < -s.width) 
            s.posx = Config.WINDOW_WH[0]-s.width;
        else if(s.posx > Config.WINDOW_WH[0])
            s.posx = 0;

        if(s.posy < -s.height)
            s.posy = Config.WINDOW_WH[1]-s.height;
        else if(s.posy > Config.WINDOW_WH[1])
            s.posy = 0;
    }

    public void render(){
        Graphics2D g = (Graphics2D) backBuffer.getDrawGraphics();

        if (!backBuffer.contentsLost()) {
            g.drawImage(this.bg,0,0,Config.WINDOW_WH[0], Config.WINDOW_WH[1], null);

            // Draw Stars
            g.setColor(Color.WHITE);
            for(Star s: stars)
                g.fillOval(s.posx - (s.width/2), s.posy - (s.height/2), s.width, s.height);

            // Draw ship
            g.drawImage(
                    this.ship.getImage(), 
                    this.ship.posx, this.ship.posy, 
                    this.ship.width, this.ship.height, null);

            backBuffer.show();
            g.dispose();
        }

    }


    public void generateStars() {
        for(int i = 0;i < 50;i++) {
            int starX = new Random().nextInt(Config.WINDOW_WH[0]+100)+5;
            int starY = new Random().nextInt(Config.WINDOW_WH[1]+100)+5;
            stars.add(new Star(starX, starY));
        }
    }


    public void gameLoop(){
        while(!gameOver){
            update();
            render();
            try{ Thread.sleep(20);}catch(Exception e){};
        }

    }

    public static void main(String[] args) {

        new Main();
    }


    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyPressed(KeyEvent e) {

        if(e.getKeyCode() == KeyEvent.VK_LEFT)  this.starGoalX = Config.lerpSpeed;
        if(e.getKeyCode() == KeyEvent.VK_RIGHT) this.starGoalX = -Config.lerpSpeed;
        if(e.getKeyCode() == KeyEvent.VK_UP)    this.starGoalY = Config.lerpSpeed;
        if(e.getKeyCode() == KeyEvent.VK_DOWN)  this.starGoalY = -Config.lerpSpeed;

        keyDownMap.put(e.getKeyCode(), true);
    }

    @Override
    public void keyReleased(KeyEvent e) {

        if(e.getKeyCode() == KeyEvent.VK_LEFT 
        || e.getKeyCode() == KeyEvent.VK_RIGHT)     this.starGoalX = 0;

        if(e.getKeyCode() == KeyEvent.VK_UP 
        || e.getKeyCode() == KeyEvent.VK_DOWN)  this.starGoalY = 0;


        keyDownMap.remove(e.getKeyCode());
    }


}

Star.java

package asteroids;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.KeyEvent;
import java.awt.geom.Ellipse2D;
import java.util.HashMap;
import java.util.Random;
public class Star {

    int width, height;
    int posx, posy;
    float velX, velY, velGoalX, velGoalY;

    /** CONSTRUCTOR **/
    public Star(int x, int y) {
        int rand = new Random().nextInt(Config.STAR_SIZES.length);
        width = Config.STAR_SIZES[rand];
        height = Config.STAR_SIZES[rand];
        posx = x;
        posy = y;


    }


    public void update() {
        // pass
    }



}

Ship.java

package asteroids;

import java.awt.Image;
import java.awt.event.KeyEvent;
import java.util.HashMap;

import javax.swing.ImageIcon;

public class Ship {

    public int posx, posy;
    public int width, height;
    private Image image;

    public Ship(int w, int h, String img) {
        this.posx = Config.WINDOW_WH[0]/2;
        this.posy = Config.WINDOW_WH[1]/2;
        this.width = w;
        this.height = h;
        this.image = new ImageIcon(getClass().getResource("/"+img)).getImage();
    }

    public Image getImage() {
        return this.image;
    }

    public void setPosx(int x) {posx = x;}
    public void setPosy(int y) {posy = y;}
    public void setImg(Image img) {
        this.image = img; 
    }

    public void update(HashMap keyDownMap) {
        // pass
    }
}

Config.java

package asteroids;

import java.awt.Color;

public class Config {

    // MAIN CANVAS SETTINGS
    public static int[] WINDOW_WH = {500, 500};
    public static String WINDOW_BG_IMG = "";
    public static Color WINDOW_BG_CLR = new Color(40, 42, 45);

    // OBJECT SETTINGS
    public static int[] STAR_SIZES = {10,5,8,3,7};
    public static float lerpSpeed = 0.8f; 
}
Feelsbadman
  • 1,163
  • 4
  • 17
  • 37
  • So, I modified your code to run (without all the image assets) and it seems to work fine for me. Some of the issues I see are; reliance of "fixed" values, like `WINDOW_WH`, when you should be using the `Canvas` bounds instead. It's important to not that the size of the `Canvas` will be the `size of the window` - `the window borders`, so your canvas is going to be smaller in size; I used `g.fillRect(0, 0, getWidth(), getHeight());` to clear the `Graphics` context instead of drawing the image, this might have had an effect – MadProgrammer Nov 02 '17 at 19:42
  • I'd recommend having a look at the key bindings API over using `KeyListener`, it will, at the very least, fix the focus related issues. – MadProgrammer Nov 02 '17 at 19:43
  • As a general suggestion, your entities should update and paint themselves – MadProgrammer Nov 02 '17 at 19:43
  • I tried to change lerp speed form 0.8f to 1 and it works fine, why would 0.x cause that kind of issue ? – Feelsbadman Nov 02 '17 at 20:06
  • No, idea, as I said, I stripped out the images and simply reduced the stars to 1 to test the code it worked. I increased the stars to 50 and it worked. I suspect a paint issue, but I can't be sure – MadProgrammer Nov 02 '17 at 21:02
  • I don't really understand your motion formula. But you might experience troubles because you have the positions as integer variables. But that's just a shot in the dark. – Nico Schertler Nov 03 '17 at 07:14
  • @NicoSchertler I use lerp formula & position variables are INT because drawImage method doesn't allow float or double – Feelsbadman Nov 04 '17 at 19:44
  • 1
    That's why you need to cast them to int for drawing. You would still keep them as floats for the simulation. – Nico Schertler Nov 04 '17 at 21:22

0 Answers0