1

I am currently working on my first jump'n Run game. The initial part is already working decent, but i still get a "bug" which appears when my "colums" are moving. This only happens when "MOVE_SPEED" is 1<. I tryed it with a Timer too, same thing.

This is how it looks like:

enter image description here

Please have a look at the code:

...
public class Board implements Runnable, KeyListener {

JFrame frame;
ArrayList<Column> cList;
Player p;
private boolean ingame = false;
public final static int INIT_WIDTH = 600;
public final static int INIT_HEIGHT = 400;
public static int WIDTH;
public static int HEIGHT;

private final int MOVE_SPEED = 10;
//When this is 1 the problem doesnt appear!

private final int GRAVITY = -3;
private int cPlayerStayingOn;
private double playerBottom;
private double floorTop;
private boolean mR = false;
private boolean mL = false;
private boolean jump = false;
long lastLoopTime = System.nanoTime();
final int TARGET_FPS = 100;
final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;
private int fps;
private int lastFpsTime;
public static double delta = 1;

public Board() {

    initBoard();
    initPlayer();
    initColumns();

}

private void initBoard() {

    frame = new JFrame("Jump'nRun");
    frame.setSize(INIT_WIDTH, INIT_HEIGHT);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLayout(null);
    frame.addKeyListener(this);

    cList = new ArrayList<Column>();

    frame.setVisible(true);

    Board.WIDTH = frame.getContentPane().getWidth();
    Board.HEIGHT = frame.getContentPane().getHeight();

}

private void initColumns() {

    for (int i = 0; i < 8; i++) {

        cList.add(new Column(i + 1, true));
        frame.add(cList.get(i));
    }
}

private void initPlayer() {

    p = new Player();
    frame.add(p);
}

private void moveColums() {

    for (Column col : cList) {

        col.setLocation((int) (col.getLocation().getX() - MOVE_SPEED), 0);
    }
}

private int playerStanding(double pX) {

    for (int i = 0; i < 8; i++) {

        if (cList.get(i).getX() <= pX
                && (cList.get(i).getX() + cList.get(i).getWidth()) >= pX) {

            return i;
        }
    }
    return -1;

}

private void movePlayer() {

    // gravity
    if (playerBottom < floorTop) {
        p.setLocation((int) p.getLocation().getX(), (int) p.getLocation()
                .getY() - GRAVITY);
    }

    if (mR) {
        p.moveRight();
    }

    if (mL) {
        p.moveLeft();
    }

    if (jump) {
        p.jump();
        jump = false;
    }

}

private void collectData() {

    this.cPlayerStayingOn = playerStanding(p.getBounds().getX()
            + p.getBounds().getWidth());

    this.playerBottom = p.getBounds().getMaxY();
    this.floorTop = cList.get(cPlayerStayingOn).floor.getY();
}

private void recycleColums() {

    if (cList.get(0).getX() + cList.get(0).getWidth() <= 0) {

        cList.remove(0);
        cList.add(7, new Column(7 + 1, false));

        frame.add(cList.get(7));

    }
}

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

}

@Override
public void keyPressed(KeyEvent e) {

    if (e.getKeyCode() == KeyEvent.VK_SPACE
            || e.getKeyCode() == KeyEvent.VK_W
            || e.getKeyCode() == KeyEvent.VK_UP) {

        if (playerBottom >= floorTop) {
            jump = true;

        }
    }

    if (e.getKeyCode() == KeyEvent.VK_D
            || e.getKeyCode() == KeyEvent.VK_RIGHT) {

        mR = true;
    }

    if (e.getKeyCode() == KeyEvent.VK_A
            || e.getKeyCode() == KeyEvent.VK_LEFT) {

        mL = true;
    }

}

@Override
public void keyReleased(KeyEvent e) {

    if (e.getKeyCode() == KeyEvent.VK_D
            || e.getKeyCode() == KeyEvent.VK_RIGHT) {

        mR = false;
    }

    if (e.getKeyCode() == KeyEvent.VK_A
            || e.getKeyCode() == KeyEvent.VK_LEFT) {

        mL = false;
    }

}

private int getFps() {

    return fps;
}

private void setFps(int fps) {

    this.fps = fps;
}

@Override
public void run() {

    while (true) {

        if (!ingame) {

            ingame = true;

        } else {

            long now = System.nanoTime();
            long updateLength = now - lastLoopTime;
            lastLoopTime = now;
            delta = updateLength / ((double) OPTIMAL_TIME);
            lastFpsTime += updateLength;
            setFps(getFps() + 1);

            if (lastFpsTime >= 1000000000) {
                lastFpsTime = 0;
                setFps(0);
            }

            recycleColums();

            collectData();
            moveColums();
            movePlayer();

            try {
                Thread.sleep((lastLoopTime - System.nanoTime() + OPTIMAL_TIME) / 1000000);
            } catch (Exception e) {

            }
        }
    }
}

}

and the Column Class:

...
public class Column extends JPanel {

JPanel floor;
JPanel grass;

Random rand = new Random();

private static final long serialVersionUID = 1L;

public final static int WIDTH = Board.WIDTH / 6;
public final int HEIGHT = Board.HEIGHT;

private int position;

public final static int FLOOR_H = WIDTH;

public Column(int pos, boolean init) {

    this.position = pos;

    setBounds((WIDTH * position) - WIDTH, 0, WIDTH, HEIGHT);
    setLayout(null);
    setBackground(Color.WHITE);

    floor = new JPanel();
    floor.setLayout(null);
    floor.setBackground(Color.BLACK);

    if (init) {

        floor.setBounds(0, HEIGHT - FLOOR_H, WIDTH, FLOOR_H);

    } else {

        floor.setBounds(0,
                (HEIGHT - (FLOOR_H + (FLOOR_H * rand.nextInt(2) / 2))),
                WIDTH, FLOOR_H * 2);
    }

    grass = new JPanel();
    grass.setBounds(0, 0, WIDTH, 10);
    grass.setBackground(Color.GREEN);

    floor.add(grass);
    add(floor);

   }
}

Any hints are appreciatet!

(Sorry for the bad english)

licklake
  • 236
  • 4
  • 15
  • What exactly is the problem? What is the bug? Are the columns not supposed to be there? – Slubberdegullion Apr 19 '16 at 20:00
  • the problem are these small gaps between my columns. (I marked them with blue arrows in the picture) – licklake Apr 19 '16 at 20:07
  • so when you say columns, you mean the black and green tiles/land? – Slubberdegullion Apr 19 '16 at 20:21
  • exactly, i dont know how to call them otherwise ^^ – licklake Apr 19 '16 at 20:25
  • 1
    Swing objects must be created and manipulated in the AWT Event Dispatch Thread. You are modifying them in another thread, which is why you're seeing strange behavior. See https://docs.oracle.com/javase/tutorial/uiswing/concurrency/ and https://stackoverflow.com/questions/7217013/java-event-dispatching-thread-explanation . – VGR Apr 19 '16 at 20:30
  • If VGR's suggestion isn't correct, does this happen immediately or only after you recycle your 'columns'? I'm just trying to work the code through my head and my guess is that the problem is a math problem if it isn't threading. – Slubberdegullion Apr 19 '16 at 20:37
  • Sorry, i can't check this right now. First i have to gather the KnowHow for awt event dispatching and fix my code. Then we'll see :) – licklake Apr 19 '16 at 20:44

1 Answers1

1

i fixed it by changing the following:

private void recycleColums() {

if (cList.get(0).getX() + cList.get(0).getWidth() <= 0) {

    cList.remove(0);
    cList.add(7, new Column(7 + 1, false, cList.get(6).getX()));

    frame.add(cList.get(7));

  }
}

...

public Column(int pos, boolean init, int lastX) {

    this.position = pos;


    setLayout(null);
    setBackground(Color.WHITE);

    floor = new JPanel();
    floor.setLayout(null);
    floor.setBackground(Color.BLACK);

    if (init) {

        setBounds((WIDTH * position) - WIDTH, 0, WIDTH, HEIGHT);
        floor.setBounds(0, HEIGHT - FLOOR_H, WIDTH, FLOOR_H);

    } else {

        setBounds(lastX + WIDTH, 0, WIDTH, HEIGHT);
        floor.setBounds(0,
                (HEIGHT - (FLOOR_H + (FLOOR_H * rand.nextInt(2) / 2))),
                WIDTH, FLOOR_H * 2);
    }
licklake
  • 236
  • 4
  • 15