Java:同时移动对象

时间:2015-09-07 15:56:09

标签: java arrays multithreading object

如果我的代码有点原始,我很抱歉,我还是编程的新手。

我目前正在开发小型Java游戏,我需要让对象从右边缘向左滚动。

然后左边的玩家需要抓住物体,用鼠标或键盘上下滚动。

我遇到了让对象同时移动的问题,我可以让玩家在没有对象滚动时完美移动。但是当对象开始移动时,我有问题在哪里为玩家实现move()函数,以便它随着输入不断移动,而不依赖于向左滚动的对象。

目前我正试图在三个地方更新玩家的动作,如果没有相对于scollers移动玩家,则无法正常工作。 在游戏循环中:

public void play()
{
    while (!isGameOver())
    { 
        StdDraw.clear(StdDraw.BLACK);   
        grid.moveAll();
        grid.draw(0, 10);
        StdDraw.setPenColor(StdDraw.WHITE);
        StdDraw.text(100, 5, "Score: " + game.getScore());
        //Grid.U.move(Grid.playerR, Grid.playerC);
        StdDraw.show(20);
        //Grid.U.move(Grid.playerR, Grid.playerC);
        if (msElapsed % 300 == 0)
        {
            grid.populateRightEdge();
        }
        msElapsed += 20;
    }
}

在网格文件中,当告诉绘制对象G(其中一个滚动条)时:

public void draw(int atX, int atY) {

    for (int r = 0; r < num_Cols; r++) {
        for (int c = 0; c < num_Rows; c++) {
            //System.out.println("test1");
            if (grid[r][c] == U) {
                U.draw(c, r, grid_CellSize);
            }    if (grid[r][c] == A) {
                A.draw(c, r, grid_CellSize);;
            } if (grid[r][c] == G) {
                //Grid.U.move(Grid.playerR, Grid.playerC);
                G.draw(c, r, grid_CellSize);
            }
        }
    }

在移动对象G的类中:

  public Location move(int r, int c) {
 //Grid.U.move(Grid.playerR, Grid.playerC);
 Grid.grid[r-1][c] = Grid.grid[r][c];
 Grid.grid[r][c] = null;
//Grid.U.move(Grid.playerR, Grid.playerC);
 try {
    TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
return null;

} }

评论文本显示了阅读播放器运动的命令。 我需要一种方法来做到这一点,而不依赖于滚动器,我可以在我的代码中实现其他什么方法来做到这一点?

编辑:将代码移动到thread.sleep函数中后,随着滚动对象的增加,程序变慢,滚动的对象越多,滚动的速度就越慢。我该如何防止这种情况?

1 个答案:

答案 0 :(得分:1)

查看here了解更多/更不完整的示例。

说明:

首先,使用OOP和继承,比如,您的所有可处理实体必须具有(并继承)某些void process()方法和可渲染 - void render()方法。像网格一样:

class Grid {

  int w;
  int h;

  public Entity[][] cells;

  public Grid(int w, int h) {
    this.w = w;
    this.h = h;
    cells = new Entity[h][w];
  }

  public void process(long timemillis) {
    // here you can process grid

    // like, change some tiles, progress animations, etc
  }

  public void render(long timemillis) {
    // here you can draw grid
  }

}

此外,玩家和G实体遵循相同的规则:

class Entity {

  public void process(long timemillis) {

  }

  public void render(long timemillis) {

  }

}

因此:

class G extends Entity {

  // override parent process() method
  @Override
  public void process(long timemillis) {
    moveLeft(speed); // we should move left by amount, specified by "speed" 
  }

  @Override
  public void render(long timemillis) {
    // here goes rendering code for G entities
  }
}

class Enemy extends Entity {

  @Override
  public void render(long timemillis) {
    // here goes rendering code for Enemy entities
  }
}

class Bonus extends Entity {

  @Override
  public void render(long timemillis) {
    // here goes rendering code for Bonus entities
  }
}

class Player extends G {

  // override processing method if needed...
  @Override
  public void process(long timemillis) {
  }

  @Override
  public void render(long timemillis) {
    // here goes rendering code for player
  }
}

为什么这样?因为现在你可以这样做:

class Game {

  Grid grid;
  ArrayList<Entity> entities;
  long lastProcess;

  public Game() {
    grid = new Grid(30, 20);
  }

  public void newGame() {
    lastProcess = 0;
    entities = new ArrayList<>();
  }

  public void render(long timemillis) {
    grid.render(timemillis);

    for (Entity entity : entities)
      entity.render(timemillis);
  }

  public void process(long timemillis) {
    grid.process(timemillis); // process grid (like, some animation)

    for (Entity entity : entities) // process entities
      entity.process(timemillis);

    if (timemillis - lastProcess > 300) { // each 300 msec ()
      lastProcess = timemillis;

      Entity spawn;

      // choose and spawn some random object
      switch (((int)(Math.random() * 10)) % 4) {
      case 0: // spawn G
        spawn = new G(this); break;
      case 1: // spawn Enemy
        spawn = new Enemy(this); break;
      case 2: // spawn Bonus
        spawn = new Bonus(this); break;
      case 3: // spawn Secret
        spawn = new Secret(this); break;
      }

      // spawn it at right grid edge (grid.w - 1) at random y position
      spawn.moveTo(grid.w - 1, (int)(Math.random() * 9999) % grid.h);
      entities.add(spawn);
    }
  }

}

为了使处理/呈现异步,请使用线程(Thread类):

public class Launcher extends Application {

  Thread gameThread;

  int renderFPS = 30; // 

  int processPPS = 10;
  // five processings per second (around 1000 / 10 = 100 msec between each)

  boolean running;

  Game game;

  public static void main(String[] args) {
    // here goes the initialization
    Launcher launcher = new Launcher();
    launcher.launch();
  }

  public void launch() {
    running = false;

    // instantiating game object
    game = new Game();

    // creating thread
    gameThread = new Thread(new Runnable() {

      @Override
      public void run() {
        // this code will be executed in thread

        running = true;
        // here goes the rendering/processing "meat";
        long lastIteration = System.currentTimeMillis();
        long lastRender = lastIteration;
        long lastProcess = lastIteration;

        long msecPerRender = 1000 / renderFPS;
        long msecPerProcess = 1000 / processPPS;

        // main game loop
        while (running) {
          long now = System.currentTimeMillis();

          // should we draw next frame?
          long delta = now - lastRender;
          if (delta >= msecPerRender) {
            lastRender = now - (delta - msecPerRender);
            game.render(lastRender);
          }

          // is it time for processing next game iteration?
          delta = now - lastProcess;
          if (delta >= msecPerProcess) {
            lastProcess = now - (delta - msecPerProcess);
            game.process(lastProcess);
          }
        }
      }
    });

    // start the thread
    gameThread.start();

    // in order to keep app running, we should wait for thread execution finished
    try {
      gameThread.join();
    } catch (InterruptedException ex) {
    }
  }

  // to stop the application execution
  public void stop() {
    running = false;
  }

  // here you can move yours player
  public void movePlayer() {
    boolean moveUp = true; // calc direction
    if (moveUp)
      game.player.moveVertically(1);
    else
      game.player.moveVertically(-1);
  }

}

注意:为简单起见,pastebin上的代码使用swing库。