我最初写的是开始在Windows上写这个,它运行得非常顺利,虽然它偶尔会冻结;但是,在我切换到Linux后,图形非常不稳定。我希望它之前有用,因为我有适合我的视频卡的驱动程序,但是在切换之后,我可能会从糟糕的驱动程序中获得较少的性能。虽然,2D游戏引擎应该能够运行在非常糟糕的计算机上。我想知道为什么跑得这么慢,以及我怎么能跑得更快。除了下面的类之外还有其他类,但下面的类包含程序的大部分主要功能。
package Platformer;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.sound.sampled.*;
import javax.sound.sampled.LineEvent.Type;
import javax.swing.JPanel;
import javax.swing.Timer;
public abstract class GameComponent extends JPanel{
//delete this i think
public static int ticks=0;
public Rectangle box;
private final int FPS=40;
public int xMovement=0;
public int yMovement=0;
public final int A=0,D=1,S=2,W=3,SPACE=4;
public boolean[] keyPressed=new boolean[5];
private InputController keyListener;
public ArrayList<Entity> Entities=new ArrayList<Entity>();
HashMap sounds=new HashMap();
public boolean drawLines=false;
public int xAxisLines=40;
public int yAxisLines=27;
Quadtree quad=new Quadtree(0,new Rectangle(0,0,1920,1080));
public GameComponent(){
keyListener=new InputController();
box=new Rectangle(90,90,20,20);
setFocusable(true);
requestFocusInWindow(true);
run();
}
public void run(){
addKeyListener(keyListener);
Timer timer=new Timer(1000/FPS, new ActionListener(){
@Override
public void actionPerformed(ActionEvent arg0) {
//movement();
gameLoop();
collisions();
repaint();
ticks++;
if(ticks==360 || ticks==1000){
try{
playSound("spun");
}
catch(Exception e){
e.printStackTrace();
}
}
}
});
timer.start();
}
@Override
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d=(Graphics2D)g.create();
//g2d.setColor(Color.RED);
//g2d.fill(box);
for(Entity entity: Entities){
g2d.drawImage(entity.IMAGE, entity.getX(),entity.getY(), entity.IMAGE.getWidth(), entity.IMAGE.getHeight(), null);
g2d.drawString(String.valueOf(entity.NAME), entity.getX(), entity.getY());
}
///draw lines in window if enabiled
if(drawLines){
drawLines(g2d);
}
///do collisions
g2d.dispose();
}
class InputController implements KeyListener{
@Override
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_W:
keyPressed[W]=true;
break;
case KeyEvent.VK_S:
keyPressed[S]=true;
break;
case KeyEvent.VK_A:
keyPressed[A]=true;
break;
case KeyEvent.VK_D:
keyPressed[D]=true;
break;
case KeyEvent.VK_SPACE:
keyPressed[SPACE]=true;
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
switch(e.getKeyCode()){
case KeyEvent.VK_W:
keyPressed[W]=false;
break;
case KeyEvent.VK_S:
keyPressed[S]=false;
break;
case KeyEvent.VK_A:
keyPressed[A]=false;
break;
case KeyEvent.VK_D:
keyPressed[D]=false;
break;
case KeyEvent.VK_SPACE:
keyPressed[SPACE]=false;
}
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
public abstract void gameLoop();
public void drawLines(Graphics2D g2d){
for(int i=0;i<1920;i+=1920/xAxisLines){
g2d.drawLine(i, 0, i, 1080);
}
for(int i=0;i<1080;i+=1080/yAxisLines){
g2d.drawLine(0, i, 1920, i);
}
}
public void collisions(){
////collisions!
ArrayList<Entity> returnEntities=new ArrayList<Entity>();
quad.clear();
for(int i=0;i<Entities.size();i++){
quad.insert(Entities.get(i));
}
for(int i=0;i <Entities.size();i++){
returnEntities.clear();
returnEntities=quad.retrieve(returnEntities,Entities.get(i));
for(Entity e:returnEntities){
//System.out.println(Entities.get(i).NAME+" could collide with "+e.NAME);
if(Math.abs(Entities.get(i).getX()-e.getX())<= Entities.get(i).IMAGE.getWidth()/2+e.IMAGE.getWidth()/2 && Math.abs(Entities.get(i).getY()-e.getY())<= Entities.get(i).IMAGE.getHeight()/2+e.IMAGE.getHeight()/2 && Entities.get(i)!=e){
//System.out.println(Entities.get(i).NAME+" is colliding with "+e.NAME);
}
}
}
////collisions!
/*
System.out.println(String.valueOf(quad.getIndex(Entities.get(0))));
System.out.println(Entities.get(0).bounds.x);
System.out.println(Entities.get(0).bounds.y);
*/
}
public void playSound(String fileName) throws IOException,
UnsupportedAudioFileException, LineUnavailableException, InterruptedException {
File clipFile=new File("assets//"+fileName+".wav");
class AudioListener implements LineListener {
private boolean done = false;
@Override public synchronized void update(LineEvent event) {
Type eventType = event.getType();
if (eventType == Type.STOP || eventType == Type.CLOSE) {
done = true;
notifyAll();
}
}
public synchronized void waitUntilDone() throws InterruptedException {
while (!done) {}
}
}
class SoundThread implements Runnable {
AudioListener listener = new AudioListener();
AudioInputStream audioInputStream;
public SoundThread() throws UnsupportedAudioFileException, IOException{
audioInputStream = AudioSystem.getAudioInputStream(clipFile);
}
@Override
public void run() {
try{
Clip clip=AudioSystem.getClip();
clip.addLineListener(listener);
clip.open(audioInputStream);
try{
clip.start();
listener.waitUntilDone();
}
finally{
clip.close();
}
}
catch(Exception e){
e.printStackTrace();
}
finally{
try {
audioInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Thread thread=new Thread(new SoundThread());
thread.start();
}
}
答案 0 :(得分:3)
嗯,你已经在程序上写了它,而不是面向对象。你有许多列表被迭代,也许如果你重构它然后你可以加快它,有没有我们可以得到代码(github等),就像这个片段我们没有太多我们可以做的帮助
答案 1 :(得分:3)
执行Graphics2D g2d=(Graphics2D)g.create()
和g2d.dispose();
的任何具体原因?
你不能只Graphics2D g2d = (Graphics2D) g;
吗?它可能会提高性能。
答案 2 :(得分:3)
TLDR;但设法发现了两个基本错误:
paint()
来制作图片。使用覆盖安全paintComponent()
。 (除了@ YoavAharoni的观点,每次重新绘制时都不要创建新的图形上下文。)
在您的情况下,您在计时器的事件方法中调用gameLoop()
,collisions()
和playSound()
- 我认为这很费时间。相反,请使用java.util.Timer
或线程。
如果您必须使用EDT,以便渲染持久的图形,请使用SwingWorker
。 (注意:repaint()
可以在EDT之外调用
答案 3 :(得分:0)
我不知道您使用的是什么IDE,但我建议您进行分析。 Eclipse有一个很好的插件。
一旦我不得不自己写游戏,我的问题就在于图像的大小:
``g2d.drawImage(entity.IMAGE, entity.getX(),entity.getY(), entity.IMAGE.getWidth(), entity.IMAGE.getHeight(), null);``
我必须将每个图像的尺寸减小到40kb以下才能正常运行。
另一件事是你在UI上切换了一些元素,看看是什么能够大大提升性能,然后你可以调整那个组件。