Movatterモバイル変換


[0]ホーム

URL:


Saltar al contenido principal
Patrones de Diseño Java

    Game Loop

    BehavioralGame programmingAlrededor de 3 min

    En esta página

    Propósito

    Un bucle de juego se ejecuta continuamente durante la partida. En cada vuelta del bucle, procesa las entradas del usuario sin bloquearse, actualiza el estado del juego y lo renderiza. Realiza un seguimiento del paso del tiempo para controlar el ritmo de juego.

    Este patrón desvincula la progresión del tiempo de juego de la entrada del usuario y de la velocidad del procesador.

    Aplicabilidad

    Este patrón se utiliza en todos los motores de juego.

    Explicación

    Ejemplo del mundo real

    El bucle de juego es el proceso principal de todos los hilos de renderizado del juego. Está presente en todos los juegos modernos. Controla el proceso de entrada, la actualización del estado interno, el renderizado, la IA y todos los demás procesos.

    En pocas palabras

    El patrón de bucle de juego garantiza que el tiempo de juego progrese a la misma velocidad en todas las configuraciones de hardware diferentes.

    Wikipedia dice

    El componente central de cualquier juego, desde el punto de vista de la programación, es el bucle de juego. El bucle de juego permite que el juego se ejecute sin problemas, independientemente de la entrada de un usuario, o la falta de ella.

    Ejemplo programático

    Empecemos con algo sencillo. Aquí está la claseBullet. Las balas se moverán en nuestro juego. Para propósitos de demostración es suficiente que tenga una posición unidimensional.

    public class Bullet {  private float position;  public Bullet() {    position= 0.0f;  }  public float getPosition() {    return position;  }  public void setPosition(float position) {    this.position = position;  }}

    ElGameController es el responsable de mover los objetos del juego, incluida la mencionada bala.

    public class GameController {  protected final Bullet bullet;  public GameController() {    bullet= new Bullet();  }  public void moveBullet(float offset) {    var currentPosition = bullet.getPosition();    bullet.setPosition(currentPosition+ offset);  }  public float getBulletPosition() {    return bullet.getPosition();  }}

    Ahora introducimos el bucle de juego. O en realidad en esta demo tenemos 3 bucles de juego diferentes. Veamos primero la clase baseGameLoop.

    public enum GameStatus {  RUNNING, STOPPED}public abstract class GameLoop {  protected final Logger logger= LoggerFactory.getLogger(this.getClass());  protected volatile GameStatus status;  protected GameController controller;  private Thread gameThread;  public GameLoop() {    controller= new GameController();    status= GameStatus.STOPPED;  }  public void run() {    status= GameStatus.RUNNING;    gameThread= new Thread(this::processGameLoop);    gameThread.start();  }  public void stop() {    status= GameStatus.STOPPED;  }  public boolean isGameRunning() {    return status== GameStatus.RUNNING;  }  protected void processInput() {    try {      var lag = new Random().nextInt(200)+ 50;      Thread.sleep(lag);    }catch (InterruptedException e) {      logger.error(e.getMessage());    }  }  protected void render() {    var position = controller.getBulletPosition();    logger.info("Current bullet position: " + position);  }  protected abstract void processGameLoop();}

    Aquí está la primera implementación del bucle de juego,FrameBasedGameLoop:

    public class FrameBasedGameLoop extends GameLoop {  @Override  protected void processGameLoop() {    while (isGameRunning()) {      processInput();      update();      render();    }  }  protected void update() {    controller.moveBullet(0.5f);  }}

    Por último, mostramos todos los bucles del juego en acción.

        try {      LOGGER.info("Start frame-based game loop:");      var frameBasedGameLoop= new FrameBasedGameLoop();      frameBasedGameLoop.run();      Thread.sleep(GAME_LOOP_DURATION_TIME);      frameBasedGameLoop.stop();      LOGGER.info("Stop frame-based game loop.");      LOGGER.info("Start variable-step game loop:");      var variableStepGameLoop= new VariableStepGameLoop();      variableStepGameLoop.run();      Thread.sleep(GAME_LOOP_DURATION_TIME);      variableStepGameLoop.stop();      LOGGER.info("Stop variable-step game loop.");      LOGGER.info("Start fixed-step game loop:");      var fixedStepGameLoop= new FixedStepGameLoop();      fixedStepGameLoop.run();      Thread.sleep(GAME_LOOP_DURATION_TIME);      fixedStepGameLoop.stop();      LOGGER.info("Stop variable-step game loop.");    }catch (InterruptedException e) {      LOGGER.error(e.getMessage());    }

    Salida del programa:

    Start frame-based game loop:Current bullet position: 0.5Current bullet position: 1.0Current bullet position: 1.5Current bullet position: 2.0Current bullet position: 2.5Current bullet position: 3.0Current bullet position: 3.5Current bullet position: 4.0Current bullet position: 4.5Current bullet position: 5.0Current bullet position: 5.5Current bullet position: 6.0Stop frame-based game loop.Start variable-step game loop:Current bullet position: 6.5Current bullet position: 0.038Current bullet position: 0.084Current bullet position: 0.145Current bullet position: 0.1805Current bullet position: 0.28Current bullet position: 0.32Current bullet position: 0.42549998Current bullet position: 0.52849996Current bullet position: 0.57799995Current bullet position: 0.63199997Current bullet position: 0.672Current bullet position: 0.778Current bullet position: 0.848Current bullet position: 0.8955Current bullet position: 0.9635Stop variable-step game loop.Start fixed-step game loop:Current bullet position: 0.0Current bullet position: 1.086Current bullet position: 0.059999995Current bullet position: 0.12999998Current bullet position: 0.24000004Current bullet position: 0.33999994Current bullet position: 0.36999992Current bullet position: 0.43999985Current bullet position: 0.5399998Current bullet position: 0.65999967Current bullet position: 0.68999964Current bullet position: 0.7299996Current bullet position: 0.79999954Current bullet position: 0.89999944Current bullet position: 0.98999935Stop variable-step game loop.

    Diagrama de clases

    alt text
    Game Loop pattern class diagram

    Créditos


    [8]ページ先頭

    ©2009-2025 Movatter.jp