common.title

Docs
Quantum Circuit
TYTAN CLOUD

QUANTUM GAMING


Overview
Contact
Event
Project
Research

Terms of service (Web service)

Terms of service (Quantum and ML Cloud service)

Privacy policy


Sign in
Sign up
common.title

生成AIでソフトウェア開発してみよう。実際画面を動かし始めてみた。その2。

Yuichiro Minato

2024/01/17 07:17

前回は生成AIにゲームを作りたいと言って、作って少しずつ進めていましたが、いよいよ画面が出来上がってきています。では見てみましょう。

前回からの続きですが、Python Flaskは素養がありますので、macで開発するために下記のサーバーを立ち上げました。game.htmlを直接javascript実行するとCORSエラーが起きましたので、それを回避するためにローカルのウェブサーバーをflaskで立ち上げております。

from flask import Flask, render_template, jsonify

app = Flask(__name__)

@app.route('/')
def main():
  return render_template('game.html')

if __name__ == '__main__':
  app.run(debug=True, host='0.0.0.0', port=8888)

templatesの中にgame.htmlを入れまして、前回の生成AI大先生の言う通りに書いております。また、ちょっとスプライトシートというもの側からなったのですが、どうやらフレームを指定してキャラクターを動かせるようです。しかし使い方わからんので、playerのフレームの指定がエラーが出ましたので、frameを0から0にしたらキャラクターはアニメーションせずにマップを移動できました。

<!DOCTYPE html>
<html>
<head>
 <title>Phaser Game</title>
 <script src="https://cdn.jsdelivr.net/npm/phaser@3/dist/phaser.min.js"></script>
</head>
<body>
<script>
// ゲームの設定
var config = {
 type: Phaser.AUTO,
 width: 800,
 height: 600,
 physics: {
  default: 'arcade',
  arcade: {
   gravity: { y: 0 },
   debug: false
  }
 },
 scene: {
  preload: preload,
  create: create,
  update: update
 }
};

// ゲームのインスタンスを作成
var game = new Phaser.Game(config);
function preload() {
 // 画像アセットの読み込み
 this.load.image('background', 'static/village.png'); // 背景画像
 this.load.spritesheet('player', 'static/player.png', { frameWidth: 40, frameHeight: 45 }); // スプライトシート
}
function create() {
 // 背景の設定
 this.add.image(0, 0, 'background');
 // プレイヤーの設定
 player = this.physics.add.sprite(600, 600, 'player');
 // プレイヤーのアニメーション設定
 this.anims.create({
  key: 'left',
  frames: this.anims.generateFrameNumbers('player', { start: 0, end: 0 }),
  frameRate: 10,
  repeat: -1
 });
 this.anims.create({
  key: 'right',
  frames: this.anims.generateFrameNumbers('player', { start: 0, end: 0 }),
  frameRate: 10,
  repeat: -1
 });
 // キーボードのカーソルキーを入力として設定
 cursors = this.input.keyboard.createCursorKeys();
 // カメラの設定(プレイヤーを追従)
 this.cameras.main.startFollow(player);
}
function update() {
 // プレイヤーの動きの管理
 player.setVelocity(0);
 if (cursors.left.isDown) {
  player.setVelocityX(-160);
  player.anims.play('left', true);
 } else if (cursors.right.isDown) {
  player.setVelocityX(160);
  player.anims.play('right', true);
 }
 if (cursors.up.isDown) {
  player.setVelocityY(-160);
 } else if (cursors.down.isDown) {
  player.setVelocityY(160);
 }
}

</script>
</body>
</html>

ということで、上記は一部反映していますが、キャラクターデザインと背景デザインを頼みました。

Q.ドット絵で高さと幅3:2でキャラクターの絵を出して

もう生成AIなのでセーフかアウトか全くわかりませんがこれが出ました。切り抜きました。さらにpixlr editorで背景切り取りをします。さらにサイズを小さくしました。

まぁ、いいでしょう。次に、

Q.はば400px 高さ300pxでなんかRPGの村の背景画像を出して。

サイズを全く無視してすぐこれが出ました。著作権大丈夫かわかりませんが、1024*1024だったので、コードの方をちょっと触って直したところ。。。

なんかゲームっぽくできました。ここまで数分です。。。

どうやらこれをベースに村人とお話をするゲームはできそうです。

ここから何をしていいかわからないのでマネージャーに聞いてみます。

Q.ドット絵キャラクターと村の背景画像を用意して、phaserでキャラクターを動かすことができました。次に当たり判定とかキャラクターの動く範囲を制限とかはできるのですか?

はい、Phaserではキャラクターの当たり判定や動く範囲の制限を設定することが可能です。これらの機能はゲームプレイに不可欠な部分であり、特にRPGのようなゲームでは重要です。以下に、Phaserでの当たり判定と動く範囲の制限の基本的な方法を説明します。

当たり判定(Collision Detection)

Phaserには、オブジェクト間の当たり判定を簡単に実装できる機能があります。例えば、キャラクターと壁や障害物の間の当たり判定を設定することができます。

function create() {
  // キャラクターの作成
  player = this.physics.add.sprite(100, 100, 'player');

// 壁や障害物の作成
  var wall = this.physics.add.staticGroup();
  wall.create(200, 200, 'wall');

// キャラクターと壁の当たり判定
  this.physics.add.collider(player, wall);
}

このコードでは、`wall`という静的グループに壁のオブジェクトを追加し、`this.physics.add.collider`を使用して、`player`と`wall`の間の当たり判定を設定しています。

動く範囲の制限(Movement Restriction)

キャラクターの動く範囲を制限するには、キャラクターの位置を監視し、特定の境界内に保つ必要があります。`update`関数内でキャラクターの位置をチェックし、必要に応じて調整します。

function update() {
  // キャラクターの動きの管理
  // ...

// キャラクターの位置が特定の範囲を超えた場合に位置を調整
  player.x = Phaser.Math.Clamp(player.x, min_x, max_x);
  player.y = Phaser.Math.Clamp(player.y, min_y, max_y);
}

ここでは`Phaser.Math.Clamp`関数を使って、`player`の`x`と`y`座標が特定の範囲(`min_x`〜`max_x`、`min_y`〜`max_y`)内に収まるようにしています。

注意点

- 当たり判定を行う際、オブジェクトの物理的な特性(例えば、質量や反発係数)を考慮することが重要です。

- マップやレベルの設計によっては、より複雑な当たり判定や動きの制限が必要になる場合があります。Phaserはタイルマップとの統合もサポートしているので、タイルベースのゲームでの使用も検討できます。

ということで、動く範囲と当たり判定が取得できました。問題として動いてみると背景画像の範囲が狭すぎて村の端っこに来ると黒背景が見えてしまいます。ちょっとレタッチして背景画像の背景を広げてみてから動ける範囲を制限したいと思います。

ちょっと画面比率や背景の範囲を調整してスマホタイプにしてみました。

その上で動ける範囲を指定してみたいと思います。今は村を超えて枠外まで移動できてしまいます。言われた通り下記の範囲をちょっとずつ調べて入れてみたところ、村から飛び出ることはなくなりました。

// キャラクターの位置が特定の範囲を超えた場合に位置を調整
 min_x = -400
 max_x = 380
 min_y = -200
 max_y = 250

player.x = Phaser.Math.Clamp(player.x, min_x, max_x);
 player.y = Phaser.Math.Clamp(player.y, min_y, max_y);

ちょっと音楽がないので、音楽も作ってみます。生成AIで音楽が作れるようです。

Q.phaserでバックグラウンド音楽を流すにはどうしたらいいですか?mp3ファイルがあります。

Phaserでバックグラウンド音楽を流すには、まず音楽ファイル(例えばMP3ファイル)をゲームに読み込み、その後、ゲームの適切なタイミングで音楽を再生するように設定します。以下に基本的なステップとサンプルコードを示します。

ステップ1: 音楽ファイルの読み込み

`preload`関数内で、音楽ファイルをゲームに読み込みます。ファイルのパスは、実際に保存されている場所に応じて変更してください。

function preload() {
  // 他のアセットの読み込み...
   
  // 音楽ファイルの読み込み
  this.load.audio('backgroundMusic', 'path/to/your/music.mp3');
}

ステップ2: 音楽の再生

`create`関数内で、読み込んだ音楽ファイルを再生します。ここでは、音楽がループするように設定することもできます。

function create() {
  // ゲームのセットアップ...

// 音楽の再生
  var music = this.sound.add('backgroundMusic');
  music.play({
    loop: true
  });
}

生成AIで音楽を作る際には、歌詞なしで曲調を指定して入れました。"8bit game village peaceful" としました。

いい感じのファミコン音楽ができましたよ。

そして、さっき何気に設定した障害物が転がってました。確かに当たり判定があります。せっかくなので今回はこれらを複数使って村人を設定したいと思います。

続く。。。

生成AIでソフトウェア開発してみよう。マネージャーからエンジニアまで生成AIでやってみた。その1。

https://blueqat.com/yuichiro_minato2/d274be21-7a88-4152-abf1-a6a71b2825d0

生成AIでソフトウェア開発してみよう。実際画面を動かし始めてみた。その2。

https://blueqat.com/yuichiro_minato2/4c18109a-a51a-46b9-a62f-a26f4667eec3

生成AIでソフトウェア開発してみよう。村人とお話をしてみる。その3。

https://blueqat.com/yuichiro_minato2/f0e55640-bdb4-4931-9b80-5394c2edfd37

© 2025, blueqat Inc. All rights reserved