更好的游戏循环/引擎

时间:2014-12-23 22:19:41

标签: java

我对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;
    }

}

enter image description here

正如你可能会说的那样,我正在渲染很多外部图像。

1 个答案:

答案 0 :(得分:0)

你的渲染可能效率低下,导致它低于目标60hz。除此之外,你的#34;赶上&#34;肯定存在问题。循环:

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

由于tick()例程也调用render(),因此tick()实际上是一个帧,但是你没有递增帧计数器。你的tick()应该导致所有部分更新,但不渲染图像,渲染应该每帧只调用一次。您可能希望从tick()例程中删除render()行。