Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 更好的游戏循环/引擎_Java - Fatal编程技术网

Java 更好的游戏循环/引擎

Java 更好的游戏循环/引擎,java,Java,我对Java游戏编程相当陌生,我想知道是否有人能帮我完成游戏循环。我试图避免使用预先制作的引擎库,我想看看自己是否能做到这一点。目前,我的游戏循环给了我一个非常低的FPS,有时甚至是个位数。在这种情况下,我必须使用多线程吗?还是有更好的方法解决这个问题?非常感谢您的帮助 下面是运行游戏循环的代码。我不包括所有的代码,因为它将有很多文件,但我认为这可能足够了,如果您需要更多,请告诉我。我还提供了一个我正在尝试创建的游戏的屏幕截图。提前谢谢 package com.Farthorn.game; i

我对Java游戏编程相当陌生,我想知道是否有人能帮我完成游戏循环。我试图避免使用预先制作的引擎库,我想看看自己是否能做到这一点。目前,我的游戏循环给了我一个非常低的FPS,有时甚至是个位数。在这种情况下,我必须使用多线程吗?还是有更好的方法解决这个问题?非常感谢您的帮助

下面是运行游戏循环的代码。我不包括所有的代码,因为它将有很多文件,但我认为这可能足够了,如果您需要更多,请告诉我。我还提供了一个我正在尝试创建的游戏的屏幕截图。提前谢谢

package com.Farthorn.game;

import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferStrategy;

import javax.swing.ImageIcon;

public class Game extends Canvas implements Runnable
{
    private static final long serialVersionUID = -4431078110090264106L;
    public final static int WIDTH = 640;
    public final static int HEIGHT = WIDTH / 12 * 9;

    private Thread thread;
    private boolean running = false;
    private CharacterHandler cHandler;
    private ObjectHandler oHandler;
    public int change = 0;

    private String mapBackgroundTop = "/Users/Ahhblala/Desktop/FarthornPics/background_top.png";
    private String mapBackgroundBottom = "/Users/Ahhblala/Desktop/FarthornPics/background_bottom.png";
    private Image backgroundTop;
    private Image backgroundBottom;

    public Game()
    {
        ImageIcon i = new ImageIcon(mapBackgroundTop);
        backgroundTop = i.getImage();
        i = new ImageIcon(mapBackgroundBottom);
        backgroundBottom = i.getImage();

        cHandler = new CharacterHandler();
        cHandler.addCharacter(new Player(ID.Player, WIDTH/2-32, HEIGHT/2+64));
        cHandler.addCharacter(new PlantEnemy(ID.PlantEnemy, WIDTH+180, HEIGHT/2+104, (Player)     cHandler.characters.getLast()));
        cHandler.addCharacter(new PlantEnemy(ID.PlantEnemy, WIDTH+195, HEIGHT/2+104, (Player) cHandler.characters.get(0)));
        cHandler.addCharacter(new PlantEnemy(ID.PlantEnemy, WIDTH+300, HEIGHT/2+104, (Player) cHandler.characters.get(0)));
        cHandler.addCharacter(new PlantEnemy(ID.PlantEnemy, WIDTH+315, HEIGHT/2+104, (Player) cHandler.characters.get(0)));

        oHandler = new ObjectHandler();
        oHandler.addObject(new HUD(10, 10, cHandler));

        this.addKeyListener(new KeyInput(cHandler));
        this.addMouseListener(new MouseInput(((Player) cHandler.characters.get(0))));

        FarthornWindow window = new FarthornWindow(WIDTH, HEIGHT, this);


    }

    public synchronized void start()
    {
        running = true;
        thread = new Thread(this);
        thread.start();
    }

    public synchronized void stop()
    {
        try
        {
            thread.join();
            running = false;
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    public void run() 
    {
        this.requestFocus();
        long lastTime = System.nanoTime();
        double amountOfTicks = 60.0;
        double ns = 1000000000 / amountOfTicks;
        double delta = 0;
        long timer = System.currentTimeMillis();
        int frames = 0;
        while (running)
        {
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            while (delta >= 1)
            {
                tick();
                delta--;
            }
            if (running)
            {
                render();
            }
            frames++;

            if(System.currentTimeMillis() - timer > 1000)
            {
                timer += 1000;
                System.out.println("FPS " + frames);
                frames = 0;
            }
        }
        stop();
    }

    private void tick()
    {       
        int deltaX = 0;
        int afterX = 0;

        deltaX = cHandler.characters.get(0).getX();

        oHandler.tick();
        cHandler.tick();

        deltaX = cHandler.characters.get(0).getX();
        if (deltaX != afterX)
            change = (afterX-deltaX);
        else
            change = 0;

        render();
    }

    private void render()
    {
        BufferStrategy bs = this.getBufferStrategy();
        if (bs == null)
        {
            this.createBufferStrategy(3);
            return;
        }

        Graphics g = bs.getDrawGraphics();

        g.drawImage(backgroundTop, 0+change, 0, null);
        g.drawImage(backgroundBottom, 0+change, 364, null);

        oHandler.render(g);
        cHandler.render(g);

        g.dispose();
        bs.show();
    }


    public static int clamp(int var, int min, int max)
    {
        if (var >= max)
        {
            return var = max;
        }
        else if (var <= min){
            return var = min;
        }
        else
            return var;
    }

}

正如您可能知道的,我正在渲染许多外部图像。

可能是渲染效率低下导致其低于您的目标60hz。除此之外,您的追赶循环中肯定存在一个问题:

    long now = System.nanoTime();
    delta += (now - lastTime) / ns;
    lastTime = now;
    while (delta >= 1)
    {
        tick();
        delta--;
    }

由于tick例程也调用render,tick本身实际上是一个帧,但您并没有增加帧计数器。您的勾选应该会导致所有部分更新,但不会渲染图像,渲染应该每帧只调用一次。您可能想从勾选例程中删除渲染线。

您可能会更好地询问此问题,但在发布之前请查看他们的帮助中心。哇,我甚至都没意识到我又在调用渲染,非常感谢您,完全修复了FPS!