セルティの開発ログ

趣味でゲーム開発にハマってます!主にCocos Creatorを使った様々なゲームジャンルに挑戦して形にしたものを投稿します!

Pong GameをCocos Creatorで作ってみた! Part3: ボールを反射させよう! 【Cocos Creator】

◆こちらでは簡単なPong Gameの手順や詳細な設定を可能な限りわかりやすくご紹介

しております。

◆今回はPart3となりますので、Part2は下記のページへ飛んでご確認ください。

celty-blog.hatenablog.com

◆またページ内で見づらく分からないことがございましたら、気軽にコメントでご連絡

をください。

使用環境

ボールを反射処理を実装する

 今回はボールを動かし、画面の壁に当たった際には『光の屈折』の要領で反射させる。実装は以下の通りです。

Cocos Creatorでの操作

  • 前回パートで実装した四隅の壁の内、『wallTop』, 『wallBottom』の『BoxCollider->Tag = 1』にします

  • 『wallLeft』の『BoxCollider->Tag = 2』とし、『wallRight』の『BoxCollider->Tag = 3』とします

  • 『paddle』の『BoxCollider->Tag = 0』とします。 f:id:celty_blog:20210320142821p:plain  上の画像は参考例です。

  • 『Script』フォルダーを右クリックし、『Create->TypeScript』で名前を『Ball』とする。 f:id:celty_blog:20210320133846p:plain

 終わったら『Ball』ノードを選択し、『Add Component->Add Component->Custom Component->Ball』を選択する。  『Ball』スクリプトをダブルクリックして、『VSCode』の作業に移る。

VSCodeでの操作

 ここからは下記のような処理を実装します。

  • 『ball』と各壁や『paddle』触れ始めた際の判定する関数『onCollisionEnter()』を実装する。 (この関数は『onLoad()』や『update(dt)』関数と同じくCocos Creator側で用意している関数なので、変えないようにしてください。)

  • 『onCollisionEnter()』関数には先程設定した『Tag』ごとに反射するようにする。

  • 『update(dt)』関数にはdt(前フレームからの経過時間)に応じて『ball』ノードを斜めに動くように実装する。

  • 詳しくはコードのコメントを参考にしつつ理解いただければと思います。

・Ball.ts

const {ccclass, property} = cc._decorator;

@ccclass
export default class Ball extends cc.Component {

    // プレイ関係の変数
    speed: number = 50; // ボールの動く速度
    x_direction: number = 1; // 横移動する変数
    y_direction: number = 1; // 縦移動する変数

    onCollisionEnter(other) {
        this.speed += 20;
        // 上か下の壁にぶつかった場合
        if(other.tag == 1) {
            this.y_direction *= -1;
            cc.log("Top&Bottom Hit");
        }
        // 左の壁にぶつかった場合
        if(other.tag == 2) {
            this.x_direction *= -1;
            cc.log("Left Hit");
        }
   // 右の壁にぶつかった場合
        if(other.tag == 3) {
            this.x_direction *= -1;
            cc.log("Right Hit");

        }
        // パドル(プレイヤー)がぶつかった場合
        if(other.tag == 0) {
            this.x_direction *= -1;
            cc.log("Player Hit");
        }
    }

    update (dt: number) {
        // 横移動と縦移動を同時に処理することで斜めに移動する
        // 横移動
        this.node.x += dt * this.speed * this.x_direction;
        // 縦移動
        this.node.y += dt * this.speed * this.y_direction;
    }
}

 ここまで書けましたら『command⌘ + P』で動作を確認してください。下の画像のように動いていれば問題ありません。

f:id:celty_blog:20210320150522p:plain

f:id:celty_blog:20210320150533p:plain

またcc.log("message")を自分の動作を確認したい関数、処理の下に入れるとデバッガーを確認する際にわかりやすくなります。

f:id:celty_blog:20210320150556p:plain

ボールをいろんな位置に表示させよう![応用]

 ここからは少し複雑な要素を追加させるため応用としてボールの出現する位置をランダムにして表示させる!

Cocos Creatorでの操作

 

空のノードを用意する/『ball』をプレハブ化する

 『Canvas』を選択して右クリックから『Create->Create Empty Node』と選択して名前を『root』とする。

f:id:celty_blog:20210320153959p:plain

   次に『ball』ノードをクリックしたままドラッグし、Part1で作った『Prefab』フォルダーへドロップすると『ball』プレハブが新たに作成される。

f:id:celty_blog:20210320154534p:plain

 ここまで出来たら、『Node』にある『ball』はクリックしてから『command⌘ + delete(✖︎)』で削除する。

『Game』スクリプトを作る

  『Script』フォルダーを右クリックし、『Create->TypeScript』で名前を『Game』とする。

f:id:celty_blog:20210320155337p:plain

 終わったら『Game』ノードを選択し、『Add Component->Add Component->Custom Component->Game』を選択する。

 『Game』スクリプトをダブルクリックして、『VSCode』の作業に移る。

VSCodeでの操作

 『Game』スクリプトでは以下のものを実装する。

  • 『Game』スクリプトはゲーム画面全体に関わる設定を管理するものにする。そのためこれまで作ってきたノードやプレハブを格納できるように書き込んでいく。

  • 新たに『getRandomPosition()』関数と『createBall()』関数の二つを作る。これらの関数にランダムにボールを出現させるコードや他のスクリプトからの情報を取得し、反映させる。

  • 詳しくはコードの横につけるコメント等を確認ください。

・Game.ts

const {ccclass, property} = cc._decorator;

@ccclass
export default class Game extends cc.Component {

    // Cocos Creator側で表示されるプロパティ
    @property(cc.Node)
    player: cc.Node = null; // 『paddle』を格納する
    @property(cc.Node)
    root: cc.Node = null; // 『root』を格納する
    @property(cc.Prefab)
    ballPrefab: cc.Prefab = null; // 『ball』プレハブを格納する

    // 無作為にたまを出現させる
    randomRange: cc.Vec3 = cc.v3(0, 0, 0); // 無作為に出現する範囲
    getRandomPosition() {
        // ボールを出現される範囲はx, yの値に対してMath.random() - 0.5をかけて、ランダムに表示させる。
        return cc.v3(Math.random() - 0.5 * this.randomRange.x, Math.random() - 0.5 * this.randomRange.y, 0);
    }
    
    // ボールを作り出す関数
    current_ball: cc.Node = null; // ボールを出現させるノード変数
    createBall() {
        this.current_ball = cc.instantiate(this.ballPrefab); // ボールプレハブノードを作り出す
        this.current_ball.parent = this.root; // 出現させる親ノードは『root』にする
        let movementComponent = this.current_ball.getComponent("Ball");
        movementComponent.init(this); // 生成した『ball』プレハブの『Ball』コンポーネントに『Game』コンポーネントの実体を渡す。
        movementComponent.speed = cc.v3(250, 500, 0).x;
        movementComponent.x_direction = Math.random() - 0.5; // 方向はランダムに
        movementComponent.y_direction = Math.random() - 0.5; // 方向はランダムに
        this.current_ball.position = this.getRandomPosition(); // ボールの位置はgetRandomPosition()関数の戻り値(return以降)に設定する。
    }

    onLoad() {
        this.randomRange = cc.v3(300, 200, 0); // 初期位置
        this.createBall(); // ボールを作り出す関数
    }

    // update(dt) {}


 このコードの多くは『Claus Witt』から参考にして書かせていただいたので是非見ていただければと思います。  ただし、Cocos Creatorのバージョンが古いため、一部使えない関数やJavaScriptでしか使えない書き方もされているので注意が必要です。

www.clauswitt.com

・Ball.ts

// Game.tsをインポートする

import Game from "./Game";

const {ccclass, property} = cc._decorator;

@ccclass
export default class Ball extends cc.Component {

    // インポートしたスクリプト
    game: Game = null;
    init(game:Game) {
        this.game = game;
    }

    // 省略 //

}

 上のコードは『Game』スクリプトのコードにある『 movementComponent.init(this);』で 『Ball』スクリプトで定義している変数を使うために『Ball』スクリプト側に『Game』スクリプトをインポートする。これは次のPartでも重要になる技法なので、理解するには時間がかかると思いますが、新たに書き込んでください。

   ここまで書き終えたら『Game』スクリプトに『paddle』や『ball』『root』ノードをドラッグ&ドロップし、『command⌘ + P』で動作を確認してください。画像では挙動を確認できないので、ここでは貼っていませんが先程とは全く違う位置で出現したら成功です!

   それでは、今回はここまでになります。お疲れ様でした。

おわりに

 今回は前回よりも投稿に時間がかかってしまいました…。申し訳ございません。またGIF画像も作れずすみません…。あった方が挙動も確認しやすいのですが、入れられませんでした…。

 完全に独学で進めているので、[応用]の部分はどのように動いているか現在勉強中ですが、自分で見様見真似で触ってみたらうまく動作したため不完全ではございますが掲載させていただきました。また独学で進めていく中で理解し、直して行けるところは修正していきますので今後ともよろしくお願いいたします。

 それではここまでお読みいただいた優しい方、ありがとうございました!次回もまたお越しください。