プレイヤー中心視点の2Dゲーム

前回の2Dゲームプログラムの考え方を拡張し、自分のキャラクターを中心として、ゲームのワールドを移動できるようなプログラムを考えてみましょう。 前回と同様にJSONを利用してゲームの状態を送受信します。 プレイヤーは、矢印キーによってキャラクターを上下左右に移動させることができるようにします。 そのキー入力をクライアントからサーバーに送ります。 サーバープログラムは、クライアントからの入力を受け取り、各プレイヤーごとに、現在の座標とその周囲に存在する他プレイヤーの情報をクライアントに送ります。

通信方向 送信内容
クライアント→サーバー プレイヤーの操作(上下左右への移動) {"direction": "up"}
クライアント←サーバー 現在のゲームの状態(表示座標と周囲のプレイヤーの座標) {"players": [{"id": 2, "x": 100, "y": 200}]}

サーバープログラム

import processing.net.*;

int screenWidth = 400;
int screenHeight = 400;
int gameWidth = 2000;
int gameHeight = 2000;

class Player {
  int id;
  float cx, cy;

  Player(int id) {
    this.id = id;
    this.cx = random(gameWidth);
    this.cy = random(gameHeight);
  }

  void move(float dx, float dy) {
    this.cx += dx;
    this.cy += dy;
    if (this.cx > gameWidth) {
      this.cx -= gameWidth;
    }
    if (this.cx < 0) {
      this.cx += gameWidth;
    }
    if (this.cy > gameHeight) {
      this.cy -= gameHeight;
    }
    if (this.cy < 0) {
      this.cy += gameHeight;
    }
  }

  JSONObject toJSON() {
    JSONObject item = new JSONObject();
    item.setInt("id", this.id);
    item.setFloat("x", this.cx);
    item.setFloat("y", this.cy);
    return item;
  }
}

Server server;
int idOffset = 0;
HashMap<Client, Player> players = new HashMap();


void setup() {
  server = new Server(this, 5204);
}

void draw() {
  for (Client client : players.keySet()) {
    Player player = players.get(client);
    JSONArray playerArray = new JSONArray();
    for (Player p : players.values()) {
      if (player.cx - screenWidth / 2 <= p.cx
        && p.cx <= player.cx + screenWidth / 2
        && player.cy - screenHeight / 2 <= p.cy
        && p.cy <= player.cy + screenHeight / 2) {
        playerArray.append(p.toJSON());
      }
    }
    JSONObject message = new JSONObject();
    message.setJSONArray("players", playerArray);
    message.setFloat("cx", player.cx);
    message.setFloat("cy", player.cy);
    client.write(message.toString());
    client.write('\0');
  }
}

void clientEvent(Client client) {
  float d = 10;
  String payload = client.readStringUntil('\0');
  if (payload != null) {
    JSONObject message = parseJSONObject(payload.substring(0, payload.length() - 1));
    Player player = players.get(client);
    switch (message.getString("direction")) {
    case "left":
      player.move(-d, 0);
      break;
    case "right":
      player.move(d, 0);
      break;
    case "up":
      player.move(0, -d);
      break;
    case "down":
      player.move(0, d);
      break;
    }
  }
}

void serverEvent(Server server, Client client) {
  Player player = new Player(idOffset++);
  players.put(client, player);
}

void disconnectEvent(Client client) {
  players.remove(client);
}

クライアントプログラム

import processing.net.*;

int playerSize = 20;
int gameWidth = 2000;
int gameHeight = 2000;

class Player {
  int id;
  float cx, cy, angle;

  Player(int id, float cx, float cy, float angle) {
    this.id = id;
    this.cx = cx;
    this.cy = cy;
    this.angle = angle;
  }

  void draw() {
  }
}

Client client;
JSONObject status = new JSONObject();

void setup() {
  size(400, 400);
  client = new Client(this, "127.0.0.1", 5204);
}

void draw() {
  background(255);
  if (status.getJSONArray("players") == null) {
    return;
  }
  synchronized(status) {
    pushMatrix();
    float cx = status.getFloat("cx");
    float cy = status.getFloat("cy");
    translate(-cx + width / 2, -cy + height / 2);
    drawField();
    JSONArray players = status.getJSONArray("players");
    for (int i = 0; i < players.size(); ++i) {
      JSONObject player = players.getJSONObject(i);
      int playerId = player.getInt("id");
      float playerX = player.getFloat("x");
      float playerY = player.getFloat("y");
      stroke(0);
      fill(255);
      ellipse(playerX, playerY, playerSize, playerSize);
      fill(0);
      textAlign(CENTER, CENTER);
      text(playerId, playerX, playerY);
    }
    popMatrix();
  }
}

void drawField() {
  int size = 100;
  int n = gameWidth / size;
  stroke(0);
  for (int i = 0; i <= n; ++i) {
    line(0, size * i, gameWidth, size * i);
  }
  for (int j = 0; j <= n; ++j) {
    line(size * j, 0, size * j, gameHeight);
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      fill(0);
      textAlign(CENTER, CENTER);
      text(i * n + j, size * j + size / 2, size * i + size / 2);
    }
  }
}

void keyPressed() {
  if (key == CODED) {
    JSONObject message = new JSONObject();
    switch (keyCode) {
    case RIGHT:
      message.setString("direction", "right");
      break;
    case LEFT:
      message.setString("direction", "left");
      break;
    case UP:
      message.setString("direction", "up");
      break;
    case DOWN:
      message.setString("direction", "down");
      break;
    default:
      return;
    }
    client.write(message.toString());
    client.write('\0');
  }
}

void clientEvent(Client client) {
  String payload = client.readStringUntil('\0');
  if (payload != null) {
    synchronized(status) {
      status = parseJSONObject(payload.substring(0, payload.length() - 1));
    }
  }
}

results matching ""

    No results matching ""