Rust言語でコパイロットと作るゲームプログラミング・シューティングゲーム編2 No-R007


** PR ** 目がかすむ、ぼやける。目の悩み解消解消に。

                         

 とうとう来ました。コンソール画面におけるシューティングゲーム。

コパイロット君に作ってもらいますが、うまくいくでしょうか。とても楽しみです。

まずは。プロンプトから。

No-R006で提案されたゲームの2番目案を作ってもらうことにしました。

自分

自分 が送信しました:

アイデア2: コンソールベースのシューティングゲームのプログラムを作ってください。

どのような回答でしょうか。

Copilot

Copilot が送信しました:

コンソールベースのシューティングゲームを作成しましょう。ここでは、プレイヤーが左右に移動し、上から降ってくる敵を撃つシンプルなシューティングゲームを作成します。以下のコードを試してみてください:

コパイロットの提案はなかなかに楽しそうです。そしてソースコードが提示されました。

Rust

use std::io::{self, Write};
use std::thread;
use std::time::Duration;
use rand::Rng;

const WIDTH: usize = 10;
const HEIGHT: usize = 10;

fn main() {
let mut player_pos = WIDTH / 2;
let mut enemy_pos = (0, rand::thread_rng().gen_range(0..WIDTH));
let mut bullets: Vec<(usize, usize)> = Vec::new();
let mut score = 0;

loop {
    // 画面をクリア
    print!("\x1B[2J\x1B[1;1H");

    // 敵の位置を更新
    enemy_pos.0 += 1;
    if enemy_pos.0 >= HEIGHT {
        enemy_pos = (0, rand::thread_rng().gen_range(0..WIDTH));
    }

    // 弾の位置を更新
    bullets.retain(|&(y, x)| y > 0);
    for bullet in &mut bullets {
        bullet.0 -= 1;
    }

    // 弾が敵に当たったかチェック
    if bullets.iter().any(|&bullet| bullet == enemy_pos) {
        score += 1;
        enemy_pos = (0, rand::thread_rng().gen_range(0..WIDTH));
        bullets.retain(|&bullet| bullet != enemy_pos);
    }

    // 画面を描画
    for y in 0..HEIGHT {
        for x in 0..WIDTH {
            if (y, x) == (HEIGHT - 1, player_pos) {
                print!("P");
            } else if (y, x) == enemy_pos {
                print!("E");
            } else if bullets.contains(&(y, x)) {
                print!("|");
            } else {
                print!(".");
            }
        }
        println!();
    }

    println!("Score: {}", score);

    // プレイヤーの入力を処理
    let mut input = String::new();
    io::stdin().read_line(&mut input).expect("入力の読み取りに失敗しました");
    match input.trim() {
        "a" => {
            if player_pos > 0 {
                player_pos -= 1;
            }
        }
        "d" => {
            if player_pos < WIDTH - 1 {
                player_pos += 1;
            }
        }
        " " => {
            bullets.push((HEIGHT - 2, player_pos));
        }
        "q" => break,
        _ => {}
    }

    // 少し待つ
    thread::sleep(Duration::from_millis(200));
}

}

コンパイルしてみます。

まずはビジュアルスタジオコードのターミナルでプロジェクト作成します。

「cargo new 任意projec名」のコマンド実行により

作業フォルダ+ソースコード(雛形)が作られます。

ここでワークスペースに作成したフォルダを追加します。

参考

ワークスペースを確認しよう

ワークスペースに複数のプロジェクトがあっても問題ないようなのでそのまま進めます。ワークスペース単位で作成したい場合は新規でワークスペースを作成してください。

このコードでは、randクレートを使用してランダムな数字を生成していますので、事前にCargo.tomlに以下の依存関係を追加してください:

この[dependencies]セクションに、randクレートを追加します。以下のように編集してください:

rand = “0.8” ” style=”position: relative; display: block; border: 1px solid var(–cib-color-stroke-neutral-primary); border-radius: var(–cib-border-radius-large); clear: both; margin-block: 24px 12px;”>

Cargo.toml の変更

[package]
name = “my_game”
version = “0.1.0”
edition = “2021”

[dependencies]
rand = “0.8”

いつものように、main.rsをコパイロット君が提案してくれたソースコードを張り付けて書き換えます。

ここで、「実行とデバック」のプロジェクトを変更します。

三角形のアイコンは「実行とデバック」を押すと、矢印のプルダウンメニューから構成(sohtgun2)の追加を選択しワークスペースを変更しておきます。

矢印の三角アイコンをマウスで押して、「実行とデバック」をおこないます。

完了すると、設定が悪いのかターミナルに文字化けした文字列が表示されます。

無視して、いつもの通り、3行目と4行目の実行|デバックの実行をマウスでクリックして実行します。

ゲームらしいコンソール画面になっています ^^) _旦~~

ターミナル画面を確認すると、warning(警告)がでています。コパイロット君に修正コードを書いてもらいましょう。

Copilot

Copilot が送信しました:

警告を解消するために、未使用のインポートと変数を削除しましょう。以下の修正を行ったコードを試してみてください:

Rust

use std::io;

use std::thread;

use std::time::Duration;

use rand::Rng;

const WIDTH: usize = 10;

const HEIGHT: usize = 10;

fn main() {

    let mut player_pos = WIDTH / 2;

    let mut enemy_pos = (0, rand::thread_rng().gen_range(0..WIDTH));

    let mut bullets: Vec<(usize, usize)> = Vec::new();

    let mut score = 0;

    loop {

        // 画面をクリア

        print!(“\x1B[2J\x1B[1;1H”);

        // 敵の位置を更新

        enemy_pos.0 += 1;

        if enemy_pos.0 >= HEIGHT {

            enemy_pos = (0, rand::thread_rng().gen_range(0..WIDTH));

        }

        // 弾の位置を更新

        bullets.retain(|&(y, _)| y > 0);

        for bullet in &mut bullets {

            bullet.0 -= 1;

        }

        // 弾が敵に当たったかチェック

        if bullets.iter().any(|&bullet| bullet == enemy_pos) {

            score += 1;

            enemy_pos = (0, rand::thread_rng().gen_range(0..WIDTH));

            bullets.retain(|&bullet| bullet != enemy_pos);

        }

        // 画面を描画

        for y in 0..HEIGHT {

            for x in 0..WIDTH {

                if (y, x) == (HEIGHT – 1, player_pos) {

                    print!(“P”);

                } else if (y, x) == enemy_pos {

                    print!(“E”);

                } else if bullets.contains(&(y, x)) {

                    print!(“|”);

                } else {

                    print!(“.”);

                }

            }

            println!();

        }

        println!(“Score: {}”, score);

        // プレイヤーの入力を処理

        let mut input = String::new();

        io::stdin().read_line(&mut input).expect(“入力の読み取りに失敗しました”);

        match input.trim() {

            “a” => {

                if player_pos > 0 {

                    player_pos -= 1;

                }

            }

            “d” => {

                if player_pos < WIDTH – 1 {

                    player_pos += 1;

                }

            }

            ” ” => {

                bullets.push((HEIGHT – 2, player_pos));

            }

            “q” => break,

            _ => {}

        }

        // 少し待つ

        thread::sleep(Duration::from_millis(200));

    }

}

うまく成功したようです。遊び方は下記の通り。

ゲームの操作方法

  • aキー: プレイヤーを左に移動
  • dキー: プレイヤーを右に移動
  • スペースキー: 弾を発射
  • qキー: ゲームを終了

ゲームの流れ

  1. プレイヤーは画面下部に位置し、左右に移動できます。
  2. 敵は画面上部からランダムな位置に出現し、下に向かって移動します。
  3. プレイヤーは弾を発射して敵を撃ちます。
  4. 敵に弾が当たるとスコアが増え、敵は再び上部から出現します。
  5. プレイヤーが敵を撃ち続けてスコアを稼ぎます。

ところが、ゲームが動きません???

もう一度、コパイロットさんに尋ねます。

自分

自分 が送信しました:

動きません

……….

………E

……….

……….

……….

……….

……….

……….

……….

…..P….

Score: 0

adadad

左右に動かすキー ”A”や”D”を押しますが、変化なし。スペースキーの発射もできません。

そこでもう一度、コパイロット君にターミナルの文字をコピペします。

Copilot

Copilot が送信しました:

ゲームが正しく動作しないようですね。いくつかの修正を試してみましょう。まず、プレイヤーの入力を非同期に処理することで、ゲームの動きをスムーズにすることができます。また、敵の動きや弾の発射を改善します。

以下のコードを試してみてください:

言われた様に、ソースコードのコピペ。

—————————————————————————————————————

//// PR ///

未経験からプロを目指せるオンラインプログラミングスクール【忍者CODE】

取扱いコース が豊富! 無料体験コースあります!

・Web制作&デザインコース

・Web制作コース

・Webデザインコース

・動画編集コース

・Pythonコース

・Javaコース

・Rubyコース

・Shopifyコース

————————————————————————————————————–

過去記事は下記を参照ください。2013年からミリタリー同人活動を行っています。

サイトマップ | ミリタリーグッズ工房「猫・工・艦」 (necokoucan.com)

【ブログ記事一覧】 | ミリタリーグッズ工房「猫・工・艦」 (necokoucan.com)

ミリタリーランキング
ブログランキング・にほんブログ村へにほんブログ村
広告

BASEオリジナルグッズ

PR VTuberサプーが教える! Python 初心者のコード/プロのコード

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です