Detaillierte Erklärung zur Erstellung von Schießspielen mit CocosCreator

Detaillierte Erklärung zur Erstellung von Schießspielen mit CocosCreator

Szeneneinstellung

Spielressourcen

Turmdrehung

Der Mechanismus ist derselbe wie beim Auto in der vorherigen Handle-Instanz und verwendet Touchmove, um auf Berührungsereignisse zu warten.

  1. Berührungsposition abrufen
  2. Verwenden Sie die Methode signAngle, um die Winkeldifferenz zwischen der Position und der Position cc.v2(1,0) zu ermitteln (denken Sie daran, ein negatives Vorzeichen hinzuzufügen. Der Vergleich gegen den Uhrzeigersinn ist negativ und der Vergleichswert gegen den Uhrzeigersinn ist positiv).
  3. Der gesuchte Winkel ist der Endwinkel.

 beim Laden(){
        //Auf 90 Grad initialisieren this.node.angle=90;
        dies.node.on('touchstart',dieses.onTouchStart,dieses);
        dies.node.on('touchmove',dies.onTouchMove,dies);
        dies.node.on('touchend',dieses.onTouchEnd,dieses);
        dies.node.on('touchconcel',dies.onTouchConcel,dies);
    }
   
    beiBerührenStart(e:cc.Event.EventTouch){
        //Startposition abrufen this.starPos=this.node.parent.convertToNodeSpace(e.getLocation());
        //Den Anfangswinkel der Mündung abrufen this.starAngle=this.node.angle;

    }
    beiBerührenEnde(e:cc.Event.EventTouch){

    }
    beiBerührenBewegung(e:cc.Event.EventTouch){
        // Aktuelle Position des Berührungspunkts abrufen let pos:cc.Vec2=this.node.parent.convertToNodeSpace(e.getLocation());

        //Winkel ermitteln //Der Winkel ist im Uhrzeigersinn negativ und gegen den Uhrzeigersinn positiv let sweep_radian=pos.signAngle(this.starPos); //Der Winkel von pos relativ zu starPose p ist im Uhrzeigersinn relativ zu s positiv let sweep_angle=sweep_radian*180/Math.PI; //Winkel in Radiant umrechnen //Den Turm auf den endgültigen Winkel zeigen lassen let angle=this.starAngle-sweep_angle;
      
        //Begrenzen Sie den Winkel zwischen 45 und 135, wenn (Winkel < 45) Winkel = 45;
        wenn(Winkel>135)Winkel=135;

        cc.log("Mündungsschwung: "+sweep_angle+"Endgültige Winkelposition: "+angle);
        this.node.angle=Winkel;
    }

Dynamisch generierte Aufzählungszeichen

  1. Erzeugen Sie einen Knoten cc.Node und fügen Sie eine Komponente addComponent(cc.Sprite) hinzu.
  2. Weisen Sie den Eigenschaften der Komponente und dem SpriteFrame des Bildes Werte zu
  3. Mounten Sie die Komponente unter einem übergeordneten Knoten
  4. Position, Winkel usw. festlegen.
  5. Um die Bewegung zu steuern, können Sie das neu erstellte Skript importieren und es der Komponente des dynamisch generierten Knotens hinzufügen.
 beiBerührenEnde(e:cc.Event.EventTouch){
        dies.feuer();
    }
    beiBerührenConcel(e:cc.Event.EventTouch){

    }

    Feuer(){

        wenn(dieses.bulleteicon==null)zurückgeben;
        let bullet:cc.Node=neuer cc.Node();
        let sprite:cc.Sprite=bullet.addComponent(cc.Sprite);
        sprite.spriteFrame=dieses.bulleteicon;
        

        //Am Knoten des Aufnahmesystems anbringen bullet.parent=this.node.parent;

        //Die relative Position des übergeordneten Knotens festlegen let ration=this.node.angle*Math.PI/180;
        sei Richtung = cc.v2 (Math.cos (Ration), Math.sin (Ration));
        bullet.angle=dieser.Knoten.angle;
        sei r=100;
        bullet.setPosition(cc.v3(r*direction.x,r*direction.y,0));
       
        //Zusätzliche Skriptkomponente let script=bullet.addComponent(Buletet);
         script.explodeImg=dieses.explodeImg;
         script.direction=Richtung;

    }
 Start () {
         dies.Zeitplan(dies.onTimer,0.01);
    }

    einTimer(){
        wenn(this.node.y>300){
            dies.aufheben(dies.aufTimer);
            dies.explodieren();
           
            zurückkehren;
        }
        sei dx = diese.Richtung.x * 5;
        sei dy=diese.Richtung.y*5;
        dieser.Knoten.y+=dy;
        dieser.Knoten.x+=dx;
    }

    explodieren()

        lass sp:cc.Sprite=this.getComponent(cc.Sprite);
        sp.spriteFrame=dieses.explodeImg;
      
        //Aufzählungszeichen verkleinern this.node.scale=0.1;
        //Beschleunigungssystem für Explosionsanimationseffekte let self=this;
        cc.tween(dieser.Knoten)
            .bis(0,5,{Maßstab:1,Deckkraft:0})
            .call(Funktion(){
                selbst.nachExplode();
            })
            .Start();

            
    }

    nachExplode(){
        dies.node.destroy();
    }

Dieser Fehler:

  1. Der importierte Klassenname unterscheidet sich vom Dateinamen. Beachten Sie, dass durch das Umbenennen der Datei der Klassenname im Code nicht automatisch geändert wird. Sie müssen ihn daher zweimal ändern.
  2. Bei Verwendung der Methode setposition() werden die Parameter in den Konstruktor von cc.v3 geschrieben. Achten Sie unbedingt auf die Position der Parameter.

Kollisionsberechnung

Berechnen Sie die relative Position der Kugel und des Ziels. Wenn sie kleiner als die Reichweite ist, wird das Ziel als getroffen beurteilt und der Treffervorgang wird ausgeführt. Andernfalls wird das Ziel als nicht getroffen beurteilt und der Nichttreffervorgang wird ausgeführt.

Das Skript muss den Zielknoten übergeben und das Zielattribut hinzufügen

   @Eigenschaft(cc.SpriteFrame)
    explodierenBild: cc.SpriteFrame = null;
    
    Richtung: cc.Vec2 = null;

    Ziel: cc.Node = null;
    beim Laden() {

    }

    Start() {
        dies.schedule(dieses.onTimer, 0,01);
    }

    einTimer() {
        wenn (this.node.y > 350) {
            wenn (this.isHit()) {
                //Explosionseffekt abspielen this.explode();
                console.log("Triff das Ziel");
            }
            anders {
                console.log("vom Ziel abgekommen");
                dies.disMiss();
            }
            dies.aufheben(dies.aufTimer);
            zurückkehren;
        }
        sei dx = diese.Richtung.x * 5;
        sei dy = diese.Richtung.y * 5;
        dieser.Knoten.y += dy;
        dieser.Knoten.x += dx;
    }

    //Beurteilen, ob es trifft isHit(): boolean {
        lass targetPos: cc.Vec2 = this.geWorldLocation(this.target);
        lass selfPos: cc.Vec2 = this.geWorldLocation(this.node);
        sei Abstand = Math.abs(ZielPos.x - SelbstPos.x);
        console.log("Ziel x=" + ZielPos.x + " , Aufzählungszeichen x=" + SelbstPos.x);

        wenn (Entfernung < 50) {
            gibt true zurück;

        }
        anders {
            gibt false zurück;
        }

    }
    explodieren() {

        let sp: cc.Sprite = this.getComponent(cc.Sprite);
        sp.spriteFrame = dies.explodeImg;

        //Aufzählungszeichen verkleinern this.node.scale = 0.1;
        // Beschleunigungssystem für Explosionsanimationseffekte let self = this;
        cc.tween(dieser.Knoten)
            .to(0,5, { Maßstab: 1, Deckkraft: 0 })
            .call(Funktion () {
                selbst.disMiss();
            })
            .Start();


    }

    geWorldLocation(Knoten: cc.Node): cc.Vec2 {
        let pos = node.getPosition();
        //Beachten Sie, dass dies node.parent ist. Der Aufrufer der Methode sollte das Koordinatensystem des aktuellen Knotens sein. return node.parent.convertToWorldSpaceAR(pos);

    }

    zurückweisen() {
        dies.node.destroy();
    }

Dieser Fehler:

Beim Abrufen der Weltkoordinaten wird nicht das Koordinatensystem des übergeordneten Knotens aufgerufen, sondern das Koordinatensystem des aktuellen Knotens verwendet, sodass der zurückgegebene Wert immer noch der Wert des aktuellen Koordinatensystems selbst ist. Denken Sie daran, dass der Methodenaufrufer zum Konvertieren von Weltkoordinaten das Koordinatensystem des aktuellen Knotens ist, normalerweise dessen übergeordneter Knoten. return node.parent.convertToWorldSpaceAR(pos); (mit dem Ankerpunkt als Ursprung)

Erhöhen Sie die Wirkung

Fügen Sie unter dem Zielknoten ein Skript hinzu, um die Bewegung zu steuern, sich nach links und rechts zu bewegen und einen Textaufforderungseffekt hinzuzufügen, wenn die Kugel trifft.

Texttipps:

 jubeln() {
        //Einen Knoten erstellen und let node mounten: cc.Node = new cc.Node();
        node.parent = this.node.parent; //Beide sind auf derselben Ebene, mit demselben übergeordneten Objekt let label: cc.Label = node.addComponent(cc.Label);
        label.string = "+10 Punkte";

        //Position, Transparenz usw. festlegen node.setPosition(cc.v3(0, 250, 0));
        Knoten. Opazität = 200;
        node.color = neue cc.Color(255, 0, 0);

        //Animation cc.tween(Knoten)
            .bis(0,5, { Maßstab: 1,5 })
            .to(0.2, { Deckkraft: 0 })
            .call(Funktion () {
                node.zerstören();
            })
            .Start();

    }

Zielbewegung

 update (dt) {
         sei Geschwindigkeit=3;
         wenn(dies.istLinks){
             Geschwindigkeit=-Geschwindigkeit;
         }
         this.node.x+=Geschwindigkeit;
         wenn(dies.istLinks&&dieser.knoten.x<-350){
             dies.isLeft=false;
         }
         wenn(!this.isLeft&&this.node.x>350){
            dies.isLeft=true;
        }
    }

Anzeige des Munitionsdepots hinzugefügt

  1. Munitionsdepot-Knoten zum Stapelgenerieren von Geschossbildern hinzugefügt (Position kann mithilfe der Widget-Komponente festgelegt werden)
  2. Fügen Sie eine Methode zum Reduzieren von Aufzählungszeichen hinzu und reduzieren Sie Aufzählungszeichen, indem Sie die aktive Eigenschaft des Aufzählungszeichenbildes festlegen.
  3. Rufen Sie die Methode auf, um die Anzahl der Kugeln im Geschützturm zu reduzieren

Es gibt zwei Aufrufmethoden. Eine besteht darin, den Munitionsdepotknoten im Turmskript abzurufen und ihn dann aufzurufen. Die andere besteht darin, eine öffentliche Klasse (statische Variable) festzulegen, den Knoten in der Methode onLoad() zu initialisieren und ihn dann direkt aufzurufen. Verwenden Sie Letzteres.

 @Eigenschaft(cc.SpriteFrame)
    Aufzählungszeichen: cc.SpriteFrame = null;
    Kapazität: Zahl = 10;
    Lagernummer: Zahl = 10;


    beim Laden() {

        lass Platz: Zahl = diese.Knotenbreite / diese.Kapazität;
        für (lass i = 0; i < diese.Kapazität; i++) {
            //Bild generieren let bulleteNode: cc.Node = new cc.Node();
            let bulleteSprite: cc.Sprite = bulleteNode.addComponent(cc.Sprite);
            bulleteSprite.spriteFrame = dieses.bulleteIcon;
            dies.node.addChild(bulleteNode);

            //Position festlegen bulleteNode.x += space * i + 10;
            bulleteNode.y = 0;

        }

    }

    Start() {

    }

    verbrauchen(num: Zahl) {
        diese.stockNumber -= Zahl;
        wenn (diese.Bestandsnummer < 0) {
            diese.Bestandsnummer = 0;
        }
        dies.anzeige();
    }

    Anzeige() {
        lass Knoten: cc.Node[] = this.node.children;
        Konsole.log(Knoten.Länge);
        für (lass i = 0; i < Knoten. Länge; i++) {
            wenn(i>=diese.Bestandsnummer){
                Knoten[i].aktiv=false;
            }
           
        }
    }

Gemeinsame öffentliche Klasse

  //Statische Klasse, globale Variable, definiere alle allgemeinen Variablen und Klassen in der allgemeinen Klasse static ammo:Ammo=null;

    beim Laden() {
        Common.ammo=cc.find('Leinwand/Munition').getComponent('Munition');
        Konsole.log(Common.ammo);
    }

Hier ist der Fehler:

Denken Sie daran, in der Methode cc.find() den Schrägstrich für die Division zu verwenden.

Punktzahl für die Aufzählungserschöpfung

  1. Erstellen Sie eine Maskenebene, importieren Sie die Skriptklasse in die Common-Klasse und setzen Sie die aktive Eigenschaft auf „false“
  2. Fügen Sie dem ResultDialog-Skript die Show-Methode hinzu, setzen Sie ihre Active-Eigenschaft auf True und zeigen Sie den Punktestand auf dem Bildschirm an.
  3. Bestimmen Sie in Bullete (dem Skript, das die Bewegung der Aufzählungszeichen steuert), ob die Anzahl der Aufzählungszeichen <= 0 ist, und rufen Sie die Show-Methode in Common auf, um das Eingabeaufforderungsfeld für die Punkte anzuzeigen.

ResultDialog-Skript (steuert das Punkte-Eingabefeld)

 beim Laden () {
         let replay:cc.Node=cc.find('Canvas/Eingabeaufforderungsfeld beenden/ein anderes Spiel spielen');
         Konsole.log(Wiedergabe);
         Wiederholung.auf('touchstart',dies.verwerfen,dies);

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

     //Eingabeaufforderungsfeld anzeigen show(){
        dieser.Knoten.aktiv=wahr;  
        lass scoreNode: cc.Node = cc.find('Ergebnisbox/Ergebnis', dieser.Knoten);
        Lassen Sie scoreLabel: cc.Label = scoreNode.getComponent(cc.Label);   
        scoreLabel.string = Common.score + 'Punkte';   
       
        
     }

     //Das Eingabeaufforderungsfeld ausblenden exclude(){
         dieser.Knoten.aktiv=falsch;
     }

     //Shield onTouchdisable wenn Maske angezeigt wird (e: cc.Event.EventTouch) {
         e.stopPropagation();
     }
    Start () {

    }

Allgemeine Skripte

 //Statische Klasse, globale Variable, definiere alle allgemeinen Variablen und Klassen in der allgemeinen Klasse static ammo:Ammo=null;
    statische Punktzahl: Zahl = 0;
    statischer Ergebnisdialog: Ergebnisdialog = null;
  

    beim Laden() {
        Common.resultdialog=cc.find('Leinwand/Eingabeaufforderungsfeld beenden').getComponent('ResultDialog');
        Common.ammo=cc.find('Leinwand/Munition').getComponent('Munition');
    }

Erhöhen Sie die Punktzahl in der Bullete-Methode

  wenn (this.isHit()) {
                //Explosionseffekt abspielen this.explode();
                //+10 Punkte anzeigen this.cheer();
                //Gesamtpunktzahl +10
                Gemeinsamer Score + = 10;
                console.log("Triff das Ziel");
            }

Spielneustart

Dieses Spiel ist relativ einfach. Um es neu zu starten, müssen Sie nur den Munitionsdepotknoten zurücksetzen. Daher wird die Reset-Methode im Ammo-Skript platziert. Erstellen Sie ein Ammo-Objekt in der öffentlichen Klasse, legen Sie eine statische Methode fest, setzen Sie den Punktestand zurück und rufen Sie die Reset-Methode von Ammo auf.

Ammo (Munitionsdepot) Skript hinzugefügt

 zurücksetzen(){
        diese.Bestandsnummer=diese.Kapazität;
        dies.anzeige();
    }

Ändern des allgemeinen Skripts

 //Statische Klasse, globale Variable, definiere alle allgemeinen Variablen und Klassen in der allgemeinen Klasse static ammo:Ammo=null;
    statische Punktzahl: Zahl = 0;
    statischer Ergebnisdialog: ResultDialog = null;
  

    beim Laden() {
        Common.resultdialog=cc.find('Leinwand/Eingabeaufforderungsfeld beenden').getComponent('ResultDialog');
        Common.ammo=cc.find('Leinwand/Munition').getComponent('Munition');
        Konsole.log(Common.ammo);
    }
    statisches ResetGame() {
        Gemeinsam.score=0;
        Common.ammo.reset();
    }

Fügen Sie einige Details hinzu

Spielgeräusche und Änderungen an der Geschützturmaktivierung hinzugefügt

1. Eigenschaften zum Turmskript hinzugefügt

 //Soundeffekt @property(cc.AudioClip)
    audioFire: cc.AudioClip = null;
    @Eigenschaft(cc.AudioClip)
    audioExplode: cc.AudioClip = null;

    //Turmbild @property(cc.SpriteFrame)
    SymbolNormal: cc.SpriteFrame = null;
    @Eigenschaft(cc.SpriteFrame)
    Symbol Aktiv: cc.SpriteFrame = null;

Bildschalter

 onTouchStart(e: cc.Event.EventTouch) {am Ende der Methode hinzufügen //Turmbild aktivieren this.node.getComponent(cc.Sprite).spriteFrame = this.iconActive;
 onTouchEnd(e: cc.Event.EventTouch) {Methode schließlich hinzugefügt //Bildwiederherstellung this.node.getComponent(cc.Sprite).spriteFrame = this.iconNormal;
      }

Soundeffekt-Wiedergabe

fire(){ Nach der Methode hinzufügen //Senden Sie den Ton der Bullet-Explosion an das Bullet-Skript script.audioExplode = this.audioExplode;
 wenn (this.audioFire != null) {
            cc.audioEngine.play(this.audioFire, false, 1);
        }
    }

Methode zum Abspielen von Audio: ==cc.audioEngine.play(this.audioFire, false, 1); ==Der zweite Parameter gibt an, ob in einer Schleife abgespielt werden soll, und der dritte Parameter ist die Lautstärke

Bullet-Skript

//Attribut hinzufügen @property(cc.SpriteFrame)
explodierenBild: cc.SpriteFrame = null;
Fügen Sie if(this.audioExplode!=null){ hinzu
	cc.audioEngine.play(dieses.audioExplode,false,1);
}

Oben finden Sie eine ausführliche Erklärung, wie Sie mit CocosCreator Schießspiele erstellen. Weitere Informationen zu CocosCreator-Schießspielen finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Unity nutzt Physik-Engine zur Simulation des Flugs von Multirotor-Drohnen
  • Einfaches Beispiel für die Verwendung von Box2d, einer 2D-Physik-Engine für Android
  • Interpretation des CocosCreator-Quellcodes: Engine-Start und Hauptschleife
  • CocosCreator allgemeines Framework-Design Ressourcenmanagement
  • So erstellen Sie eine Liste in CocosCreator
  • Analyse des neuen Ressourcenmanagementsystems von CocosCreator
  • CocosCreator Skelettanimation Drachenknochen
  • So zeichnen Sie in CocosCreator ein cooles Radardiagramm
  • Detaillierte Erklärung der CocosCreator MVC-Architektur
  • So verwenden Sie Verbindungen der Physik-Engine in CocosCreator

<<:  Detaillierte Erklärung zur Verwendung des Grep-Befehls in Linux

>>:  MySQL-Hochverfügbarkeitslösung MMM (MySQL Multi-Master-Replikationsmanager)

Artikel empfehlen

Detaillierte Erläuterung zur Verwendung der WeChat-Miniprogrammkarte

In diesem Artikelbeispiel wird der spezifische Im...

HTML-Tutorial: Sammlung häufig verwendeter HTML-Tags (5)

Verwandte Artikel: Anfänger lernen einige HTML-Ta...

So kapseln Sie Timerkomponenten in Vue3

Hintergrund Wenn Sie auf manchen Webseiten von Ei...

So implementieren Sie https mit Nginx und OpenSSL

Wenn die Serverdaten nicht verschlüsselt und mit ...

So ändern Sie den Hostnamen in Linux dauerhaft

Wenn Sie Ihren Hostnamen ändern möchten, können S...

Verwenden Sie die mail()-Funktion von PHP zum Senden von E-Mails

Senden von E-Mails mit der Mail-Funktion von PHP ...

Schnellstart der Vue3-Dokumentation

Inhaltsverzeichnis 1. Einrichtung 1. Der erste Pa...

Ein kurzer Überblick über CSS3-Pseudoklassenselektoren

Vorwort Wenn CSS die Grundfertigkeit der Front-En...

Eine kurze Diskussion über HTML-Dokumenttypen und -Kodierung

DOKTYP Doctype wird verwendet, um dem Browser mit...

Lösung, wenn der Docker-Container nicht auf den Host-Port zugreifen kann

Ich bin kürzlich bei der Arbeit auf ein Problem g...

xtrabackup MySQL-Datenbank sichern und wiederherstellen

Aufgrund einiger seiner eigenen Merkmale (Sperren...

Implementierung der MySQL GRANT-Benutzerautorisierung

Bei der Autorisierung geht es darum, einem Benutz...