CocosCreatorでシューティングゲームを作る詳しい解説

CocosCreatorでシューティングゲームを作る詳しい解説

シーン設定

ゲームリソース

砲塔の回転

メカニズムは前のハンドル インスタンスの車と同じで、touchmove を使用してタッチ イベントをリッスンします。

  1. タッチ位置を取得
  2. signAngle メソッドを使用して、位置と cc.v2(1,0) 位置の角度差を調べます (負の符号を追加することを忘れないでください。反時計回りの比較は負で、反時計回りの角度の値は正です)。
  3. 求めた角度が最終的な角度です。

 オンロード(){
        //90 度に初期化します this.node.angle=90;
        this.node.on('touchstart',this.onTouchStart,this);
        this.node.on('touchmove',this.onTouchMove,this);
        this.node.on('touchend',this.onTouchEnd,this);
        this.node.on('touchconcel',this.onTouchConcel,this);
    }
   
    onTouchStart(e:cc.Event.EventTouch){
        //開始位置を取得します this.starPos=this.node.parent.convertToNodeSpace(e.getLocation());
        //銃口の初期角度を取得します。this.starAngle=this.node.angle;

    }
    onTouchEnd(e:cc.Event.EventTouch){

    }
    onTouchMove(e:cc.Event.EventTouch){
        //タッチポイントの現在の位置を取得します。let pos:cc.Vec2=this.node.parent.convertToNodeSpace(e.getLocation());

        //角度を取得します //角度は時計回りに負、反時計回りに正です let sweep_radian=pos.signAngle(this.starPos); //starPose p に対する pos の角度は、s に対する時計回りに正です let sweep_angle=sweep_radian*180/Math.PI; //角度をラジアンに変換します //砲塔が最終角度を指すようにします let angle=this.starAngle-sweep_angle;
      
        //角度を 45 〜 135 の間に制限します。if (angle<45) angle=45;
        角度>135の場合、角度=135;

        cc.log("銃口スイング: "+sweep_angle+"最終角度位置: "+angle);
        this.node.angle=角度;
    }

動的に生成された弾丸

  1. ノードcc.Nodeを生成し、コンポーネントaddComponent(cc.Sprite)を追加します。
  2. コンポーネントのプロパティと画像のspriteFrameに値を割り当てる
  3. コンポーネントを親ノードの下にマウントする
  4. 位置、角度などを設定します。
  5. 動きを制御するには、新しく作成したスクリプトをインポートし、動的に生成されたノードのコンポーネントに追加します。
 onTouchEnd(e:cc.Event.EventTouch){
        これを起動します。
    }
    タッチキャンセル(e:cc.Event.EventTouch){

    }

    火(){

        if(this.bulleteicon==null) を返します。
        bullet:cc.Node=new cc.Node(); とします。
        sprite:cc.Sprite=bullet.addComponent(cc.Sprite); とします。
        sprite.spriteFrame=this.bulleteicon;
        

        // 射撃システムノードにマウント bullet.parent=this.node.parent;

        //親ノードの相対位置を設定します。let ration=this.node.angle*Math.PI/180;
        direction=cc.v2(Math.cos(ration),Math.sin(ration)) とします。
        ノードの角度を指定します。
        r=100とします。
        bullet.setPosition(cc.v3(r*direction.x,r*direction.y,0));
       
        //追加のスクリプト コンポーネント let script=bullet.addComponent(Buletet);
         script.explodeImg=this.explodeImg;
         script.direction=方向;

    }
 始める () {
         this.schedule(this.onTimer,0.01);
    }

    オンタイマー(){
        y>300の場合
            this.unschedule(this.onTimer);
            これを爆発させる();
           
            戻る;
        }
        dx = this.direction.x * 5 とします。
        dy=this.direction.y*5 とします。
        y は dy を表します。
        this.node.x+=dx;
    }

    爆発()

        sp:cc.Sprite=this.getComponent(cc.Sprite); とします。
        sp.spriteFrame=this.explodeImg;
      
        //弾丸を縮小します this.node.scale=0.1;
        //爆発アニメーション効果イージングシステム let self=this;
        cc.tween(このノード)
            .to(0.5,{スケール:1,不透明度:0})
            .call(関数(){
                自己.afterExplode();
            })
            。始める();

            
    }

    afterExplode(){
        このノードを破棄します。
    }

このバグ:

  1. インポートされたクラス名はファイル名と異なります。ファイル名を変更してもコード内のクラス名は自動的に変更されないので、2回変更する必要があることに注意してください。
  2. setposition() メソッドを使用する場合、パラメータは cc.v3 のコンストラクタ内に記述されます。パラメータの位置に注意してください。

衝突計算

弾丸とターゲットの相対位置を計算し、射程距離以内であればターゲットに当たったと判断してヒット動作を行い、そうでない場合はターゲットに当たっていないと判断して不ヒット動作を行います。

スクリプトはターゲットノードを渡し、ターゲット属性を追加する必要がある。

   @property(cc.SpriteFrame)
    爆発画像: cc.SpriteFrame = null;
    
    方向: cc.Vec2 = null;

    ターゲット: cc.Node = null;
    オンロード() {

    }

    始める() {
        this.schedule(this.onTimer, 0.01);
    }

    オンタイマー() {
        (this.node.y > 350)の場合{
            if (this.isHit()) {
                //爆発効果を再生します this.explode();
                console.log("ターゲットをヒット");
            }
            それ以外 {
                console.log("ターゲット外");
                this.disMiss();
            }
            this.unschedule(this.onTimer);
            戻る;
        }
        dx = this.direction.x * 5 とします。
        dy = this.direction.y * 5 とします。
        this.node.y += dy;
        this.node.x += dx;
    }

    //ヒットしたかどうかを判定する isHit(): boolean {
        targetPos: cc.Vec2 = this.geWorldLocation(this.target); とします。
        selfPos: cc.Vec2 = this.geWorldLocation(this.node); とします。
        距離を Math.abs(targetPos.x - selfPos.x) とします。
        console.log("ターゲット x=" + targetPos.x + " 、箇条書き x=" + selfPos.x);

        (距離<50)の場合{
            true を返します。

        }
        それ以外 {
            false を返します。
        }

    }
    爆発() {

        sp: cc.Sprite = this.getComponent(cc.Sprite); とします。
        spriteFrame を this.explodeImg に追加します。

        //弾丸を縮小します this.node.scale = 0.1;
        // 爆発アニメーション効果イージングシステム let self = this;
        cc.tween(このノード)
            .to(0.5, { スケール: 1, 不透明度: 0 })
            .call(関数() {
                自己.disMiss();
            })
            。始める();


    }

    geWorldLocation(ノード: cc.Node): cc.Vec2 {
        pos = node.getPosition() とします。
        //これは node.parent であることに注意してください。メソッドの呼び出し元は、現在のノードの座標系である必要があります。 return node.parent.convertToWorldSpaceAR(pos);

    }

    却下する() {
        このノードを破棄します。
    }

このバグ:

ワールド座標を取得する際には、親ノードの座標系は呼び出されず、現在のノードの座標系が使用されるため、返される値は現在の座標系自体の値のままとなります。ワールド座標を変換するためのメソッド呼び出し元は、現在のノード (通常はその親ノード) の座標系であることに注意してください。 node.parent.convertToWorldSpaceAR(pos); を返します(アンカーポイントを原点として)

効果を高める

ターゲット ノードの下にスクリプトを追加して、動きを制御し、左右に移動し、弾が当たったときにテキスト プロンプト効果を追加します。

テキストのヒント:

 応援(){
        //ノードを作成してマウントします。let node: cc.Node = new cc.Node();
        node.parent = this.node.parent; // 両方とも同じレベルにあり、同じ親オブジェクトを持ちます let label: cc.Label = node.addComponent(cc.Label);
        label.string = "+10 ポイント";

        //位置、透明度などを設定します。node.setPosition(cc.v3(0, 250, 0));
        ノードの不透明度 = 200;
        ノードの色を新しいcc.Color(255, 0, 0);

        //アニメーション cc.tween(node)
            .to(0.5, {スケール: 1.5 })
            .to(0.2, { 不透明度: 0 })
            .call(関数() {
                ノードを破棄します。
            })
            。始める();

    }

ターゲットの動き

 更新 (dt) {
         速度を3とします。
         if(this.isLeft){
             速度=-速度;
         }
         this.node.x+=速度;
         if(this.isLeft&&this.node.x<-350){
             this.isLeft = false;
         }
         if(!this.isLeft&&this.node.x>350){
            this.isLeft が true である。
        }
    }

弾薬庫の表示を追加

  1. 弾丸画像を一括生成するための弾薬庫ノードを追加しました (位置はウィジェット コンポーネントを使用して設定できます)
  2. 箇条書きを減らすメソッドを追加し、箇条書き画像のアクティブ プロパティを設定することで箇条書きを減らします。
  3. 砲塔の射撃メソッドで弾丸を減らすメソッドを呼び出す

呼び出し方法は 2 つあります。1 つは砲塔スクリプト内で弾薬庫ノードを取得して呼び出す方法です。もう 1 つは、パブリック クラス (静的変数) を設定し、onLoad() メソッド内でノードを初期化して直接呼び出す方法です。後者を使用してください。

 @property(cc.SpriteFrame)
    箇条書きアイコン: cc.SpriteFrame = null;
    容量: 数 = 10;
    在庫数: 数値 = 10;


    オンロード() {

        スペース: number = this.node.width / this.capacity;
        (i = 0 とします; i < this.capacity; i++) {
            //画像を生成します。let bulleteNode: cc.Node = new cc.Node();
            bulleteSprite を追加します: cc.Sprite = bulleteNode.addComponent(cc.Sprite);
            bulletSprite.spriteFrame = this.bulleteIcon;
            このノードに子を追加します(bulleteNode)。

            //位置を設定する bulleteNode.x += space * i + 10;
            箇条書きノード.y = 0;

        }

    }

    始める() {

    }

    消費(数値: 数値) {
        this.stockNumber -= num;
        (this.stockNumber < 0)の場合{
            this.stockNumber = 0;
        }
        これを表示します。
    }

    画面() {
        ノードを作成します: cc.Node[] = this.node.children;
        console.log(ノードの長さ);
        for(let i=0;i<nodes.length;i++){
            if(i>=this.stockNumber){
                ノード[i].active=false;
            }
           
        }
    }

共通パブリッククラス

  //静的クラス、グローバル変数、共通クラス内のすべての共通変数とクラスを定義します static ammo:Ammo=null;

    オンロード() {
        Common.ammo=cc.find('Canvas/Ammunition').getComponent('Ammo');
        console.log(Common.ammo);
    }

バグは次のとおりです:

cc.find() メソッドでは、除算にスラッシュを使用することを忘れないでください。

弾切れプロンプトスコア

  1. マスクレイヤーを作成し、スクリプトクラスをCommonクラスにインポートし、activeプロパティをfalseに設定します。
  2. ResultDialog スクリプトに show メソッドを追加し、その active プロパティを true に設定して、スコアを画面に表示します。
  3. Bullete(弾の動きを制御するスクリプト)で、弾の数が <= 0 かどうかを判定し、Common の show メソッドを呼び出してスコアプロンプトボックスを表示します。

ResultDialog スクリプト (スコア プロンプト ボックスを制御)

 オンロード(){
         let replay:cc.Node=cc.find('Canvas/プロンプトボックスの終了/別のゲームをプレイ');
         console.log(リプレイ);
         replay.on('touchstart',this.dismiss,this);

         this.node.on('touchstart',this.onTouchdisable,this);
         this.node.on('touchmove',this.onTouchdisable,this);
         this.node.on('touchend',this.onTouchdisable,this);
   
     }

     //プロンプトボックスを表示 show(){
        アクティブノードを true に設定します。  
        scoreNode を設定します: cc.Node = cc.find('score box/score', this.node);
        scoreLabel を作成します: cc.Label = scoreNode.getComponent(cc.Label);   
        scoreLabel.string = Common.score + 'ポイント';   
       
        
     }

     //プロンプトボックスを非表示にする ignore(){
         this.node.active=false;
     }

     //マスクが表示されているときにシールドの onTouchdisable を有効にする (e: cc.Event.EventTouch) {
         e.stopPropagation();
     }
    始める () {

    }

一般的なスクリプト

 //静的クラス、グローバル変数、共通クラス内のすべての共通変数とクラスを定義します static ammo:Ammo=null;
    静的スコア:数値 = 0;
    静的結果ダイアログ: ResultDialog = null;
  

    オンロード() {
        Common.resultdialog=cc.find('Canvas/End prompt box').getComponent('ResultDialog');
        Common.ammo=cc.find('Canvas/Ammunition').getComponent('Ammo');
    }

Bullete方式でスコアを上げる

  if (this.isHit()) {
                //爆発効果を再生します this.explode();
                //+10 ポイントを表示します this.cheer();
                //合計スコア +10
                共通スコア += 10;
                console.log("ターゲットをヒット");
            }

ゲーム再開

このゲームは比較的単純です。再開するには、弾薬庫ノードをリセットするだけです。そのため、リセット メソッドは Ammo スクリプトに配置されます。パブリック クラスに Ammo オブジェクトを作成し、静的メソッドを設定して、スコアをリセットし、Ammo のリセット メソッドを呼び出します。

弾薬庫スクリプトを追加しました

 リセット(){
        this.stockNumber=this.capacity;
        これを表示します。
    }

共通スクリプトを変更する

 //静的クラス、グローバル変数、共通クラス内のすべての共通変数とクラスを定義します static ammo:Ammo=null;
    静的スコア:数値 = 0;
    静的結果ダイアログ: ResultDialog = null;
  

    オンロード() {
        Common.resultdialog=cc.find('Canvas/End prompt box').getComponent('ResultDialog');
        Common.ammo=cc.find('Canvas/Ammunition').getComponent('Ammo');
        console.log(Common.ammo);
    }
    静的リセットゲーム() {
        共通スコア=0;
        Common.ammo.reset();
    }

詳細を追加する

ゲームサウンドの追加と砲塔の起動の変更

1. 砲塔スクリプトにプロパティを追加

 //サウンド効果 @property(cc.AudioClip)
    audioFire: cc.AudioClip = null;
    @property(cc.AudioClip)
    audioExplode: cc.AudioClip = null;

    //砲塔画像 @property(cc.SpriteFrame)
    アイコンノーマル: cc.SpriteFrame = null;
    @property(cc.SpriteFrame)
    アイコンアクティブ: cc.SpriteFrame = null;

画像スイッチ

 onTouchStart(e: cc.Event.EventTouch) {メソッドの最後に追加 //砲塔の画像をアクティブに切り替えます this.node.getComponent(cc.Sprite).spriteFrame = this.iconActive;
 onTouchEnd(e: cc.Event.EventTouch) {メソッドが最後に追加されました //画像の復元 this.node.getComponent(cc.Sprite).spriteFrame = this.iconNormal;
      }

効果音再生

fire(){ メソッドの後に追加します // 弾丸の爆発音を弾丸スクリプトに送信します script.audioExplode = this.audioExplode;
 if (this.audioFire != null) {
            cc.audioEngine.play(this.audioFire, false, 1);
        }
    }

オーディオを再生する方法: ==cc.audioEngine.play(this.audioFire, false, 1); ==2番目のパラメータはループ再生するかどうか、3番目のパラメータは音量です

箇条書きスクリプト

//属性を追加 @property(cc.SpriteFrame)
爆発画像: cc.SpriteFrame = null;
if(this.audioExplode!=null){ を追加します。
	cc.audioEngine.play(this.audioExplode,false,1);
}

以上がCocosCreatorでシューティングゲームを作る方法の詳しい説明です。CocosCreatorシューティングゲームの詳細については、123WORDPRESS.COMの他の関連記事に注目してください!

以下もご興味があるかもしれません:
  • Unity は物理エンジンを使用してマルチロータードローンの飛行をシミュレートします
  • Android 向け 2D 物理エンジン Box2d を使用する簡単な例
  • CocosCreator ソースコードの解釈: エンジンの起動とメインループ
  • CocosCreator 一般的なフレームワーク設計リソース管理
  • CocosCreatorでリストを作成する方法
  • CocosCreator の新しいリソース管理システムの分析
  • CocosCreator スケルトンアニメーション ドラゴンボーン
  • CocosCreatorでクールなレーダーチャートを描く方法
  • CocosCreator MVCアーキテクチャの詳細な説明
  • CocosCreator で物理エンジン ジョイントを使用する方法

<<:  Linux での grep コマンドの使い方の詳細な説明

>>:  MySQL 高可用性ソリューション MMM (MySQL マルチマスター レプリケーション マネージャー)

推薦する

CSS 表示テーブルの適応的な高さと幅の問題の解決策

定義と使用法display プロパティは、要素が生成するボックスのタイプを指定します。例示するこの属...

LinuxのバックグラウンドでPythonプログラムを実行するいくつかの方法

1. 最初の方法は、unhup コマンドを直接使用してプログラムをバックグラウンドで実行することです...

ローカル yum ソースの設定、国内 yum ソースの設定、epel ソースの設定を行う Linux の手順

1. ローカルyumソースを設定する1. ISOイメージをマウントする マウント -o loop /...

キャンバス操作プラグイン fabric.js の使い方を詳しく解説

Fabric.js は非常に便利なキャンバス操作プラグインです。ここでは、日常のプロジェクトで使用さ...

Dockerを使用してサーバー上で複数のPHPバージョンを実行する

PHP7 がリリースされてからかなり時間が経ちますが、パフォーマンスが大幅に向上したことはよく知られ...

Linux は、Deepin がルートユーザーとして Google Chrome ブラウザを起動できない問題を解決します

Deepin がルートユーザーとして Google Chrome ブラウザを起動できない問題を解決す...

MySQL で高性能なインデックスを作成するための完全な手順

目次1. インデックスの基本1. インデックスの種類1.1 Bツリーインデックス1.2 ハッシュイン...

Linuxがすべてのコマンドをサポートしていない問題の解決策

Linux がすべてのコマンドをサポートしていない場合はどうすればいいですか?すべてのLinuxコマ...

Angularルーティングサブルートの詳細な説明

目次1. サブルート構文2. 例1. 2つの新しいコンポーネントを作成し、その内容を変更する2. ル...

win10でのmysql5.7.21解凍バージョンのインストールチュートリアル

次のように、Win10でMysqlの解凍バージョンをインストールします。環境: win10 64ビッ...

SQL Server コメントのショートカット キー操作

SQL Server のバッチコメントバッチ注釈Ctrl + (K, C): Ctrlキーを押しなが...

Centos サーバーに MySql をデプロイし、Navicat に接続するプロセスの詳細な説明

(1)サーバー構成: [root@localhost ~]# cd /usr/local/src/ ...

JavaScriptの記事では、Webフォームの操作方法を説明します。

1. はじめに先ほど、ウェブページの急速な発展について紹介しました。今回は、より深い内容についてお...

JavaScript の onblur および onfocus イベントの詳細な説明

HTML ページでは、ボタンやテキスト ボックスなどの視覚要素にフォーカスを設定したり、フォーカスを...

IE7でソースファイルを含むページを開くとページが空白になる問題の解決方法

質問:私のブログのエンコーディングは utf-8 です。ページを開くと空白になっていることもあります...