Java游戏循环:帧跳跃

Java游戏循环:帧跳跃,java,game-engine,2d-games,game-loop,Java,Game Engine,2d Games,Game Loop,我在Youtube上发布了一段视频,你可以在那里看到问题所在。我已经放慢了视频的速度,所以你真的可以看到跳跃 链接: 这个问题在视频的最后部分最为明显。你可以清楚地看到画面跳跃,就像跳过了一两帧 我没有滞后或性能问题,因为我运行游戏的电脑采用了最新技术 我认为这可能与游戏循环有关,比如舍入错误之类的,但我似乎在代码中找不到任何错误。。 我在网上找过类似的问题,但找不到 这是我的密码 GUI 导入java.awt.Container; 导入java.awt.Graphics2D; 导入java.a

我在Youtube上发布了一段视频,你可以在那里看到问题所在。我已经放慢了视频的速度,所以你真的可以看到跳跃

链接:

这个问题在视频的最后部分最为明显。你可以清楚地看到画面跳跃,就像跳过了一两帧

我没有滞后或性能问题,因为我运行游戏的电脑采用了最新技术

我认为这可能与游戏循环有关,比如舍入错误之类的,但我似乎在代码中找不到任何错误。。 我在网上找过类似的问题,但找不到

这是我的密码 GUI

导入java.awt.Container;
导入java.awt.Graphics2D;
导入java.awt.event.KeyAdapter;
导入java.awt.event.KeyEvent;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.awt.image.buffereImage;
导入javax.swing.JFrame;
公共类Gui扩展JFrame实现可运行{
私有静态最终长serialVersionUID=1L;
公共静态最终整数帧/PR/SEC=60;
公共静态最终整数时间帧=1000/帧/秒;
公共静态最终整数裕度_X=3;
公共静态最终整数余量_Y=32;
公共静态最终整数宽度=800;
公共静态最终内部高度=600;
公共静态int TILE_SIZE=32;
公共静态积分速度=5;
公共静态void main(最终字符串[]args){
新Gui();
}
私人游戏;
私人货柜;;
专用缓冲区映像;
私有图形2dg;
公共图形用户界面(){
超级(“基于瓷砖的游戏”);
设置大小(宽度+边距X+3,高度+边距Y-4);
可设置大小(假);
setVisible(真);
setLocationRelativeTo(空);
setDefaultCloseOperation(关闭时退出);
_cp=getContentPane();
_游戏=新游戏();
新图形();
addMouseListener(新的MouseAdapter(){
@凌驾
public void mousePressed(最终MouseEvent arg0){
_mP(arg0.getX()-MARGIN\ux,arg0.getY()-MARGIN\uy);
}
@凌驾
公共无效鼠标事件(最终鼠标事件arg0){
_game.mR(arg0.getX()-MARGIN\ux,arg0.getY()-MARGIN\uy);
}
});
addKeyListener(新的KeyAdapter(){
@凌驾
按下公共无效键(最终键事件arg0){
_game.keyP(arg0.getKeyCode());
}
@凌驾
公共无效密钥已释放(最终密钥事件arg0){
_game.keyR(arg0.getKeyCode());
}
});
新线程(this.start();
}
私有void newGraphics(){
_img=getGraphicsConfiguration().createCompatibleImage(宽度、高度);
_g=_img.createGraphics();
}
@凌驾
公开募捐{
while(true){
很久以前=System.currentTimeMillis();
_game.update();
新图形();
_游戏。平局(_g);
_cp.getGraphics().drawImage(_img,0,0,null);
long after=System.currentTimeMillis();
长睡眠=时间帧-(之后-之前);
System.out.println(睡眠);
如果(睡眠<5){
睡眠=5;
}
试一试{
睡眠;
}捕捉(中断异常e){
}
}
}
}
我想您需要的所有东西都在GUI类中,但我已经包括了其他类,以防您需要它们中的任何东西

游戏课

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;

public class Game {
private Map[] _maps;
private String[] _mapNames;
private int _currentMap;

private boolean _r;
private boolean _l;
private boolean _u;
private boolean _d;

public Game() {
    _mapNames = new String[0];
    _maps = new Map[0];
    addMap("test.map");

}

public void addMap(final String s) {
    String[] stringTemp = _mapNames;
    _mapNames = new String[stringTemp.length + 1];
    for (int i = 0; i < stringTemp.length; i++) {
        _mapNames[i] = stringTemp[i];
    }
    _mapNames[_mapNames.length - 1] = s.replace(".map", "");
    Map[] mapTemp = _maps;
    _maps = new Map[mapTemp.length + 1];
    for (int i = 0; i < mapTemp.length; i++) {
        _maps[i] = mapTemp[i];
    }
    _maps[_maps.length - 1] = new Map(s);
}

public void draw(final Graphics2D _g) {
    _maps[_currentMap].draw(_g);
    _g.setColor(Color.WHITE);
    _g.drawString(_mapNames[_currentMap], 5, 595);
}

public void keyP(final int keyCode) {
    if (keyCode == KeyEvent.VK_RIGHT) {
        _r = true;
    }
    if (keyCode == KeyEvent.VK_LEFT) {
        _l = true;
    }

    if (keyCode == KeyEvent.VK_UP) {
        _u = true;
    }
    if (keyCode == KeyEvent.VK_DOWN) {
        _d = true;
    }
}

public void keyR(final int keyCode) {
    if (keyCode == KeyEvent.VK_SPACE) {
        if (_currentMap < _maps.length - 1) {
            _currentMap++;
        } else {
            _currentMap = 0;
        }
    }
    if (keyCode == KeyEvent.VK_RIGHT) {
        _r = false;
    }
    if (keyCode == KeyEvent.VK_LEFT) {
        _l = false;
    }

    if (keyCode == KeyEvent.VK_UP) {
        _u = false;
    }
    if (keyCode == KeyEvent.VK_DOWN) {
        _d = false;
    }
}

public void mP(final int i, final int j) {

}

public void mR(final int i, final int j) {

}

public void update() {

    if (_r) {
        _maps[_currentMap].incOffsetX(Gui.SPEED);
    }
    if (_l) {
        _maps[_currentMap].decOffsetX(Gui.SPEED);
    }
    if (_u) {
        _maps[_currentMap].decOffsetY(Gui.SPEED);
    }
    if (_d) {
        _maps[_currentMap].incOffsetY(Gui.SPEED);
    }
    _maps[_currentMap].update();
}
}
导入java.awt.Color;
导入java.awt.Graphics2D;
导入java.awt.event.KeyEvent;
公开课游戏{
私人地图[]_地图;
私有字符串[]\u映射名称;
私有int_currentMap;
私有布尔函数;
私有布尔函数;
私有布尔_;
私有布尔函数;
公共游戏(){
_mapNames=新字符串[0];
_地图=新地图[0];
addMap(“test.map”);
}
公共void addMap(最终字符串s){
字符串[]stringTemp=\u映射名;
_mapNames=新字符串[stringTemp.length+1];
对于(int i=0;i
最后是Map类(处理.Map文件等的加载)

导入java.awt.Color;
导入java.awt.Graphics2D;
导入java.awt.Image;
导入java.awt.image.buffereImage;
导入java.io.BufferedReader;
导入java.io.File;
导入java.io.FileNotFoundException;
导入java.io.FileReader;
导入java.io.IOException;
导入javax.imageio.imageio;
公共类地图{
私人类瓷砖{
私人形象;
私人互联网;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;

public class Game {
private Map[] _maps;
private String[] _mapNames;
private int _currentMap;

private boolean _r;
private boolean _l;
private boolean _u;
private boolean _d;

public Game() {
    _mapNames = new String[0];
    _maps = new Map[0];
    addMap("test.map");

}

public void addMap(final String s) {
    String[] stringTemp = _mapNames;
    _mapNames = new String[stringTemp.length + 1];
    for (int i = 0; i < stringTemp.length; i++) {
        _mapNames[i] = stringTemp[i];
    }
    _mapNames[_mapNames.length - 1] = s.replace(".map", "");
    Map[] mapTemp = _maps;
    _maps = new Map[mapTemp.length + 1];
    for (int i = 0; i < mapTemp.length; i++) {
        _maps[i] = mapTemp[i];
    }
    _maps[_maps.length - 1] = new Map(s);
}

public void draw(final Graphics2D _g) {
    _maps[_currentMap].draw(_g);
    _g.setColor(Color.WHITE);
    _g.drawString(_mapNames[_currentMap], 5, 595);
}

public void keyP(final int keyCode) {
    if (keyCode == KeyEvent.VK_RIGHT) {
        _r = true;
    }
    if (keyCode == KeyEvent.VK_LEFT) {
        _l = true;
    }

    if (keyCode == KeyEvent.VK_UP) {
        _u = true;
    }
    if (keyCode == KeyEvent.VK_DOWN) {
        _d = true;
    }
}

public void keyR(final int keyCode) {
    if (keyCode == KeyEvent.VK_SPACE) {
        if (_currentMap < _maps.length - 1) {
            _currentMap++;
        } else {
            _currentMap = 0;
        }
    }
    if (keyCode == KeyEvent.VK_RIGHT) {
        _r = false;
    }
    if (keyCode == KeyEvent.VK_LEFT) {
        _l = false;
    }

    if (keyCode == KeyEvent.VK_UP) {
        _u = false;
    }
    if (keyCode == KeyEvent.VK_DOWN) {
        _d = false;
    }
}

public void mP(final int i, final int j) {

}

public void mR(final int i, final int j) {

}

public void update() {

    if (_r) {
        _maps[_currentMap].incOffsetX(Gui.SPEED);
    }
    if (_l) {
        _maps[_currentMap].decOffsetX(Gui.SPEED);
    }
    if (_u) {
        _maps[_currentMap].decOffsetY(Gui.SPEED);
    }
    if (_d) {
        _maps[_currentMap].incOffsetY(Gui.SPEED);
    }
    _maps[_currentMap].update();
}
}
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import javax.imageio.ImageIO;

public class Map {

private class Tile {
    private Image _img;
    private int _x;
    private int _y;

    public Tile(final Image img) {
        _img = img;
    }

    public Image getImg() {
        return _img;
    }

    public int getX() {
        return _x;
    }

    public int getY() {
        return _y;
    }

    public void setLoc(final int x, final int y) {
        _x = x * Gui.TILE_SIZE;
        _y = y * Gui.TILE_SIZE;
    }
}

private int _offsetX;
private int _offsetY;

private String[][] _map;

private Tile[][] _tileMap;

private BufferedImage _terrain;

private Color _waterColor;

public Map(final String s) {
    _terrain = loadImg("terrain.png");

    _waterColor = new Color(21, 108, 153);

    _map = loadMap(s);

    _offsetX = _map[0].length * Gui.TILE_SIZE / 2 - Gui.WIDTH / 2;
    _offsetY = _map.length * Gui.TILE_SIZE / 2 - Gui.HEIGHT / 2;

    _tileMap = new Tile[_map.length][_map[0].length];

    for (int i = 0; _map.length > i; i++) {
        for (int j = 0; _map[0].length > j; j++) {
            Image img;
            switch (_map[i][j]) {
            case "o":
                img = getSubimage(_terrain, 0, 0, 3, 6);
                break;
            case "0":
                img = getSubimage(_terrain, 0, 1, 3, 6);
                break;
            case "a":
                img = getSubimage(_terrain, 1, 0, 3, 6);
                break;
            case "b":
                img = getSubimage(_terrain, 2, 0, 3, 6);
                break;
            case "c":
                img = getSubimage(_terrain, 1, 1, 3, 6);
                break;
            case "d":
                img = getSubimage(_terrain, 2, 1, 3, 6);
                break;
            case "1":
                img = getSubimage(_terrain, 0, 2, 3, 6);
                break;
            case "2":
                img = getSubimage(_terrain, 1, 2, 3, 6);
                break;
            case "3":
                img = getSubimage(_terrain, 2, 2, 3, 6);
                break;
            case "4":
                img = getSubimage(_terrain, 0, 3, 3, 6);
                break;
            case "5":
                img = getSubimage(_terrain, 1, 3, 3, 6);
                break;
            case "6":
                img = getSubimage(_terrain, 2, 3, 3, 6);
                break;
            case "7":
                img = getSubimage(_terrain, 0, 4, 3, 6);
                break;
            case "8":
                img = getSubimage(_terrain, 1, 4, 3, 6);
                break;
            case "9":
                img = getSubimage(_terrain, 2, 4, 3, 6);
                break;
            case "#":
                img = getSubimage(_terrain, 0, 5, 3, 6);
                break;
            case "&":
                img = getSubimage(_terrain, 1, 5, 3, 6);
                break;
            case "%":
                img = getSubimage(_terrain, 2, 5, 3, 6);
                break;
            default:
                img = null;
                break;
            }
            Tile tile = new Tile(img);
            int x = j;
            int y = i;
            tile.setLoc(x, y);
            _tileMap[i][j] = tile;
        }
    }
}

public void decOffsetX(final int i) {
    _offsetX -= i;
}

public void decOffsetY(final int i) {
    _offsetY -= i;
}

public void draw(final Graphics2D _g) {
    for (int i = 0; _tileMap.length > i; i++) {
        for (int j = 0; _tileMap[0].length > j; j++) {
            if (_tileMap[i][j].getImg() != null
                    && isVisible(_tileMap[i][j])) {
                _g.drawImage(_tileMap[i][j].getImg(), _tileMap[i][j].getX()
                        - _offsetX, _tileMap[i][j].getY() - _offsetY, null);
            } else if (_tileMap[i][j].getImg() == null
                    && isVisible(_tileMap[i][j])) {
                _g.setColor(_waterColor);
                _g.fillRect(_tileMap[i][j].getX() - _offsetX,
                        _tileMap[i][j].getY() - _offsetY, Gui.TILE_SIZE,
                        Gui.TILE_SIZE);
            }
        }
    }
}

private Image getSubimage(final BufferedImage img, final int x,
        final int y, final int w, final int h) {
    return img.getSubimage(x * Gui.TILE_SIZE, y * Gui.TILE_SIZE,
            Gui.TILE_SIZE, Gui.TILE_SIZE);

}

public void incOffsetX(final int i) {
    _offsetX += i;
}

public void incOffsetY(final int i) {
    _offsetY += i;
}

public boolean isVisible(final Tile tile) {
    if (tile.getX() - _offsetX < 0 - Gui.TILE_SIZE) {
        return false;
    } else if (tile.getX() - _offsetX > Gui.WIDTH) {
        return false;
    }
    if (tile.getY() - _offsetY < 0 - Gui.TILE_SIZE) {
        return false;
    } else if (tile.getY() - _offsetY > Gui.HEIGHT) {
        return false;
    }
    return true;
}

private BufferedImage loadImg(final String s) {
    BufferedImage img = null;
    try {
        img = ImageIO.read(new File("res/" + s));
    } catch (IOException e) {
    }
    return img;
}

private String[][] loadMap(final String s) {
    String _s = null;
    String string = null;
    int appear = 0;
    try {
        BufferedReader br;
        br = new BufferedReader(new FileReader("res/maps/" + s));
        while ((_s = br.readLine()) != null) {
            string = string + _s + ",";
            appear++;
        }
        br.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    String[] ss = string.replaceAll("null", "").split(",");
    String[][] items = new String[appear][];
    for (int i = 0; i < items.length; i++) {
        items[i] = ss[i].split(" ");
    }

    return items;
}

public void update() {
    if (_offsetX < 0) {
        _offsetX += Gui.SPEED;
    } else if (_offsetX > _map[0].length * Gui.TILE_SIZE - Gui.WIDTH
            - Gui.SPEED) {
        _offsetX -= Gui.SPEED;
    }
    if (_offsetY < 0) {
        _offsetY += Gui.SPEED;
    } else if (_offsetY > _map.length * Gui.TILE_SIZE - Gui.HEIGHT
            - Gui.SPEED) {
        _offsetY -= Gui.SPEED;
    }
}
}