2016-06-04 6 views
0

В моей игре «SpcaeShip» у меня есть петлевая игра, которая обновляет и рисует все мои объекты. Теперь я хочу добавить в игру список астероидов и нарисовать их, но проблема в том, что если я рисую массив астероидов в игре с петлями, игра будет очень медленной. Мое решение состояло в том, чтобы нарисовать астероиды по таймеру, и скорость игры идеальна. Единственная проблема, с которой я сталкиваюсь, это то, что мои астрооиды постоянно мерцают. Мне нужно использовать bufferStrategy или что-то подобное?Мерцающее изображение, которое работает на потоке

Это мой метод рисования в цикле игр (в этом цикле я называю в игре государственного метод Draw):

private void tick() 
{ 
//update all objects 
} 

private void render() 
    { 
     //how many buffers(hold the same data as our screen) the canvas would use 
     bs = display.getCanvas().getBufferStrategy(); 


     if(bs == null) 
     { 
      display.getCanvas().createBufferStrategy(3); 
      return; 
     } 


     g = bs.getDrawGraphics(); 


     g.clearRect(0, 0, width, height); 

     if(State.getState() != null) 
     { 
      State.getState().render(g); 

     } 


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

    } 

public void run() 
{ 

    init(); 

    int fps = 60; 
    double timePerTick = 1000000000/ fps; 
    double delta = 0; 
    long now; 
    long lastTime =System.nanoTime(); 
    long timer = 0; 


    //game loop 
    while(running) 
    { 
     now = System.nanoTime(); 
     delta += (now - lastTime)/timePerTick; 
     timer += now - lastTime; 
     lastTime = now; 

     if(delta >= 1) 
     { 
      tick(); 
      render(); 
     } 
    } 

    stop(); 
} 

Это моя игра государственных методы:

import java.awt.Graphics;  
import java.awt.event.ActionEvent;  
import java.awt.event.ActionListener;  
import java.util.ArrayList;   
import javax.swing.Timer; 
public class GameState extends State 
{ 

    private SpaceShip spaceShip; 
    private BgHandler bgHandler; 
    private ArrayList<Meteor> meteors; 

    public GameState(Handler handler) 
    { 
     super(handler); 

     bgHandler = new BgHandler(handler.getWidth(), handler.getHeight()); 
     spaceShip = new SpaceShip(handler, handler.getWidth()/2 - Things.DEFAULT_OBJECT_WIDTH/2, 
       handler.getHeight() - Things.DEFAULT_OBJECT_HEIGHT - 100); 
     meteors = new ArrayList<Meteor>(); 

     for(int i = 0; i < 5; i++) 
     { 
      Meteor m = new Meteor(handler,(int) (Math.random() * (handler.getWidth() - Things.DEFAULT_OBJECT_WIDTH)) 
        , -Things.DEFAULT_OBJECT_WIDTH, 
        Things.DEFAULT_OBJECT_WIDTH, 
        Things.DEFAULT_OBJECT_HEIGHT); 

      meteors.add(m); 
     } 

     timer.start(); 

    } 

    Timer timer = new Timer (50, new ActionListener() 
    { 
     public void actionPerformed(ActionEvent e) 
     { 
      tickMeteor(); 
      renderMeteor(); 

     } 
    }); 

    public void tickMeteor() 
    { 
     for(int i = 0; i < meteors.size(); i++) 
     { 
      Meteor m = meteors.get(i); 

      if(m.getVisible()) 
      { 
       m.tick(); 
      } 
      else 
      { 
       meteors.remove(i); 
      } 
     } 
    } 

    public void renderMeteor() 
    { 

     for(Meteor m: meteors) 
     { 
      Meteor m1 = (Meteor) m; 

      if(m1.getVisible()) 
      { 
       m1.render(handler.getGame().getGraphics()); 
      } 
     } 
    } 


    @Override 
    public void tick() 
    { 
     spaceShip.tick(); 
     for(int i = 0; i < meteors.size(); i++) 
     { 
      Meteor m = meteors.get(i); 

      if(m.getVisible()) 
      { 
       m.tick(); 
      } 
      else 
      { 
       meteors.remove(i); 
      } 
     } 
    } 

    } 

    @Override 
    public void render(Graphics g) 
    { 
     bgHandler.render(g); 
     spaceShip.render(g); 

    }  
}  
+0

Проверьте, как часто 'если (State.getState()! = NULL)' генерирует пустой кадр – MadProgrammer

+0

Если вы используете BufferStategy, то вам не нужно использовать Swing-таймер, вы можете использовать ваша собственная тема, поскольку вам больше не нужно беспокоиться о синхронизации процесса рисования с EDT, поскольку они являются отдельным процессом. – MadProgrammer

+0

Итак, все должно быть обновлено и окрашено в одну и ту же нить и должно выполняться в одном и том же проходе вместе – MadProgrammer

ответ

1

Это m1.render(handler.getGame().getGraphics()) является массово неправильным.

Рендеринг метеоров должно быть сделано в методе render и использовать тот же Graphics контекст, как и другие элементы, так что все они оказываются в том же проходе

getGraphics никогда не следует использовать, так как она обеспечивает ссылка на контекст Graphics вне нормального цикла окраски, что означает, что все, что на нем нарисовано, будет удалено на следующем цикле краски.

Если честно, я понятия не имею, что ваш метод «запуска» пытается достичь, но в основном , это свободный ход, который может излишне потреблять циклы процессора, убирая циклы с других частей вашей программы.

Ни при каких условиях в цикле выполнения это не должно быть sleep, чтобы предоставить время другим потокам (или процессам).

Ниже приведен пример, который пытается поддерживать цикл обновления постоянной скорости 60 тиков в секунду в зависимости от количества времени, которое должна была выполнить фактическая работа.

public void run() { 

    int fps = 60; 
    long nanosInSecond = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS); 
    long timePerTick = (long)(nanosInSecond/(double)fps); 

    //game loop 
    while (true) { 
     long now = System.nanoTime(); 

     try { 
      // This is simulating the update and rendering process 
      Thread.sleep(5); 
     } catch (InterruptedException ex) { 
     } 
     long delta = System.nanoTime() - now; 
     long timer = timePerTick - delta; 
     timer = TimeUnit.MILLISECONDS.convert(timer, TimeUnit.NANOSECONDS); 
     if (timer > 0) { 
      try { 
       System.out.println("sleep for " + timer + " milliseconds"); 
       Thread.sleep(timer); 
      } catch (InterruptedException ex) { 
      } 
     } 
    } 

} 
+0

ok, теперь я использую тот же контекст графики в методе рендеринга, и метеоры больше не мерцают, но игра движется очень медленно, потому что мне нужно отобразить массив метеоров. что может решить эту проблему? –

+0

Обычно вы должны использовать переменную задержку между обновлениями для поддержания постоянной частоты кадров, поэтому, если вам нужно 60 кадров в секунду, вам необходимо обновить и отобразить кадр каждые 16 мс, но если фаза обновления/визуализации занимает 10 мс, вам нужно только «спать» 6 мс. Так как вы не предоставили код «игрового цикла», который на самом деле это делает, трудно сказать, что вы должны делать – MadProgrammer

+0

Букет из фрагментов кода контекста не очень полезен, возможно, подумайте о предоставлении [runnable example] (https : //stackoverflow.com/help/mcve), который демонстрирует вашу проблему. Это не дамп кода, а пример того, что вы делаете, что подчеркивает проблему, с которой вы сталкиваетесь. Это приведет к меньшему путанице и лучшим ответам. – MadProgrammer