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