Unity-Small Game Priester und Dämon

Unity-Small Game Priester und Dämon

Spieleinführung

Zu Beginn des Spiels befinden sich drei Priester und drei Dämonen auf einer Seite des Flusses. Ziel des Spiels ist es, ihnen zu helfen, den Fluss auf die andere Seite zu überqueren, und die Anzahl der Priester darf nicht geringer sein als die Anzahl der Dämonen auf beiden Seiten, sonst greifen die Dämonen die Priester an. Die Spielregeln lauten wie folgt:

Charaktere und Requisiten:
  • Priester (P): Es gibt drei Priester im Spiel, dargestellt durch P.
  • Teufel (D): Es gibt drei Dämonen im Spiel, dargestellt durch D.
  • Schiff (B): Es gibt ein Schiff im Spiel, dargestellt durch B. Die maximale Kapazität des Bootes beträgt zwei Personen.
Ausgangszustand:
  • Zunächst befinden sich drei Priester (PPP), drei Dämonen (DDD) und das Boot (B) auf einer Seite des Flusses.
Zielstatus:
  • Das Ziel des Spiels ist es, alle Priester und Dämonen sicher auf die andere Seite des Flusses zu bringen, und es darf auf keiner Seite mehr Dämonen als Priester geben (z. B. sind PD oder PDD auf beiden Seiten des Flusses legal), aber DD ist ein illegaler Status).
Bewegungsregeln:
  • Ein Boot kann bis zu zwei Charaktere (Kleriker, Dämonen oder eine Mischung aus beiden) gleichzeitig über den Fluss transportieren.
  • Es darf auf keiner Seite mehr Dämonen als Priester geben, sonst greifen die Dämonen die Priester an und das Spiel ist verloren.
  • Sowohl Geistliche als auch Dämonen können das Schiff bedienen, es dürfen sich jedoch nicht mehr als zwei Charaktere an Bord befinden.
Spiel vorbei:

Das Spiel endet in zwei Situationen:

  • Wenn alle Priester und Dämonen sicher auf die andere Seite des Flusses gelangt sind und die Bedingungen erfüllen (die Anzahl der Dämonen ist nicht größer als die Anzahl der Priester), ist das Spiel gewonnen.
  • Wenn es auf einer Seite mehr Dämonen als Priester gibt, greifen die Dämonen die Priester an und das Spiel ist verloren.

„Priests and Demons“ ist ein klassisches Denkspiel, bei dem die Spieler die Positionen der Charaktere und Passagiere auf dem Boot geschickt und den Regeln entsprechend anordnen müssen, um sicherzustellen, dass alle Charaktere den Fluss sicher überqueren können. Es ist ein Spiel, das logisches Denken und Planen auf die Probe stellt Fähigkeiten. .

Designarchitektur (MVC)

Mit der MVC-Idee (Model-View-Controller) ist die Spielstruktur klarer.

1. Einführung in die Klasse
  • Director-Klasse: Im Einzelinstanzmodus implementiert, verantwortlich für globale Spieleinstellungen, Szenenverwaltung usw.

  • SceneManager-Klasse: Implementiert die Spielmodellverwaltung und Spiellogik, entspricht dem MVC-Framework und trennt die Logik der Benutzeransicht und des Spielszenenmodells.

  • Schnittstelle zur Mensch-Computer-Interaktion (IUserAction): Beschreibt die den Spielregeln entsprechenden Vorgänge und definiert das Benutzerinteraktionsverhalten im Spiel.

2. MVC-Framework-Workflow
  1. Director-Objekteinstellungen: Die Director-Klasse ist für die globalen Einstellungen des Spiels verantwortlich, einschließlich der Initialisierung von Spielszenen, Charakteren und anderen Informationen.

  2. Szenenwechsel: Der Szenenmanager ist für die Verwaltung von Spielszenen verantwortlich, einschließlich des Wechsels zwischen verschiedenen Spielszenen, um einen reibungslosen Ablauf des Spielprozesses sicherzustellen.

  3. Benutzeroperationsverarbeitung: Benutzeroperationen werden von Klassen verarbeitet, die die IUserAction-Schnittstelle implementieren, die Operationen definiert, die Spielregeln entsprechen, wie z. B. Spielerbewegungen , Angriff usw.

3. Vorteile
  • Klare Struktur: Das MVC-Framework macht die Spielstruktur klarer und trennt Datenmodell, Benutzeransicht und Steuerungslogik.

  • Modulare Entwicklung: Verschiedene Module (Model, View, Controller) können unabhängig voneinander entwickelt und getestet werden, was die Wartbarkeit und Skalierbarkeit des Codes verbessert.

  • Logische Trennung: Durch MVC wird die logische Trennung der Benutzeransicht und des Spielszenenmodells erreicht, wodurch die Kopplung reduziert wird.

  • Einheitliche Szenensteuerung: Es wurde eine einheitliche Szenensteuerungsschnittstelle eingerichtet, um unterschiedliche Geschäftslogiken in verschiedenen Szenarien zu unterstützen und so die Flexibilität zu erhöhen.

Fügen Sie hier eine Bildbeschreibung ein

Der konkrete Entwurfsplan lautet wie folgt:
Fügen Sie hier eine Bildbeschreibung ein

Spezifische Code-Implementierung

IUserAction
public interface IUserAction
{
    // 移动船
    void moveBoat();
    // 处理角色点击事件
    void characterIsClicked(MyCharacterController characterCtrl);
    // 重新开始游戏
    void restart();
}

Die SchnittstelleIUserAction definiert drei Methoden für den Spielbetrieb: moveBoat() zum Bewegen des Schiffs, characterIsClicked(MyCharacterController characterCtrl) zur Verarbeitung des Zeichenklickereignisses , restart() wird verwendet, um das Spiel neu zu starten.

ISceneController
// ISceneController 接口,定义了游戏场景控制器的方法契约。
public interface ISceneController
{
    
    
    // 加载游戏资源的方法,由实现接口的类负责具体实现。
    void loadResources();
}

Code-Analyse:

  1. ISceneControllerEs handelt sich um eine Schnittstelle, die den Vertrag des Spielszenen-Controllers definiert. Eine Schnittstelle ist ein abstrakter Datentyp, der nur Deklarationen von Methoden, Eigenschaften, Ereignissen oder Indexern enthält, aber keine Implementierung von Methoden bereitstellt. Schnittstellen stellen eine Spezifikation bereit, die die Implementierung mehrerer Klassen nach denselben Standards ermöglicht und so die Organisation und Zusammenarbeit von Code ermöglicht.

  2. loadResources()Die Funktion der Methode besteht darin, die vom Spiel benötigten Ressourcen zu laden. Die spezifische Implementierung wird durch eine Klasse vervollständigt, die die Schnittstelle ISceneController implementiert. Diese Methode ermöglicht es dem Spielszenen-Controller, die erforderlichen Ressourcen zu Beginn des Spiels zu laden, damit das Spiel ordnungsgemäß ausgeführt werden kann.

BenutzerGUI
// UserGUI 类,继承自 MonoBehaviour,负责游戏界面的显示和用户输入的处理。
public class UserGUI : MonoBehaviour
{
    
    
    // 用户操作接口。
    private IUserAction action;
    // 游戏状态,0 表示游戏进行中,1 表示游戏结束(失败),2 表示游戏结束(胜利)。
    public int status = 0;
    GUIStyle style;
    GUIStyle buttonStyle;

    // 在 Start 方法中进行初始化操作。
    void Start()
    {
    
    
        // 获取用户操作接口。
        action = SSDirector.getInstance().currentSceneController as IUserAction;

        // 设置文本样式。
        style = new GUIStyle();
        style.fontSize = 40;
        style.alignment = TextAnchor.MiddleCenter;

        // 设置按钮样式。
        buttonStyle = new GUIStyle("button");
        buttonStyle.fontSize = 30;
    }

    // 在 OnGUI 方法中绘制游戏界面和处理用户输入。
    void OnGUI()
    {
    
    
        // 根据游戏状态显示不同的界面。
        if (status == 0)
        {
    
    
            // 游戏进行中,显示“Restart”按钮,点击按钮可以重新开始游戏。
            if (GUI.Button(new Rect(Screen.width - 160, 10, 140, 70), "Restart", buttonStyle))
            {
    
    
                status = 0;
                action.restart();
            }
        }
        else if (status == 1)
        {
    
    
            // 游戏结束(失败),显示“Gameover!”文本和“Restart”按钮,点击按钮可以重新开始游戏。
            GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height / 2 - 85, 100, 50), "Gameover!", style);
            if (GUI.Button(new Rect(Screen.width / 2 - 70, Screen.height / 2, 140, 70), "Restart", buttonStyle))
            {
    
    
                status = 0;
                action.restart();
            }
        }
        else if (status == 2)
        {
    
    
            // 游戏结束(胜利),显示“You win!”文本和“Restart”按钮,点击按钮可以重新开始游戏。
            GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height / 2 - 85, 100, 50), "You win!", style);
            if (GUI.Button(new Rect(Screen.width / 2 - 70, Screen.height / 2, 140, 70), "Restart", buttonStyle))
            {
    
    
                status = 0;
                action.restart();
            }
        }
    }
}

Code-Analyse:

  1. UserGUIDie Klasse ist eine von MonoBehaviour geerbte Klasse und wird für die Anzeige und Benutzereingabe der Spieloberfläche verwendet.

  2. actionDie Variable wird zum Speichern der Instanz der Benutzerbetriebsschnittstelle verwendet, die über SSDirector.getInstance().currentSceneController abgerufen wird.

  3. statusDie Variable stellt den Spielstatus dar, 0 bedeutet, dass das Spiel läuft, 1 bedeutet, dass das Spiel vorbei ist (Misserfolg) und 2 bedeutet, dass das Spiel vorbei ist (Sieg).

  4. Führen Sie die Initialisierung in der Methode Start() durch und legen Sie die Stile von Text und Schaltflächen fest.

  5. OnGUI()Methoden werden verwendet, um Text und Schaltflächen auf der Spieloberfläche zu zeichnen und Benutzerklickereignisse zu verarbeiten. Je nach Spielstand werden unterschiedliche Oberflächenelemente angezeigt.

  6. Wenn der Spielstatus läuft (status == 0), wird die Schaltfläche „Neustart“ angezeigt. Klicken Sie auf die Schaltfläche, um das Spiel neu zu starten.

  7. Wenn der Spielstatus fehlgeschlagen ist (status == 1), werden der Text „Gameover!“ und die Schaltfläche „Neustart“ angezeigt. Klicken Sie auf die Schaltfläche, um das Spiel neu zu starten.

  8. Wenn der Spielstatus Sieg ist (status == 2), werden der Text „Sie gewinnen!“ und die Schaltfläche „Neustart“ angezeigt. Klicken Sie auf die Schaltfläche, um das Spiel neu zu starten.

SSDirector
// SSDirector 类,继承自 System.Object,实现了单例模式,用于管理当前场景的场景控制器。
public class SSDirector : System.Object
{
    
    
    // 静态变量,用于保存唯一的 SSDirector 实例。
    private static SSDirector _instance;
    // 当前场景的场景控制器,实现了 ISceneController 接口。
    public ISceneController currentSceneController {
    
     get; set; }

    // 获取单例实例的静态方法。
    public static SSDirector getInstance()
    {
    
    
        // 如果实例为空,创建一个新的 SSDirector 实例。
        if (_instance == null)
        {
    
    
            _instance = new SSDirector();
        }
        // 返回唯一的实例。
        return _instance;
    }
}

Code-Analyse:

  1. SSDirectorDie Klasse ist eine Singleton-Klasse, die zum Verwalten des Szenencontrollers der aktuellen Szene verwendet wird.

  2. currentSceneControllerDas Attribut wird zum Speichern der Szenen-Controller-Instanz der aktuellen Szene verwendet. Die Controller-Klasse muss die Schnittstelle ISceneController implementieren.

  3. getInstance()Die Methode ist eine statische Methode, die eine Instanz von SSDirector abruft. Wenn bei dieser Methode _instance leer ist (d. h. nicht instanziiert wurde), erstellen Sie eine neue SSDirector-Instanz und geben Sie diese Instanz dann zurück. Dadurch wird sichergestellt, dass in der gesamten Anwendung nur eine Instanz der Klasse SSDirector vorhanden ist, wodurch der Mehraufwand mehrerer Instanziierungen vermieden wird und gleichzeitig Datenkonsistenz und -sicherheit gewährleistet werden.

  4. Durch den Singleton-Modus stellt die Klasse SSDirector einen global eindeutigen Zugriffspunkt bereit, sodass andere Klassen ihn über SSDirector.getInstance()< erhalten können eine Instanz von i=3>, um auf den Szenencontroller der aktuellen Szene zuzugreifen und ihn zu verwalten. SSDirector

FirstController

Da es zu viel Code gibt, werde ich einige ikonische Teile extrahieren, um sie unten anzuzeigen.

Codekommentare und Textanalyse:

// FirstController 类,继承自 MonoBehaviour,实现了 ISceneController 和 IUserAction 接口,
// 用于控制游戏场景的初始化、游戏规则和用户操作。

public class FirstController : MonoBehaviour, ISceneController, IUserAction
{
    
    
    // 水面的位置。
    readonly Vector3 water_pos = new Vector3(0, 0.5F, 0);
    // 用户界面管理器。
    UserGUI userGUI;
    // 岸边的控制器。
    public CoastController fromCoast;
    public CoastController toCoast;
    // 船的控制器。
    public BoatController boat;
    // 角色控制器数组。
    private MyCharacterController[] characters;

    // Awake 方法在对象被创建时调用,用于初始化数据。
    void Awake()
    {
    
    
        // 获取场景总管,将当前场景控制器设置为当前场景。
        SSDirector director = SSDirector.getInstance();
        director.currentSceneController = this;
        // 在游戏对象上添加 UserGUI 组件,用于管理用户界面。
        userGUI = gameObject.AddComponent<UserGUI>() as UserGUI;
        // 初始化角色控制器数组和加载游戏资源。
        characters = new MyCharacterController[6];
        loadResources();
    }

    // 检查游戏是否结束的方法,返回值:0->未结束, 1->失败, 2->胜利
    int check_game_over()
    {
    
    
        // 统计各个岸上的牧师和魔鬼数量。
        int from_priest = 0;
        int from_devil = 0;
        int to_priest = 0;
        int to_devil = 0;

        // 统计 fromCoast 上的角色数量。
        int[] fromCount = fromCoast.getCharacterNum();
        from_priest += fromCount[0];
        from_devil += fromCount[1];

        // 统计 toCoast 上的角色数量。
        int[] toCount = toCoast.getCharacterNum();
        to_priest += toCount[0];
        to_devil += toCount[1];

        // 如果 toCoast 上的牧师和魔鬼总数为 6,则游戏胜利。
        if (to_priest + to_devil == 6)
            return 2;

        // 统计船上的角色数量。
        int[] boatCount = boat.getCharacterNum();
        if (boat.get_to_or_from() == -1)
        {
    
       // 船在 toCoast 上
            to_priest += boatCount[0];
            to_devil += boatCount[1];
        }
        else
        {
    
       // 船在 fromCoast 上
            from_priest += boatCount[0];
            from_devil += boatCount[1];
        }

        // 如果 fromCoast 上的牧师数量小于魔鬼数量并且有牧师,则游戏失败。
        if (from_priest < from_devil && from_priest > 0)
        {
    
           // 失败
            return 1;
        }
        // 如果 toCoast 上的牧师数量小于魔鬼数量并且有牧师,则游戏失败。
        if (to_priest < to_devil && to_priest > 0)
        {
    
    
            return 1;
        }
        // 游戏未结束。
        return 0;
    }

    // 重新开始游戏的方法,用于重置船和岸上的角色。
    public void restart()
    {
    
    
        boat.reset();
        fromCoast.reset();
        toCoast.reset();
        for (int i = 0; i < characters.Length; i++)
        {
    
    
            characters[i].reset();
        }
    }
}

Code-Analyse:

  1. FirstControllerDie Klasse ist der Controller der Spielszene und implementiert die Schnittstellen ISceneController und IUserAction.

  2. In der Methode Awake() rufen Sie eine Instanz des Szenenmanagers ab SSDirector und legen den aktuellen Szenencontroller auf die aktuelle Szene fest. Initialisieren Sie gleichzeitig die Benutzeroberflächenkomponente UserGUI und das Charakter-Controller-Array und laden Sie Spielressourcen.

  3. check_game_over()Methode zur Überprüfung, ob das Spiel beendet ist. Wenn das Spiel gewonnen wird (die Gesamtzahl der Priester und Teufel auf toCoast beträgt 6), gib 2 zurück; wenn das Spiel verloren geht (von

Wenn die Anzahl der Priester auf Coast oder toCoast geringer ist als die Anzahl der Teufel und es Priester gibt, geben Sie 1 zurück; andernfalls geben Sie 0 zurück, um anzuzeigen, dass das Spiel noch nicht vorbei ist.

  1. restart()Die Methode wird verwendet, um das Spiel neu zu starten. Bei dieser Methode werden der Status des Schiffes und der Charakter am Ufer zurückgesetzt, wodurch das Spiel in seinen Ausgangszustand zurückversetzt wird.

Entwicklungszusammenfassung

Während der Entwicklung dieses „Priests and Demons“-Spiels habe ich viele wichtige Konzepte und Fähigkeiten zur Spieleentwicklung erlernt, indem ich auf viele Referenzblogs und Codes im Internet zurückgegriffen habe. Hier sind einige wichtige Punkte aus der Entwicklungszusammenfassung:

1. Spieldesign und -planung

  • Definition der Spielregeln: Spielregeln müssen klar definiert sein, einschließlich Charakterfähigkeiten, Spielsiegbedingungen und Misserfolgsbedingungen usw.
  • Charakterdesign: Die Charaktere im Spiel sollten klare Identitäten und Eigenschaften haben, damit das Spiel über ausreichend Tiefe und Strategie verfügt.

2. Programmierkenntnisse

  • Schnittstelle und Implementierung: Verwenden Sie Schnittstellen, um Spiellogik und Benutzeroperationen zu trennen und so die Modularität und Wartbarkeit des Codes zu verbessern.
  • Einzelfallmodus: Verwenden Sie den Einzelfallmodus, um den Spielstatus zu verwalten und sicherzustellen, dass es während des gesamten Spiellebenszyklus nur eine Instanz gibt.
  • GUI-Programmierung: Erfahren Sie, wie Sie das GUI-System von Unity verwenden, um Spieloberflächen zu erstellen, einschließlich Schaltflächen, Beschriftungen und anderen UI-Elementen.

3. Logisches Denken und Problemlösung

  • Beurteilung des Spielstatus: Das Schreiben einer Spiellogik und die Beurteilung, ob das Spiel erfolgreich oder fehlgeschlagen ist, erfordert logisches Denken und Fähigkeiten zur Problemlösung.
  • Spielmechanismusdesign: Das Entwerfen von Spielregeln und Charakterfähigkeiten erfordert gründliche Überlegungen zur Ausgewogenheit und zum Spaß des Spiels.

4. Benutzererfahrung und Schnittstellendesign

  • Design der Benutzeroberfläche: Entwerfen Sie eine benutzerfreundliche Spieloberfläche, einschließlich Tastenposition, Schriftgröße usw., um ein gutes Benutzererlebnis zu bieten.
  • Spielfeedback: Geben Sie im Spiel angemessenes Feedback, z. B. die Anzeige entsprechender Aufforderungsinformationen, wenn das Spiel erfolgreich oder fehlgeschlagen ist, um die Interaktivität des Spiels zu erhöhen.

Videoanzeige

Einheitsspiel Priester und Dämon

Referenzblog

http://t.csdnimg.cn/UbqPT
http://t.csdnimg.cn/T5rqW

Supongo que te gusta

Origin blog.csdn.net/helianthus_254/article/details/133849634
Recomendado
Clasificación