如何确保游戏在其他计算机上的速度不 运行?
How to make sure the game isnt running faster on other computers?
我正在做一个游戏,现在我只是在修图,按键输入等等。现在我只有一个皮卡丘用方向键移动(游戏与口袋妖怪,皮卡丘只是我选择的图像)我想确保游戏不会因为软件功能在其他计算机上 运行 更快(因为皮卡丘从 A 点到 B 点的速度比另一个快计算机,而不是像其他游戏那样只是有点滞后)
我相信我做对了,因为我听说不要将引擎绑定到框架上,而框架唯一要做的就是显示它的 X、Y 等。其他一切都在框架之外完成帧.
这是我的代码:
package net.trenterprises;
import java.awt.MouseInfo;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
public class Main implements KeyListener {
static JLabel LabelImage = null;
static ArrayList<String> KeysPressed = new ArrayList<String>();
static int UP = 38;
static int DOWN = 40;
static int LEFT = 37;
static int RIGHT = 39;
public static void main(String[] args) {
Window TestWindow = new Window("Mouse Location", null);
KeyListener listener = new Main();
TestWindow.addKeyListener(listener);
TestWindow.setLayout(null);
int MouseX = 0;
int MouseY = 0;
JLabel MouseLabel = new JLabel("???");
MouseLabel.setSize(MouseLabel.getPreferredSize());
TestWindow.add(MouseLabel);
try {
BufferedImage CUPCAKES = (ImageIO.read(new URL("http://img3.wikia.nocookie.net/__cb20140328192412/pokemon/images/thumb/0/0d/025Pikachu.png/200px-025Pikachu.png")));
LabelImage = new JLabel(new ImageIcon(CUPCAKES));
TestWindow.add(LabelImage);
LabelImage.setSize(LabelImage.getPreferredSize());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
LabelImage.setBounds(0, 0, LabelImage.getSize().width, LabelImage.getSize().height);
new PikaMoveUp().start();
new PikaMoveDown().start();
new PikaMoveLeft().start();
new PikaMoveRight().start();
while(true) {
MouseX = (MouseInfo.getPointerInfo().getLocation().x);
MouseY = (MouseInfo.getPointerInfo().getLocation().y);
MouseLabel.setText("Mouse X: " + MouseX + "\n Mouse Y: " + MouseY);
MouseLabel.setSize(MouseLabel.getPreferredSize());
MouseLabel.setBounds(0, 0, MouseLabel.getSize().width, MouseLabel.getSize().height);
}
}
public static int getPikaX() {
return LabelImage.getX();
}
public static int getPikaY() {
return LabelImage.getY();
}
public static void setPikachuPosition(int x, int y) {
LabelImage.setBounds(x, y, LabelImage.getSize().width, LabelImage.getSize().height);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
int Char = (int) e.getKeyChar();
int Keycode = (int) e.getKeyCode();
if(Char == 65535) {
if(Keycode == UP) {
if(!KeysPressed.contains(Keycode + "")) {
KeysPressed.add(Keycode + "");
}
}
if(Keycode == DOWN) {
if(!KeysPressed.contains(Keycode + "")) {
KeysPressed.add(Keycode + "");
}
}
if(Keycode == LEFT) {
if(!KeysPressed.contains(Keycode + "")) {
KeysPressed.add(Keycode + "");
}
}
if(Keycode == RIGHT) {
if(!KeysPressed.contains(Keycode + "")) {
KeysPressed.add(Keycode + "");
}
}
}
}
@Override
public void keyReleased(KeyEvent e) {
int Char = (int) e.getKeyChar();
int Keycode = (int) e.getKeyCode();
if(Char == 65535) {
if(Keycode == UP) {
while(KeysPressed.contains(Keycode + "")) {
KeysPressed.remove(Keycode + "");
}
}
if(Keycode == DOWN) {
while(KeysPressed.contains(Keycode + "")) {
KeysPressed.remove(Keycode + "");
}
}
if(Keycode == LEFT) {
while(KeysPressed.contains(Keycode + "")) {
KeysPressed.remove(Keycode + "");
}
}
if(Keycode == RIGHT) {
while(KeysPressed.contains(Keycode + "")) {
KeysPressed.remove(Keycode + "");
}
}
}
}
class PikaMoveUp extends Thread implements Runnable {
public void run() {
while(true) {
try {
while(Main.KeysPressed.contains(Main.UP + "")) {
Thread.sleep(5);
Main.setPikachuPosition(Main.getPikaX(), Main.getPikaY() - 1);
}
}
catch(Exception E) {
E.printStackTrace();
}
}
}
}
class PikaMoveDown extends Thread implements Runnable {
public void run() {
while(true) {
try {
while(Main.KeysPressed.contains(Main.DOWN + "")) {
Thread.sleep(5);
Main.setPikachuPosition(Main.getPikaX(), Main.getPikaY() + 1);
}
}
catch(Exception E) {
E.printStackTrace();
}
}
}
}
class PikaMoveLeft extends Thread implements Runnable {
public void run() {
while(true) {
try {
while(Main.KeysPressed.contains(Main.LEFT + "")) {
Thread.sleep(5);
Main.setPikachuPosition(Main.getPikaX() - 1, Main.getPikaY());
}
}
catch(Exception E) {
E.printStackTrace();
}
}
}
}
class PikaMoveRight extends Thread implements Runnable {
public void run() {
while(true) {
try {
while(Main.KeysPressed.contains(Main.RIGHT + "")) {
Thread.sleep(5);
Main.setPikachuPosition(Main.getPikaX() + 1, Main.getPikaY());
}
}
catch(Exception E) {
E.printStackTrace();
}
}
}
您通常会看到 delta-timing or fixed-timestep 实现到游戏循环中。
Delta 计时使用 delta
变量,该变量基于测量每帧之间的时间。您可以将所有变换乘以 delta
以使游戏在多台计算机上以相同的速度 运行。这很顺利,也很容易实现,但你必须记住将 所有 变换乘以 delta
.
另一方面,固定时间步长以某种方式控制帧之间的时间,从而消除了对增量变量的需要。众所周知,它有点不稳定/难以实施,但您不再需要在所有地方应用 delta
。
虽然您可以自己实现它,但切换到像 LibGDX 或 Slick2D 这样的实际游戏库会更容易,他们会在那里处理它(并且 很多 更多) 给你。
另外,使用过多的线程也可能导致性能不稳定。在基本游戏循环中更新时,移动可以以更简洁的方式完成;
if(Main.KeysPressed.contains(Main.LEFT + ""))
Main.setPikachuPosition(Main.getPikaX() - 1, Main.getPikaY());
我正在做一个游戏,现在我只是在修图,按键输入等等。现在我只有一个皮卡丘用方向键移动(游戏与口袋妖怪,皮卡丘只是我选择的图像)我想确保游戏不会因为软件功能在其他计算机上 运行 更快(因为皮卡丘从 A 点到 B 点的速度比另一个快计算机,而不是像其他游戏那样只是有点滞后)
我相信我做对了,因为我听说不要将引擎绑定到框架上,而框架唯一要做的就是显示它的 X、Y 等。其他一切都在框架之外完成帧.
这是我的代码:
package net.trenterprises;
import java.awt.MouseInfo;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
public class Main implements KeyListener {
static JLabel LabelImage = null;
static ArrayList<String> KeysPressed = new ArrayList<String>();
static int UP = 38;
static int DOWN = 40;
static int LEFT = 37;
static int RIGHT = 39;
public static void main(String[] args) {
Window TestWindow = new Window("Mouse Location", null);
KeyListener listener = new Main();
TestWindow.addKeyListener(listener);
TestWindow.setLayout(null);
int MouseX = 0;
int MouseY = 0;
JLabel MouseLabel = new JLabel("???");
MouseLabel.setSize(MouseLabel.getPreferredSize());
TestWindow.add(MouseLabel);
try {
BufferedImage CUPCAKES = (ImageIO.read(new URL("http://img3.wikia.nocookie.net/__cb20140328192412/pokemon/images/thumb/0/0d/025Pikachu.png/200px-025Pikachu.png")));
LabelImage = new JLabel(new ImageIcon(CUPCAKES));
TestWindow.add(LabelImage);
LabelImage.setSize(LabelImage.getPreferredSize());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
LabelImage.setBounds(0, 0, LabelImage.getSize().width, LabelImage.getSize().height);
new PikaMoveUp().start();
new PikaMoveDown().start();
new PikaMoveLeft().start();
new PikaMoveRight().start();
while(true) {
MouseX = (MouseInfo.getPointerInfo().getLocation().x);
MouseY = (MouseInfo.getPointerInfo().getLocation().y);
MouseLabel.setText("Mouse X: " + MouseX + "\n Mouse Y: " + MouseY);
MouseLabel.setSize(MouseLabel.getPreferredSize());
MouseLabel.setBounds(0, 0, MouseLabel.getSize().width, MouseLabel.getSize().height);
}
}
public static int getPikaX() {
return LabelImage.getX();
}
public static int getPikaY() {
return LabelImage.getY();
}
public static void setPikachuPosition(int x, int y) {
LabelImage.setBounds(x, y, LabelImage.getSize().width, LabelImage.getSize().height);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
int Char = (int) e.getKeyChar();
int Keycode = (int) e.getKeyCode();
if(Char == 65535) {
if(Keycode == UP) {
if(!KeysPressed.contains(Keycode + "")) {
KeysPressed.add(Keycode + "");
}
}
if(Keycode == DOWN) {
if(!KeysPressed.contains(Keycode + "")) {
KeysPressed.add(Keycode + "");
}
}
if(Keycode == LEFT) {
if(!KeysPressed.contains(Keycode + "")) {
KeysPressed.add(Keycode + "");
}
}
if(Keycode == RIGHT) {
if(!KeysPressed.contains(Keycode + "")) {
KeysPressed.add(Keycode + "");
}
}
}
}
@Override
public void keyReleased(KeyEvent e) {
int Char = (int) e.getKeyChar();
int Keycode = (int) e.getKeyCode();
if(Char == 65535) {
if(Keycode == UP) {
while(KeysPressed.contains(Keycode + "")) {
KeysPressed.remove(Keycode + "");
}
}
if(Keycode == DOWN) {
while(KeysPressed.contains(Keycode + "")) {
KeysPressed.remove(Keycode + "");
}
}
if(Keycode == LEFT) {
while(KeysPressed.contains(Keycode + "")) {
KeysPressed.remove(Keycode + "");
}
}
if(Keycode == RIGHT) {
while(KeysPressed.contains(Keycode + "")) {
KeysPressed.remove(Keycode + "");
}
}
}
}
class PikaMoveUp extends Thread implements Runnable {
public void run() {
while(true) {
try {
while(Main.KeysPressed.contains(Main.UP + "")) {
Thread.sleep(5);
Main.setPikachuPosition(Main.getPikaX(), Main.getPikaY() - 1);
}
}
catch(Exception E) {
E.printStackTrace();
}
}
}
}
class PikaMoveDown extends Thread implements Runnable {
public void run() {
while(true) {
try {
while(Main.KeysPressed.contains(Main.DOWN + "")) {
Thread.sleep(5);
Main.setPikachuPosition(Main.getPikaX(), Main.getPikaY() + 1);
}
}
catch(Exception E) {
E.printStackTrace();
}
}
}
}
class PikaMoveLeft extends Thread implements Runnable {
public void run() {
while(true) {
try {
while(Main.KeysPressed.contains(Main.LEFT + "")) {
Thread.sleep(5);
Main.setPikachuPosition(Main.getPikaX() - 1, Main.getPikaY());
}
}
catch(Exception E) {
E.printStackTrace();
}
}
}
}
class PikaMoveRight extends Thread implements Runnable {
public void run() {
while(true) {
try {
while(Main.KeysPressed.contains(Main.RIGHT + "")) {
Thread.sleep(5);
Main.setPikachuPosition(Main.getPikaX() + 1, Main.getPikaY());
}
}
catch(Exception E) {
E.printStackTrace();
}
}
}
您通常会看到 delta-timing or fixed-timestep 实现到游戏循环中。
Delta 计时使用 delta
变量,该变量基于测量每帧之间的时间。您可以将所有变换乘以 delta
以使游戏在多台计算机上以相同的速度 运行。这很顺利,也很容易实现,但你必须记住将 所有 变换乘以 delta
.
另一方面,固定时间步长以某种方式控制帧之间的时间,从而消除了对增量变量的需要。众所周知,它有点不稳定/难以实施,但您不再需要在所有地方应用 delta
。
虽然您可以自己实现它,但切换到像 LibGDX 或 Slick2D 这样的实际游戏库会更容易,他们会在那里处理它(并且 很多 更多) 给你。
另外,使用过多的线程也可能导致性能不稳定。在基本游戏循环中更新时,移动可以以更简洁的方式完成;
if(Main.KeysPressed.contains(Main.LEFT + ""))
Main.setPikachuPosition(Main.getPikaX() - 1, Main.getPikaY());