قم بإنشاء أول لعبة iPhone لك من الصفر ، ولا توجد حاجة إلى تجربة تشفير.

المقدمة

تمت كتابة هذا البرنامج التعليمي لـ Swift 4.0 / XCode 9 ، وقد تواجه أي إصدارات مستقبلية مشاكل حتى أقوم بتحديث المقال.

إذن أنت مهتم ببناء ألعاب محمولة؟ ربما يكون ذلك بمثابة جاذبية الإقلاع وشراء سيارة جديدة أو ربما يكون مجرد شغف إنشاء لعبتك الخاصة. بغض النظر عن دوافعك ، سيرشدك هذا البرنامج التعليمي إلى خطوات إعداد جهاز الكمبيوتر الخاص بك لإنشاء تطبيقات وإنشاء لعبة بسيطة من الصفر! يتم تضمين جميع رمز اللعبة في البرنامج التعليمي. لا توجد حاجة إلى معرفة مسبقة بالبرمجة لإكمال هذا المشروع.

بعد الانتهاء من هذا البرنامج التعليمي ، ستتمكن من تشغيل تطبيق IOS الخاص بالبناء الخاص بك على جهازك أو محاكي الجهاز. سوف تفهم أساسيات تصميم لعبة من الصفر ، وكيفية حفظ البيانات على جهازك بعد إغلاق التطبيق الخاص بك ، وكيفية تقديم العفاريت على الشاشة ، وسوف تبدأ في فهم كيفية استخدام محرك لعبة SpriteKit. سوف أطلعك أيضًا على كيفية تصميم لعبة Snake وكيف يمكنك البدء في بناء لعبة بتصميم خاص بك!

فيما يلي رابط تنزيل لإصدار معدّل قليلاً من هذه اللعبة متوفر في متجر التطبيقات: https://itunes.apple.com/us/app/minimal-snake/id1355406338؟mt=8 (مجاني تمامًا بدون إعلانات).

ملاحظة: خلال المقالة ، استخدمت عبارة "نسخ / لصق" ، أوضح لي القارئ أن هذه ممارسة سيئة وأنا أوافق تمامًا. إذا كنت ترغب في نسخ الشفرة بسرعة وإنشاء منتج يعمل بشكل جيد ، فمن المحتمل أن تحصل على المزيد من الكتابة بخط اليد!

المنتج المكتمل

إليك مقطع فيديو يوضح ما ستقوم ببنائه وتثبيته على هاتفك بحلول نهاية هذا البرنامج التعليمي!

ابدء

لمتابعة هذا البرنامج التعليمي ، ستحتاج إلى إعداد حساب مطور Apple وتنزيل Xcode (البرنامج المستخدم لإنشاء تطبيقات IOS). Xcode متاح ، للأسف ، فقط لأجهزة Macs ؛ إذا كان لديك جهاز يعمل بنظام Windows / Linux ، فهناك موقع إلكتروني قد يساعدك في إعداد Xcode.

ستتبع الخطوات التالية عملية التسجيل للحصول على حساب مطور مجاني وتثبيت Xcode. إذا كان لديك بالفعل حساب و Xcode ، فيمكنك الانتقال إلى القسم التالي. من أجل البدء أولاً ، قم بزيارة developer.apple.com وانقر فوق مركز الأعضاء ، ثم قم بتسجيل الدخول باستخدام معرف Apple الخاص بك. انتقل إلى صفحة اتفاقية Apple Developer وقبول الاتفاقية ؛ لديك الآن حساب مطور مجاني! من أجل تحميل مشاريعك إلى متجر التطبيقات ، سيتعين عليك دفع رسوم سنوية قدرها 100 دولار.

الآن بعد أن أصبح لديك حساب مطور ، يجب عليك تثبيت Xcode. Xcode متاح عبر متجر تطبيقات Mac. بعد تثبيت Xcode ، قم بتشغيل البرنامج وانقر فوق Xcode -> تفضيلات -> حسابات -> + واختر إضافة معرف Apple. قم بتسجيل الدخول باستخدام معرف Apple الذي كان يستخدم للتسجيل لحساب المطور. تهانينا ، يمكنك الآن اختبار تطبيقاتك في محاكي iPhone أو تشغيلها على جهازك الشخصي!

بداية المشروع

الآن بعد أن قمت بالتسجيل لحساب المطور وتثبيت Xcode ، يمكنك البدء في تطوير أول لعبة للهاتف المحمول!

قم بتشغيل Xcode وانقر فوق "إنشاء مشروع Xcode جديد".

انقر على "لعبة" القالب.

أدخل اسم "Snake" (أو ما تريد) لعبتك. اختر اسم مؤسسة ، إذا كان لديك موقع ويب ، يمكنك إدخال ذلك للخلف (com.gavinshrader) ، أو يمكنك ببساطة استخدام اسمك كمعرّف. تأكد من ضبط اللغة على "Swift" وأن تقنية اللعبة هي "SpriteKit". قم بإلغاء تحديد خانات الاختيار 3 إذا كانت محددة.

انقر بزر الماوس الأيمن على "Actions.sks" وانتقل إلى المهملات. انتقل إلى GameScene.sks وانقر فوق نص "Hello World" ثم احذفه. انتقل إلى GameScene.swift وقم بإزالة جميع التعليمات البرمجية مسبقة الصنع بحيث يطابق ملفك الصورة أدناه.

قم بإنشاء ملف Swift جديد إما بالانتقال إلى File -> New File والنقر فوق Swift File ، أو بالنقر بزر الماوس الأيمن على مجلد المشروع ("Snake") واختيار ملف جديد. ابحث عن أيقونة Swift File الموضحة أدناه ، إذا لم يكن موجودًا ، اكتب "Swift" في شريط التصفية. أدخل اسم "GameManager" وتأكد من تحديد مشروعك ("Snake") ضمن الأهداف ، انقر فوق "إنشاء" لإنشاء ملف سريع جديد.

بناء قائمة اللعبة

قبل أن نبدأ الترميز ، تحقق للتأكد من تجميع مشروعك بعد التغييرات التي أجريتها في القسم الأخير. حدد جهازًا من قائمة المحاكاة ، وانقر فوق الزر الذي يوجد به "iPhone 6" ، ومن المحتمل أن يتم تسميته "Generic iOS device". إذا كنت ترغب في إجراء اختبار على جهاز مادي ، قم بتوصيل جهاز iPhone ، فامنح Xcode بضع لحظات ، ثم انقر فوق جهازك. بعد الانتهاء من هذا النقر على زر التشغيل الثلاثي. إذا اخترت جهازًا محاكيًا ، فستظهر هذه الشاشة:

إذا كانت الشاشة تعرض "Hello World" ، فاحرص على حذف التسمية من خلال الانتقال إلى GameScene.sks ، والنقر فوق الملصق ثم تحديد الحذف.

نحن مستعدون أخيرًا لبدء بناء اللعبة! عندما تبدأ لعبة ، فهي تساعد على تخطيط الشاشات مسبقًا. في هذه اللعبة ، سنبدأ بشاشة قائمة بسيطة تعرض عنوان / شعار اللعبة. سيؤدي زر التشغيل إلى إطلاق شاشة لعب مع منطقة ألعاب وتسمية اثنين للحصول على درجاتك الحالية وأفضل نتيجة. عندما تموت ، سيتم عرض شاشة اللعبة النهائية مع خيار للعب مرة أخرى.

من أجل تشغيل لعبتنا ، يتعين علينا أولاً بناء قائمة لبدء اللعبة. سنبدأ بكتابة التعليمات البرمجية لتهيئة قائمة بإضافة عنوان اللعبة وتسمية "أفضل نتيجة" وزر التشغيل. افتح ملف GameScene.swift وانسخ كل الشفرة من أسفل بحيث يتطابق ملفك مع الصورة (الشكل أ).

// 1
فار gameLogo: SKLabelNode!
فار bestScore: SKLabelNode!
فار playButton: SKShapeNode!
// 2
initializeMenu ()
// 3
func initializeMenu () {
    / / إنشاء عنوان اللعبة
    gameLogo = SKLabelNode (fontNamed: "ArialRoundedMTBold")
    gameLogo.zPosition = 1
    gameLogo.position = CGPoint (x: 0، y: (frame.size.height / 2) - 200)
    gameLogo.fontSize = 60
    gameLogo.text = "SNAKE"
    gameLogo.fontColor = SKColor.red
    self.addChild (gameLogo)
    / / إنشاء أفضل تسمية النتيجة
    bestScore = SKLabelNode (fontNamed: "ArialRoundedMTBold")
    bestScore.zPosition = 1
    bestScore.position = CGPoint (x: 0، y: gameLogo.position.y - 50)
    bestScore.fontSize = 40
    bestScore.text = "أفضل النتائج: 0"
    bestScore.fontColor = SKColor.white
    self.addChild (شهرية)
    // إنشاء زر التشغيل
    playButton = SKShapeNode ()
    playButton.name = "play_button"
    playButton.zPosition = 1
    playButton.position = CGPoint (x: 0، y: (frame.size.height / -2) + 200)
    playButton.fillColor = SKColor.cyan
    واسمحوا topCorner = CGPoint (x: -50 ، y: 50)
    اسمحوا bottomCorner = CGPoint (x: -50 ، y: -50)
    اسمحوا الأوسط = CGPoint (س: 50 ، ص: 0)
    دع المسار = CGMutablePath ()
    path.addLine (إلى: topCorner)
    path.addLines (بين: [topCorner، bottomCorner، middle])
    playButton.path = المسار
    self.addChild (playButton)
}
الشكل أ

قم بتجميع الكود الخاص بك وتحقق من أن جهازك يعرض الصورة من أعلى. إليك شرح لما يجري هنا ، قد يبدو هذا كجدار الشفرة ، لكن من السهل فهمه عند كسره.

  • 1: نقوم بإنشاء متغيرات للشعارات / الأزرار. تعني كلمة "!" بعد اسم المتغير أنه يجب علينا تهيئة المتغيرات ، فلا يمكن أن تكون فارغة أو "لا شيء".
  • 2: نحن نسمي وظيفة "initializeMenu ()" بمجرد تحميل طريقة عرض اللعبة. didMove (إلى: عرض: SKView) هي الوظيفة التي يتم استدعاؤها بمجرد تحميل GameScene.
  • 3: هذه هي وظيفة intializeMenu () التي كتبناها لإنشاء كائنات القائمة.
  • 4/5/6: قم بإنشاء الكائنات وإضافة إلى GameScene عن طريق استدعاء "self.addChild ()".
  • 7: اخترت استخدام SKShapeNodes لهذا المشروع بسبب بساطته ، وهذا بديل لإنشاء الرسومات الخاصة بك في محرر الصور. ينشئ سطر التعليمات البرمجية هذا مسارًا في شكل مثلث. يرجى ملاحظة أنه إذا كنت تخطط لبناء ونشر تطبيق ، فيجب عليك استخدام SKSpriteNodes لتحميل صورة قمت بإنشائها ، يمكن أن تتسبب ShapeNodes في مشاكل في الأداء عند استخدامها بكميات كبيرة حيث يتم رسمها ديناميكيًا مرة واحدة لكل إطار.
  • 8: اضبط المسار الثلاثي الذي أنشأناه على sprite playButton وأضفه إلى GameScene.

لعب اللعبة

الآن وبعد أن أصبح لدينا إعداد قائمة بسيطة ، فلنبدأ تشغيل زر التشغيل. انتقل أولاً إلى ملف GameManager.swift واستبدل كل الشفرة بهذا بحيث يطابق الصورة أدناه (الشكل ب).

استيراد SpriteKit
فئة GameManager {
}
الشكل ب

انسخ الرمز أدناه في ملف GameScene.swift بحيث يطابق الصورة أدناه (الشكل C).

// 1
لعبة فار: GameManager!
// 2
game = GameManager ()
// 3
overcide func touchesBegan (_ touches: Set  ، مع الحدث: UIEvent؟) {
    للمس في اللمسات
        اسمح للموقع = touch.location (في: الذات)
        دع touchedNode = self.nodes (في: الموقع)
        للعقدة في touchedNode {
            إذا node.name == "play_button" {
                بدء اللعبة()
            }
        }
    }
}
// 4
func startGame () {
    طباعة ("بدء اللعبة")
}
الشكل ج
  • 1: تهيئة كائن GameManager. المزيد حول هذا الموضوع لاحقًا ... سيؤدي ذلك إلى الاحتفاظ ببيانات النقاط وإدارة حركة اللاعب.
  • 2: تعيين متغير اللعبة إلى كائن GameManager () جديد.
  • 3: يطلق على هذه اللعبة مشغل اللعبة في كل مرة يلمس فيها المستخدم الشاشة. تذكر أن زر التشغيل الذي أنشأناه سابقًا له اسم "play_button". باستخدام الاسم ، يمكننا التحقق مما إذا كان المستخدم قد لمس SpriteNode باسم "play_button" ، وبمجرد حدوث ذلك ، فإننا نسمي وظيفة startGame () من النقطة النقطية 4.
  • 4: هذه الوظيفة تبدأ اللعبة.

تأكد من أن الشفرة تعمل بشكل صحيح عن طريق تشغيل التطبيق الخاص بك والنقر فوق زر التشغيل الثلاثي. إذا تم قياس اللمسات بشكل صحيح ، فيجب أن تعرض وحدة التحكم "بدء اللعبة" كما هو موضح في الصورة أدناه (الشكل د).

الشكل د

إذا لم تظهر وحدة التحكم الخاصة بك ، فانتقل إلى الشريط العلوي وانقر فوق "مساعدة" ، في شريط البحث ، اكتب "وحدة التحكم" ، ثم انقر فوق "Debug Area> Activate Console". لدينا الآن نظام قائمة عمل وزر تشغيل ، حيث يمكننا حقًا البدء في الاستمتاع ببعض المرح.

تحميل لعبة عرض

إذن لدينا الآن زر تشغيل يمكنه تشغيل وظيفة ، فما الذي يجب علينا فعله؟ لإظهار عرض اللعبة ، علينا أولاً إخفاء أزرار القائمة. أضف سطر التعليمات البرمجية هذا لإخفاء أزرار القائمة باستخدام رسم متحرك بسيط. يجب أن يتطابق رمزك مع الصورة أدناه (الشكل E).

//ابدأ اللعبة
func startGame () {
    طباعة ("بدء اللعبة")
    // 1
    gameLogo.run (SKAction.move (بواسطة: CGVector (dx: -50 ، dy: 600) ، المدة: 0.5)) {
    self.gameLogo.isHidden = صحيح
    }
    // 2
    playButton.run (SKAction.scale (إلى: 0 ، المدة: 0.3)) {
        self.playButton.isHidden = صحيح
    }
    // 3
    اسمحوا bottomCorner = CGPoint (x: 0 ، y: (frame.size.height / -2) + 20)
    bestScore.run (SKAction.move (إلى: bottomCorner ، المدة: 0.4))
}
الشكل هالشكل و
  • 1: حرك gameLogo خارج الشاشة ثم أخفيها عن الأنظار. يتم تشغيل الأقواس بعد SKAction بمجرد اكتمال الإجراء. على سبيل المثال ، إذا قمنا بتشغيل SKAction لمدة 10 ، فسيتم تشغيل الرمز الموجود داخل القوس بعد 10 ثوانٍ. هنا مثال:
exampleNode.run (SKAction.move (بواسطة: CGVector (dx: 0 ، dy: 0) ، المدة: 10) {
    طباعة ("وصلت بعد 10 ثوانٍ")
}
  • 2: قم بتوسيع playButton إلى 0 ؛ هذا الإجراء يتقلص الزر ثم يخفيه عن الأنظار.
  • 3: انقل ملصق bestScore إلى أسفل الشاشة.

يجب أن تتصرف القائمة الخاصة بك الآن مثل هذا gif (الشكل F) عند النقر فوق زر التشغيل!

الآن سنبدأ في تصميم جزء "الثعبان" الفعلي من هذه اللعبة ، ابدأ من خلال إضافة سطور التعليمات البرمجية هذه بحيث يتطابق رمزك مع الصورة أدناه (الشكل ز).

// 1
var currentScore: SKLabelNode!
var playerPositions: [(Int، ​​Int)] = []
فار gameBG: SKShapeNode!
var gameArray: [(node: SKShapeNode، x: Int، y: Int)] = []
// 2
initializeGameView ()
// 3
func privateizeGameView () {
    // 4
    currentScore = SKLabelNode (fontNamed: "ArialRoundedMTBold")
    currentScore.zPosition = 1
    currentScore.position = CGPoint (x: 0، y: (frame.size.height / -2) + 60)
    currentScore.fontSize = 40
    currentScore.isHidden = صحيح
    currentScore.text = "Score: 0"
    currentScore.fontColor = SKColor.white
    self.addChild (currentScore)
    // 5
    دع العرض = frame.size.width - 200
    اسمح للارتفاع = frame.size.height - 300
    اسمحوا rect = CGRect (س: - عرض / 2 ، ص: الطول / 2 ، العرض: العرض ، الارتفاع: الارتفاع)
    gameBG = SKShapeNode (rect: rect، cornerRadius: 0.02)
    gameBG.fillColor = SKColor.darkGray
    gameBG.zPosition = 2
    gameBG.isHidden = صحيح
    self.addChild (gameBG)
    // 6
    createGameBoard (العرض: العرض ، الارتفاع: الارتفاع)
}
الشكل زالشكل ز
  • 1: متغيرات جديدة! نحن بصدد إنشاء علامة لإظهار النتيجة الحالية ، ومجموعة من جميع المواقف التي يتمتع بها "الأفعى" أو اللاعب حاليًا ، وخلفية لعرض لعبتنا ومجموعة لتتبع أوضاع كل خلية في عرض اللعبة.
  • 2: استدعاء دالة initializeGameView ().
  • 3: تهيئة عرض اللعبة.
  • 4: إضافة تسمية النتيجة الحالية إلى الشاشة ، يتم إخفاء هذا حتى نترك قائمتنا.
  • 5: قم بإنشاء ShapeNode لتمثيل منطقة لعبنا. هذا هو المكان الذي سيتحرك فيه الثعبان.
  • 6: إنشاء لوحة اللعبة. هذه الوظيفة تهيئة طن من الخلايا المربعة ويضيفها إلى لوحة اللعبة.

بعد ذلك ، نريد إنشاء مجموعة من الخلايا التي سنستخدمها لتقديم الثعبان والنقاط التي تظهر على الشاشة. قم بإنشاء دالة createGameBoard من الكود أدناه بحيث تتطابق مع الشكل H.

/ / إنشاء لوحة لعبة ، تهيئة مجموعة من الخلايا
func createGameBoard الخاص (العرض: كثافة العمليات ، الارتفاع: كثافة العمليات)
    دع cellWidth: CGFloat = 27.5
    دع numRows = 40
    دع numCols = 20
    var x = CGFloat (عرض / -2) + (cellWidth / 2)
    var y = CGFloat (ارتفاع / 2) - (cellWidth / 2)
    // حلقة من خلال الصفوف والأعمدة ، وخلق الخلايا
    لـ i في 0 ... numRows - 1 {
        لـ j في 0 ... numCols - 1 {
            دع cellNode = SKShapeNode (rectOf: CGSize (العرض: cellWidth ، الارتفاع: cellWidth))
            cellNode.strokeColor = SKColor.black
            cellNode.zPosition = 2
            cellNode.position = CGPoint (x: x، y: y)
            // أضف إلى مجموعة من الخلايا - ثم أضف إلى لوحة اللعبة
            gameArray.append ((العقدة: cellNode ، x: i ، y: j))
            gameBG.addChild (cellNode)
            // تكرار س
            س + = cellWidth
        }
        / / إعادة تعيين x ، وتكرار ذ
        س = CGFloat (العرض / -2) + (cellWidth / 2)
        ص - = عرض الخلية
    }
}
الشكل ح

يجب أن يتطابق الرمز الخاص بك مع الرمز الوارد أعلاه ، وعند تشغيل لعبتك ، لن يظهر شيء قد تغير. إذا كنت ترغب في رؤية لوحة اللعبة كما هو موضح في لقطة شاشة simulator أعلاه ، فأضف الكود التالي إلى وظيفة لعبة البداية حتى تتوافق مع الشكل الأول.

bestScore.run (SKAction.move (إلى: bottomCorner ، المدة: 0.4)) {
    self.gameBG.setScale (0)
self.currentScore.setScale (0)
self.gameBG.isHidden = false
self.currentScore.isHidden = false
self.gameBG.run (SKAction.scale (إلى: 1 ، المدة: 0.4))
self.currentScore.run (SKAction.scale (إلى: 1 ، المدة: 0.4))
}

شرح موجز لطريقة createGameBoard قبل أن ننتقل. تستمر هذه الطريقة في 40 صفًا و 20 عمودًا ، ولكل موضع صف / عمود ، نقوم بإنشاء مربع مربع جديد أو "cellNode" وإضافة هذا إلى المشهد. نضيف أيضًا هذه cellNode إلى صفيف "gameArray" حتى نتمكن من تحديد نقطة صف وعمود في الخلية المناسبة بسهولة.

الشكل الأول - يعرض لوحة لعبة جديدة!

إنشاء مثيل لعبة

لدينا الآن زر التشغيل ، صندوق مليء بالمربعات الصغيرة وبعض الملصقات. كيف يمكننا تحويل هذا إلى لعبة ممتعة بالفعل للعب؟ أولاً ، سنحتاج إلى كائن لتتبع موقع "الثعبان" على الشاشة حتى نتمكن من التنقل. افتح فئة GameManager.swift وقم بإنشاء الطرق التالية. أضف هذا التغيير أيضًا (// 1) في وظيفة didMove (للعرض: SKView) في GameScene.swift بحيث يتطابق رمزك مع الشكل J.

// 1 - GameScene.swift
game = GameManager (مشهد: الذات)
// 2 - GameManager.swift
فئة GameManager {
    
    فار المشهد: GameScene!
    الحرف الأول (المشهد: GameScene) {
        المشهد الذاتي = المشهد
    }
}
الشكل ي

عن طريق إجراء هذه التغييرات ، نقول إن GameManager يجب أن يحتوي على إشارة إلى فئة GameScene بمجرد أن تتم تهيئتها. الآن يمكن لفئة GameManager التواصل مع GameScene عن طريق استدعاء scene.method_name. على سبيل المثال ، يمكن تشغيل scene.startGame () وظيفة بدء اللعبة من داخل عنصر التحكم في فئة GameManager.

نحن الآن على استعداد لتحميل اللاعب إلى GameView. أولاً قم بإضافة مقتطف الشفرة التالي في ملف GameScene.swift الخاص بك في طريقة startGame () داخل الأقواس الموجودة في bestScore.run () {} ستقوم هذه الطريقة باستدعاء دالة initGame بمجرد انتهاء تسمية bestScore من SKAction.

//رمز جديد
self.game.initGame ()
الشكل ك

انتقل الآن إلى GameManager.swift وأضف الطرق التالية أسفل طريقة init (مشهد: GameScene) بحيث يتطابق رمزك مع الشكل L.

// 1
func initGame () {
    // بدء موقف اللاعب
    scene.playerPositions.append ((10 ، 10))
    scene.playerPositions.append ((10 ، 11))
    scene.playerPositions.append ((10 ، 12))
    renderChange ()
}
// 2
func renderChange () {
    لـ (عقدة ، س ، ص) في scene.gameArray {
        إذا كانت تحتوي على (a: scene.playerPositions ، v: (x، y)) {
            node.fillColor = SKColor.cyan
        } آخر {
            node.fillColor = SKColor.clear
        }
    }
}
// 3
يحتوي func (a: [(Int، ​​Int)]، v: (Int، ​​Int)) -> Bool {
    دع (c1، c2) = v
    لـ (v1 ، v2) في {if v1 == c1 && v2 == c2 {return true}}
    عودة كاذبة
}
الشكل لام
  • 1: initGame () وظيفة. هذا يضيف 3 إحداثيات إلى مجموعة GameScene’sPositions ،
  • 2: renderChange () وظيفة. سوف نسمي هذه الطريقة في كل مرة ننقل فيها "الأفعى" أو اللاعب. هذا يجعل جميع المربعات الفارغة واضحة وجميع المربعات التي يوجد بها اللاعب سماويًا.
  • 3: هذه وظيفة بسيطة تتحقق من وجود tuple (بنية بيانات سريعة يمكن أن تحتوي على مجموعة من الأنواع في شكل (Int ، CGFloat ، Int ، String) ... إلخ) في مجموعة من tuples. تتحقق هذه الوظيفة من أن صفيف playerPositions يحتوي على الإحداثيات المدخلة من صفيف خلايا GameScene. هذه ليست بالضرورة الطريقة الأكثر فاعلية للقيام بالأشياء حيث أننا نتحقق من كل خلية أثناء كل تحديث. إذا كنت تريد تحدي نفسك ، فحاول تحديث الكود بحيث لا يعدل المربعات من صفيف playerPositions فقط!

تحريك اللاعب

الشكل م

لدينا الآن لاعبنا يتم عرضه على الشاشة والقدرة على تقديم أي عدد من المناصب. إذا قمت بإضافة المزيد من الإحداثيات إلى مجموعة playerPositions ، فسيتم تلوين المزيد من المربعات سماوي. خلال اللعبة ، نريد تحريك "الثعبان" باستمرار في اتجاه واحد حتى الضربات الشديدة على الشاشة لتغيير الاتجاهات. فيما يلي شبكة توضح الإحداثيات لنظام الشبكة الخاص بنا بحيث يمكنك بسهولة فهم كيفية عمل الإحداثيات خلف الكواليس (الشكل M).

كما ترى من خلال الملصقات الصغيرة البغيضة ، فإن الزاوية العلوية اليسرى هي 0،0 والزاوية اليمنى السفلية هي 39،19. هذا يعني أننا إذا أردنا تحريك لاعبنا في الاتجاهات يسارًا ، يمينًا ، لأعلى ولأسفل ، فنحن نفعل ذلك من خلال تطبيق الجبر الأساسي التالي (الشكل N).

الشكل ن

كما ترون ، تتطابق الاتجاهات يسار / يمين مع مستوى الإحداثيات النموذجي ؛ اليسار سلبي والحق إيجابي. ومع ذلك ، من أجل الصعود على مستوى الإحداثيات ، نريد تقليل y وللانتقال نريد زيادة y. هذا يرجع إلى حقيقة أن لدينا حلقة في وظيفة createGameBoard بدأت في الأعلى وانخفضت.

الآن بعد أن أدركت اتجاه اللوحة ، يمكنك تنفيذ طريقة تحريك اللاعب. إذا قمت بفتح ملف GameScene.swift ، فستلاحظ طريقة سهلة تسمى التحديث (_ currentTime: TimeInterval). في حلقة العرض ، يتم استدعاء وظيفة التحديث مرة واحدة في الثانية. هذا يعني أنه إذا كان تطبيقك يعمل بسرعة 60 إطارًا في الثانية ، فسيتم استدعاء الوظيفة 60 مرة في الثانية ، وإذا كانت اللعبة تعمل بسرعة 40 إطارًا في الثانية ، فسيطلق عليها 40 مرة في الثانية. داخل وظيفة التحديث الخاصة بك ، أضف سطر التعليمات البرمجية هذا بحيث يتطابق الرمز الخاص بك مع الشكل O.

// 1
game.update (الوقت: currentTime)
الشكل يا

بعد إضافة هذا الرمز ، يجب أن يظهر خطأ أحمر ، لإصلاح هذا الانتقال إلى ملف GameManager.swift الخاص بك وإضافة أسطر التعليمات البرمجية هذه بحيث يتطابق ملفك مع الشكل P.

// 1
فار nextTime: مزدوج؟
فار timeExtension: مزدوج = 1
// 2
تحديث func (الوقت: مزدوج) {
    إذا nextTime == لا شيء {
        nextTime = time + timeExtension
    } آخر {
        إذا كان الوقت> = nextTime! {
            nextTime = time + timeExtension
            طباعة (الوقت)
        }
    }
}
الشكل P

عند تشغيل التطبيق الخاص بك ، يجب أن تطبع وحدة التحكم مرة جديدة كل ثانية. في ما يلي عرض سريع لما تفعله هذه الشفرة.

  • 1: تهيئة اثنين من المتغيرات الجديدة. nextTime هو الفاصل الزمني nextTime الذي سنقوم بطباعة بيان على وحدة التحكم ، و timeExtension هو المدة التي سننتظرها بين كل طباعة (ثانية واحدة).
  • 2: تسمى وظيفة التحديث 60 مرة في الثانية ، نريد فقط تحديث وضع اللاعب مرة واحدة في الثانية حتى لا تكون اللعبة سريعة بشكل يبعث على السخرية. من أجل تحقيق ذلك ، نتحقق مما إذا كان قد تم تعيين nextTime. كما ترى من 1/1 ، تمت تهيئة nextTime لتكون قيمة اختيارية. ال " ؟ "بعد أن يخبر Double برنامج التحويل البرمجي السريع أننا نريد أن يكون nextTime مزدوجًا وأنه يمكن ضبطه على الصفر. عندما يتم استدعاء وظيفة التحديث ، نتحقق أولاً مما إذا كان قد تم تعيين nextTime ، وإذا لم يتم تعيينه ، فسنقوم بتعيينه على الوقت الحالي + timeText (1 ثانية). بمجرد حذف الوقت الحالي لـ "nextTime" ، فإننا نزيد nextTime بمقدار ثانية واحدة. تأخذ هذه الوظيفة الآن وظيفة تحديث غير منتظمة (حوالي 30-60 مرة / ثانية) وتنتج فقط إخراج مرة واحدة في الثانية.

لدينا الآن وظيفة يتم تشغيلها مرة واحدة في الثانية ، إذا كنت ترغب في زيادة سرعة لعبتك ، فما عليك سوى تقليل وقت الإيقاف إلى قيمة أكبر من 0 ، وإذا كنت تريد إبطاء لعبتك ، فقم بزيادة قيمة timeExtension. (ملاحظة: "1" == ثانية واحدة ل timeExtension).

نريد الآن نقل المشغل حول الشاشة ، وإضافة الكود التالي حتى يتطابق ملفك مع الشكل Q. وأيضًا ، قم بإزالة سطر "الطباعة (الوقت)" من وظيفة التحديث التي أنشأناها للتو في GameManager.swift ، سيؤدي هذا إلى إرسال بريد مزعج لديك وحدة التحكم وكانت مفيدة حقا فقط لاختبار صحة التعليمات البرمجية الخاصة بك.

// 1
var playerDirection: Int = 1
// 2
updatePlayerPosition ()
// 3
update func updatePlayerPosition () {
    // 4
    فار xChange = -1
    فار yChange = 0
    // 5
    تبديل لاعبالتوجيه {
        حالة 1:
            //اليسار
            xChange = -1
            yChange = 0
            استراحة
        الحالة 2:
            //فوق
            xChange = 0
            yChange = -1
            استراحة
        الحالة 3:
            //حق
            xChange = 1
            yChange = 0
            استراحة
        الحالة 4:
            //أسفل
            xChange = 0
            yChange = 1
            استراحة
        الافتراضي:
            استراحة
    }
    // 6
    if scene.playerPositions.count> 0 {
        فار start = scene.playerPositions.count - 1
        أثناء البدء> 0 {
            scene.playerPositions [start] = scene.playerPositions [start - 1]
            البدء - = 1
        }
        scene.playerPositions [0] = (scene.playerPositions [0] .0 + yChange، scene.playerPositions [0] .1 + xChange)
    }
    // 7
    renderChange ()
}
الشكل س

بعد إضافة هذا الرمز ، يجب أن تبدو لعبتك مثل صورة GIF من الشكل Q (اضبط playerDirection على 4 للحصول على نفس اتجاه الحركة). ظهر شيئان على الفور عندما كتبت هذا ؛ أولاً ، يتحرك الأفعى ببطء شديد ، وربما يتعين علينا زيادة سرعة اللعبة من ثانية واحدة إلى 1/2 أو 1/4 ثانية. ثانياً ، ماذا سنفعل عندما يضرب الأفعى جدارًا؟ في بعض إصدارات الثعبان ، يلتفت المشغل حول الشاشة ، وفي إصدارات أخرى ، يؤدي الاصطدام بجدار إلى الوفاة. تعجبني شكل التفاف الشاشة ، لذلك أعتقد أننا سنستخدم هذه الطريقة لهذه اللعبة. الآن شرح لهذا الرمز الذي كتبته للتو:

  • 1: قم بإنشاء متغير يتم استخدامه لتحديد اتجاه اللاعب الحالي. في الكود ، يتم ضبط المتغير على 1 ، في GIF في الشكل Q ، عيّن الاتجاه إلى 4. غير هذا المتغير لرؤية كل الاتجاهات المختلفة.
  • 2: لقد أزلنا الطباعة (الوقت) واستبدلناها بمكالمة بـ updatePlayerPosition () ، في هذا التكرار ندعو التحديث كل ثانية.
  • 3: هذه الطريقة تحريك اللاعب أو "الأفعى" حول الشاشة.
  • 4: اضبط المتغيرات لتحديد التغيير الذي يجب أن نجريه على x / y من مقدمة الثعبان.
  • 5: هذا عبارة عن بيان تبديل ، حيث يأخذ مدخلات playerPosition ويعدل متغيرات x / y وفقًا لما يتحرك فيه اللاعب لأعلى أو لأسفل أو لليسار أو لليمين.
  • 6: كتلة التعليمات البرمجية هذه تحريك المواضع للأمام في الصفيف. نريد تحريك الجزء الأمامي من الذيل في الاتجاه المناسب ثم نقل جميع الكتل الخلفية إلى الموضع التالي.
  • 7: تقديم التغييرات التي أجريناها على مجموعة من المواقف.

تزييف الثعبان حول الشاشة

لدينا الآن لاعب متحرك ، عمل رائع! أولاً ، سنرغب في زيادة سرعة اللعبة ، حيث يبدو أن الانتظار لمدة ثانية واحدة بطيئة للغاية لدرجة أنه لا يمكن أن يكون ممتعًا. هذا درس سوف تتعلمه في تصميم اللعبة ، وهناك الكثير من التغييرات والتبديل الطفيف التي سيتعين عليك إجراؤها لإضفاء لمسة مثالية على اللعبة. عندما أعمل في مشروع ، كثيراً ما أقضي معظم وقتي في إجراء تغييرات طفيفة لضبط الإحساس ، يجب عليك أن تتقن ميكانيكك من أجل بناء لعبة ممتعة ؛ بمجرد حصولك على ميكانيكا مثالية ، يمكنك العمل على إضافة إضافات رائعة مثل الجزيئات والأصوات.

تغيير المتغير timeExtension إلى 0.15 و ترجمة المشروع الخاص بك.

// 1 - GameManager.swift
فار timeExtension: مزدوج = 0.15

الآن يمكننا البدء في تزييف الثعبان حول الشاشة ، أضف التعليمات البرمجية التالية بحيث يتطابق مشروعك مع الشكل R. ملاحظة ، تتم إضافة هذا الرمز إلى وظيفة updatePlayerPosition () في GameManager.swift التي كتبناها للتو.

// 1
if scene.playerPositions.count> 0 {
    دع x = scene.playerPositions [0] .1
    دع y = scene.playerPositions [0] .0
    إذا كانت y> 40 {
        scene.playerPositions [0] .0 = 0
    } آخر إذا كانت y <0 {
        scene.playerPositions [0] .0 = 40
    } آخر إذا كانت x> 20 {
       scene.playerPositions [0] .1 = 0
    } آخر إذا كانت x <0 {
        scene.playerPositions [0] .1 = 20
    }
}
الشكل ص

عند تجميع تطبيقك ، يجب أن تتوافق شاشتك مع صورة GIF من الشكل R ، فقد استخدمت playerDirection 4 في gif. يمكن للثعبان الآن الالتفاف حول كل جانب من الشاشة.

  • 1: هذا الكود بسيط إلى حد ما ، فهو يتحقق مما إذا كان موضع رأس الأفعى قد تجاوز الجزء العلوي أو السفلي أو الجانب الأيسر أو الجانب الأيمن ثم نقل اللاعب إلى الجانب الآخر من الشاشة.

السيطرة على حركة الأفعى باستخدام الإيماءات السريعة

تأتي لعبتنا ، نحتاج الآن إلى طريقة للتحكم في اتجاه الثعبان. لتنفيذ ذلك ، سوف نستخدم إيماءات التمرير للتحرك إلى اليسار واليمين والأعلى والأسفل. أضف هذا الرمز إلى ملف GameScene.swift بحيث يطابق الشكل S.

// 1
اسمحوا swipeRight: UISwipeGestureRecognizer = UISwipeGestureRecognizer (الهدف: النفس ، العمل: #selector (swipeR))
swipeRight.direction = .right
view.addGestureRecognizer (swipeRight)
اسمحوا swipeLeft: UISwipeGestureRecognizer = UISwipeGestureRecognizer (الهدف: النفس ، العمل: #selector (swipeL))
swipeLeft.direction = .left
view.addGestureRecognizer (swipeLeft)
اسمحوا swipeUp: UISwipeGestureRecognizer = UISwipeGestureRecognizer (الهدف: النفس ، العمل: #selector (swipeU))
swipeUp.direction = .up
view.addGestureRecognizer (swipeUp)
اسمحوا swipeDown: UISwipeGestureRecognizer = UISwipeGestureRecognizer (الهدف: النفس ، العمل: #selector (swipeD))
swipeDown.direction = .down
view.addGestureRecognizer (swipeDown)
// 2
objc func swipeR () {
    طباعة ( "ص")
}
objc func swipeL () {
    طباعة ( "ل")
}
objc func swipeU () {
    طباعة ( "ش")
}
objc func swipeD () {
    طباعة ( "د")
}
الأرقام
  • 1: أضف إيماءات التمرير السريع إلى وظيفة didMove (للعرض: SKView).
  • 2: قم بإنشاء الوظائف التي يتم استدعاؤها عندما يدخل المستخدم في إيماءة انتقاد. "objc" قبل أن تنشئ الدالة دالة c ، فإن هذا ضروري ليتم استدعاؤها عبر #selector في UISwipeGestureRecognizer الأصلي.

اختبر الكود الخاص بك عن طريق ترجمة التطبيق الخاص بك ، ثم التمرير في الاتجاهات الأربعة ، يجب أن تطبع وحدة التحكم الخاصة بك الحرف المقابل لكل إيماءة تمرير. الآن بعد أن تم إعداد أدوات التعرف على الإيماءات ، نحتاج إلى تغيير اتجاه حركة اللاعب ، واستبدال عبارات الطباعة داخل وظائف التمرير السريع بهذا الرمز وإضافة رمز إلى GameManager.swift حتى يطابق مشروعك الشكل T.

// 1 - GameScene.swift
game.swipe (ID: 3)
game.swipe (ID: 1)
game.swipe (ID: 2)
game.swipe (ID: 4)
// 2 - GameManager.swift
انتقاد func (ID: Int) {
    if! (ID == 2 && playerDirection == 4) &&! (ID == 4 && playerDirection == 2) {
        if! (ID == 1 && playerDirection == 3) &&! (ID == 3 && playerDirection == 1) {
            playerDirection = المعرف
        }
    }
}
الشكل Tالشكل T
  • 1: بمجرد اكتشاف لفتة انتقاد يتم إخطار فئة gameManager.
  • 2: إذا كان التمرير السريع لا يتعارض مع الاتجاه الحالي ، فاضبط اتجاه اللاعب على إدخال التمرير السريع. إذا كنت تتحرك لأسفل ، فلا يمكنك التحرك للأعلى على الفور. إذا كنت تتحرك يسارًا ، فلا يمكنك التحرك فجأة لليمين. في بعض إصدارات الأفعى التي تؤدي خطوة غير صحيحة مثل هذه ، قد تؤدي إلى الوفاة ، ولكن في هذا الإصدار ، سنتجاهل ببساطة المدخلات الخارجية.

إضافة نقاط إلى اللعبة وضبط النتيجة

لدينا الآن نظام قائمة عمل يفتح لوحة ألعاب ومجموعة من الخلايا ومجموعة من أوضاع اللاعب ومشغل يمكنه التنقل في جميع أنحاء الشاشة والتشوه حول الحواف ومعرف انتقاد لعناصر التحكم. الآن يتعين علينا إضافة آلية تسجيل بحيث تكون اللعبة ممتعة. ستنشئ هذه الآلية نقاطًا عشوائية تؤدي إلى زيادة النتيجة وإطالة أثر "الأفعى" أو اللاعب.

الخطوة الأولى: توليد نقطة عشوائية وجعلها على الشاشة. أضف التعليمات البرمجية التالية إلى ملف GameScene.swift بحيث يتطابق مع الشكل U.

// 1
فار scorePos: CGPoint؟
الشكل U

انتقل الآن إلى ملف GameManager.swift وأضف الكود التالي بحيث يتطابق مع الشكل الخامس.

// 2
generateNewPoint ()
// 3
إنشاء وظيفة خاصةجديد () {
    اسمحوا randomX = CGFloat (arc4random_uniform (19))
    دع عشوائيًا = CGFloat (arc4random_uniform (39))
    scene.scorePos = CGPoint (x: randomX ، y: randomY)
}
// 4
if scene.scorePos! = nil {
    إذا Int ((scene.scorePos؟ .x)!) == y&& Int ((scene.scorePos؟ .y)!) == x {
        node.fillColor = SKColor.red
    }
}
الشكل الخامس

بعد تشغيل الكود الخاص بك ، يجب أن يظهر جهاز محاكاة مربع أحمر تم وضعه بشكل عشوائي.

  • 1: تهيئة متغير لموقف النتيجة عشوائية. ال " ؟ "يشير إلى أن هذا لا شيء (فارغ أو لم يتم تعيينه بعد) حتى نضبط المتغير لاحقًا.
  • 2: استدعاء الدالة داخل الدالة initGame () التي ستنشئ نقطة عشوائية جديدة.
  • 3: تنشئ هذه الوظيفة موقعًا عشوائيًا داخل حدود اللوحة (20/40) ، وتبدأ المصفوفات في العد عند 0 لذلك نحسب من 0 إلى 19 ومن 0 إلى 39 ، هذه صفيف 20 × 40.
  • 4: داخل حلقة التقديم ، نتحقق مما إذا كان موضع العقدة الحالية يتطابق مع النتيجة الموضوعة عشوائيًا ، وإذا كان لدينا تطابق ، فقم بتعيين اللون على اللون الأحمر. يمكنك تعديل اللون ليناسب ذوقك. المتغير الذي يحفظ موضع الدرجات هو CGPoint ، وهذا يعني أنه يتعين علينا التحقق من point.x و point.y ومقارنته بمواقع العقدين x و y الحاليين. لاحظ أن المواضع x / y يتم قلبها في صفيف العقد ، ولهذا السبب نقوم بمقارنة x == y و y == x.

نحتاج الآن إلى تعيين متغير يحمل درجة اللعبة الحالية ويقوم بتكرارها بمجرد أن يصل اللاعب إلى نقطة. عندما يضرب اللاعب نقطة ما ، يجب علينا إنشاء نقطة عشوائية جديدة وزيادة طول "ذيل" اللاعب.

أضف التعليمات البرمجية التالية إلى ملف GameManager.swift بحيث يطابق الشكل W.

// 1
var currentScore: Int = 0
// 2
checkForScore ()
// 3
func checkForScore الخاص () {
    if scene.scorePos! = nil {
        دع x = scene.playerPositions [0] .0
        دع y = scene.playerPositions [0] .1
        إذا Int ((scene.scorePos؟ .x)!) == y&& Int ((scene.scorePos؟ .y)!) == x {
            currentScore + = 1
            scene.currentScore.text = "Score: \ (currentScore)"
            generateNewPoint ()
         }
     }
}
// 4
بينما يحتوي على (a: scene.playerPositions ، v: (Int (randomX) ، Int (randomY))) {
    randomX = CGFloat (arc4random_uniform (19))
    randomY = CGFloat (arc4random_uniform (39))
}
الشكل ث
  • 1: تهيئة متغير لتتبع النتيجة الحالية في هذه اللعبة.
  • 2: استدعاء وظيفة checkForScore () داخل وظيفة التحديث ، وهذا ما يسمى في كل مرة يتحرك فيها اللاعب.
  • 3: تقوم هذه الوظيفة بالتحقق مما إذا كانت النتيجة قد تم تعيينها ، إذا كانت موجودة ، فتقوم بالتحقق من رأس الأفعى. إذا كان الأفعى يمس نقطة ثم يتم تكرار النتيجة ، يتم تحديث تسمية النص التي تظهر النتيجة ويتم إنشاء نقطة جديدة.
  • 4: لقد أضفت هذا الرمز إلى طريقة generNewPoint () لضمان عدم إنشاء نقطة داخل جسم الثعبان. نظرًا لتزايد طول الثعبان ، فمن المحتمل أن نواجه هذه المشكلة ، لذا يجب أن تعمل كتلة الشفرة هذه على حل هذه المشكلة.

عند تشغيل الكود ، ستلاحظ أن الوصول إلى نتيجة سيؤدي إلى إنشاء درجة جديدة على السبورة وتكرار تصنيف درجاتك. الآن علينا زيادة طول الثعبان بحيث تكون آليات لعب اللعبة أقرب إلى الاكتمال. يبدو أن هذا بسيط للغاية ، ببساطة أضف مقتطف الشفرة هذا إلى وظيفة checkForScore () بحيث يتطابق الرمز الخاص بك مع الشكل X.

scene.playerPositions.append (scene.playerPositions.last!)
scene.playerPositions.append (scene.playerPositions.last!)
scene.playerPositions.append (scene.playerPositions.last!)
الشكل العاشر

إنهاء اللعبة

نحتاج الآن إلى تطبيق طريقة تنهي اللعبة وتعود إلى نظام القائمة. في لعبة الأفعى ، تنتهي اللعبة بمجرد دخول اللاعب إلى ذيله. يمكننا تحقيق هذا التأثير من خلال تطبيق سطور التعليمات البرمجية التالية في ملف GameManager.swift. تأكد من تطابق الكود الخاص بك مع الشكل Y.

// 1
checkForDeath ()
// 2
func checkCor الخاص () {
    if scene.playerPositions.count> 0 {
        فار arrayOfPositions = scene.playerPositions
        دع headOfSnake = arrayOfPositions [0]
        arrayOfPositions.remove (في: 0)
        إذا كان يحتوي على (a: arrayOfPositions، v: headOfSnake) {
            playerDirection = 0
        }
    }
}
// 3
إذا كان playerDirection! = 0 {
    playerDirection = المعرف
}
// 4
الحالة 0:
    //ميت
    xChange = 0
    yChange = 0
    استراحة
الشكل صالشكل ص
  • 1: استدعاء دالة checkForDeath ().
  • 2: تحقق مما إذا كان رأس اللاعب قد اصطدم بأي من مواقع الذيل. إذا توفي اللاعب ، قم بتعيين playerDirection على 0.
الشكل Z
  • 3: إذا توفي اللاعب (playerDirection = 0) ، فلا تسمح بإيماءات التمرير الجديدة كمدخلات.
  • 4: أضف حالة جديدة في بيان التبديل في updatePlayerPosition () ، إذا تم ضبط playerDirection على 0 ، فلا تقم بتغيير موضع الرأس. هذا سيسمح لمواقف الذيل بإزالة نفسها ببطء عن الأنظار.

بعد تنفيذ هذه التغييرات البرمجية ، يجب أن يعمل تطبيقك كما هو الحال في تسجيل الشاشة (الشكل Z).

عندما يصطدم الثعبان بنفسه وقد انتهت اللعبة ، نحتاج الآن إلى بناء طريقة لإعادة تشغيل اللعبة وحفظ النتيجة على أنها أعلى الدرجات.

إعادة تشغيل اللعبة وتوفير بيانات درجة عالية

لقد بنينا الآن لعبة ثعبان العمل (بالنسبة للجزء الأكبر). الخطوات النهائية على مرمى البصر! نحتاج إلى طريقة لإعادة تشغيل اللعبة والعودة إلى القائمة ، كما نحتاج أيضًا إلى حفظ بيانات الدرجات العالية في الجهاز إذا كانت نتيجة هذه الجولة أفضل من أفضل درجاتك.

أولاً ، دعونا ننفذ طريقة تعود إلى القائمة بمجرد انتهاء الثعبان من الرسوم المتحركة الختامية. أضف التعليمات البرمجية التالية إلى ملف GameManager.swift بحيث يتطابق الرمز الخاص بك مع الشكل AA.

// 1
finishAnimation ()
// 2
انتهاء مهمة خاصة () {
    if playerDirection == 0 && scene.playerPositions.count> 0 {
        فار hasFinished = صحيح
        دع headOfSnake = scene.playerPositions [0]
        للموقف في scene.playerPositions {
            إذا headOfSnake! = موقف {
                hasFinished = false
            }
         }
     إذا انتهى الأمر {
        طباعة ("نهاية اللعبة")
        playerDirection = 4
        اكتمل // الرسوم المتحركة
        scene.scorePos = لا شيء
        scene.playerPositions.removeAll ()
        renderChange ()
        // العودة إلى القائمة
        scene.currentScore.run (SKAction.scale (إلى: 0 ، المدة: 0.4) {
        self.scene.currentScore.isHidden = صحيح
}
        scene.gameBG.run (SKAction.scale (إلى: 0 ، المدة: 0.4)) {
            self.scene.gameBG.isHidden = صحيح
            self.scene.gameLogo.isHidden = false
            self.scene.gameLogo.run (SKAction.move (إلى: CGPoint (x: 0، y: (self.scene.frame.size.height / 2) - 200) ، المدة: 0.5)) {
                 self.scene.playButton.isHidden = false
                 self.scene.playButton.run (SKAction.scale (إلى: 1 ، المدة: 0.3))
                 self.scene.bestScore.run (SKAction.move (إلى: CGPoint (x: 0، y: self.scene.gameLogo.position.y - 50) ، المدة: 0.3))
               }
          }
          }
     }
}
الشكل أأ

إليك شرح لهذه الطريقة:

  • 1: استدعاء دالة finishAnimation ().
  • 2: سوف تتحقق هذه الوظيفة من إكمال الرسوم المتحركة النهائية للثعبان عند إغلاقه في حد ذاته. عندما تتطابق جميع المناصب في مجموعة playerPositions مع بعضها البعض ، تقلصت الأفعى إلى مربع واحد. بعد حدوث ذلك ، قمنا بتعيين playerDirection إلى 4 (تم ضبطه مسبقًا على 0 مما يشير إلى الموت) ثم نعرض كائنات القائمة. نحن أيضًا نخفي تسمية حالية وعلامة gameBG (شبكة المربعات).

دعنا نضيف طريقة لحفظ الدرجة العالية للجهاز بحيث عندما يغلق التطبيق ، لن نفقد بيانات درجاتنا العالية. في الطريقة الجديدة (finishAnimation ()) كتبت للتو أضف سطر التعليمات البرمجية هذا بحيث يتطابق ملفك مع الشكل BB.

updateScore ()
الرقم BB

افتح الآن ملف AppDelegate.swift وأضف سطور التعليمات البرمجية التالية بحيث يتطابق مشروعك مع الشكل CC. يستخدم مقتطف الشفرة هذا UserDefaults لحفظ البيانات في ذاكرة جهازك. إذا كنت تخطط لبناء مشروع يحتوي على كميات هائلة من البيانات المخزنة ، فقد يتسبب ذلك في حدوث مشكلة ، ومع ذلك ، فإنه يعمل بشكل جيد على أشياء بسيطة مثل تبديل الإعدادات والمتغيرات.

دع الإعدادات الافتراضية = UserDefaults.standard
دع defaultValue = ["bestScore": 0]
defaults.register (الإعدادات الافتراضية: defaultValue)
الشكل CC

عد الآن إلى ملف GameManager.swift الخاص بك وقم بإنشاء الطريقة التالية بحيث يتطابق رمزك مع الشكل DD. يتحقق هذا الكود من التعليمات البرمجية ببساطة مما إذا كانت النتيجة قد حققت أفضل نتيجة وتحديثات وفقًا لذلك.

// 1
تحديث func الخاص () {
     if currentScore> UserDefaults.standard.integer (forKey: "bestScore") {
          UserDefaults.standard.set (currentScore ، forKey: "bestScore")
     }
     CurrentScore = 0
     scene.currentScore.text = "النتيجة: 0"
     scene.bestScore.text = "أفضل النتائج: \ (UserDefaults.standard.integer (forKey:" bestScore "))"
}
الرقم DD

افتح GameScene.swift وقم بتحرير وظيفة initializeMenu () بحيث يتطابق ملفك مع الشكل EE. يضمن ذلك أنه عند تحميل اللعبة ، يتم عرض أفضل نتيجة محفوظة بدلاً من 0.

bestScore.text = "أفضل نتيجة: \ (UserDefaults.standard.integer (forKey:" bestScore "))"
الشكل ه

بعد إضافة هذا الرمز الجديد ، سيتم حفظ درجاتك العالية في ذاكرة جهازك بمجرد إغلاق التطبيق.

إغلاق الأفكار

من أجل إزالة معلومات المطور في أسفل الشاشة ، افتح ملف GameViewController.swift وقم بتعيين view.showFPS و view.showsNodeCount إلى false.

لقد قمت الآن بإنشاء لعبة iPhone بالكامل من البداية! إليك مقطع فيديو يوضح المنتج النهائي.

إذا كنت تتمتع بالمشروع ، ففحص التحقق من تطبيق IOS الخاص بي إذا كان لديك أي مشاكل أو أسئلة فلا تتردد في مراسلتي عبر البريد الإلكتروني على shrader.gavin@gmail.com.

ما بناه اليوم بالكاد يخدش سطح التعقيد الذي يقدمه محرك ألعاب SpriteKit. في المستقبل ، أخطط للقيام بالدروس التعليمية التي تغطي الفيزياء ، وتصميم المستوى والرسوم المتحركة.