كيف تكتب أول لعبة Android في Java

مؤلف: John Stephens
تاريخ الخلق: 1 كانون الثاني 2021
تاريخ التحديث: 18 قد 2024
Anonim
How to write your first Android game in Java
فيديو: How to write your first Android game in Java

المحتوى


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

اعداد

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


أول شيء تريد القيام به هو التغيير AppCompatActivity إلى نشاط. هذا يعني أننا لن نستخدم ميزات شريط الإجراءات.

وبالمثل ، نريد أيضًا أن نجعل لعبتنا ممتلئة. أضف التعليمات البرمجية التالية إلى onCreate () قبل استدعاء setContentView ():

getWindow (). setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN، WindowManager.LayoutParams.FLAG_FULLSCREEN)؛ this.requestWindowFeature (Window.FEATURE_NO_TITLE)؛

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

خلق طريقة لعبتك

قد تستخدم للتطبيقات التي تستخدم برنامج نصي XML لتعريف تخطيط طرق العرض مثل الأزرار والصور والتسميات. هذا هو ما الخط setContentView يفعل بالنسبة لنا.


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

لذلك غيّر هذا السطر ليصبح نصه كما يلي:

setContentView (GameView جديد (هذا))

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

لذلك انقر بزر الماوس الأيمن على اسم الحزمة في التسلسل الهرمي الخاص بك على اليسار واختر جديد> الصف. سيتم تقديم نافذة الآن لإنشاء فصلك وستقوم بالاتصال به GameView. تحت SuperClass ، اكتب: android.view.SurfaceView مما يعني أن الفصل سيرث الأساليب - قدراته - من SurfaceView.

في المربع (الواجهات) ، ستكتب android.view.SurfaceHolder.Callback. كما هو الحال مع أي فئة ، نحتاج الآن إلى إنشاء مُنشئ لدينا. استخدم هذا الكود:

مؤشر ترابط MainThread الخاص ؛ GameView العامة (سياق السياق) {super (سياق)؛ . getHolder () addCallback (هذا)؛ }

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

بإضافة Callback ، يمكننا اعتراض الأحداث.

الآن تجاوز بعض الأساليب:

تضمين التغريدة

هذه تسمح لنا أساسًا بتجاوز (وبالتالي الاسم) الأساليب في الطبقة الفائقة (SurfaceView). يجب ألا يكون لديك الآن تسطير أحمر أكثر في التعليمات البرمجية الخاصة بك. لطيف.

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

خلق المواضيع

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

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

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

يجب أن يبدو الأمر كاملاً كما يلي:

الطبقة العامة MainThread يمتد الموضوع {private SurfaceHolder surfaceHolder؛ GameView gameView الخاصة ؛ MainThread public (SurfaceHolder surfaceHolder، GameView gameView) {super ()؛ this.surfaceHolder = surfaceHolder؛ this.gameView = gameView؛ }}

Schweet. لدينا الآن GameView وخيط!

خلق حلقة اللعبة

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

في الوقت الحالي ، ما زلنا في موضوع الرئيسي الصف ، ونحن في طريقنا لتجاوز طريقة من الطبقة العليا. هذا هو واحد يركض.

وغني عن شيء مثل هذا:

Override public void run () {while (running) {canvas = null؛ جرب {canvas = this.surfaceHolder.lockCanvas ()؛ متزامن (surfaceHolder) {this.gameView.update () ؛ this.gameView.draw (قماش)؛ }} catch (Exception e) {} أخيرًا {if (canvas! = null) {try {surfaceHolder.unlockCanvasAndPost (canvas)؛ } catch (Exception e) {e.printStackTrace ()؛ }}}}}

سترى الكثير من التسطير ، لذلك نحتاج إلى إضافة المزيد من المتغيرات والمراجع. عد إلى الأعلى ثم أضف:

SurfaceHolder الخاصة GameView gameView الخاصة ؛ تشغيل منطقي خاص ؛ ثابت قماش قماش العامة.

تذكر لاستيراد قماش. قماش هو الشيء الذي سنستفيد منه بالفعل. بالنسبة لـ "lockCanvas" ، هذا مهم لأنه يجمد القماش بشكل أساسي للسماح لنا بالاعتماد عليه. هذا أمر مهم لأنه بخلاف ذلك ، يمكن أن يكون لديك عدة خيوط تحاول الاعتماد عليها مرة واحدة. فقط أعرف أنه من أجل تحرير اللوحة القماشية ، يجب عليك أولاً قفل قماش.

يعد التحديث طريقة سننشئها ، وهذا هو المكان الذي ستحدث فيه الأشياء الممتعة لاحقًا.

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

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

public void setRunning (منطقية isRunning) {running = isRunning؛ }

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

تحديث الفراغ العام () {}

نحن بحاجة أيضا إلى بداية الخيط! سنقوم بهذا في منطقتنا surfaceCreated طريقة:

Override public void surfaceCreated (حامل SurfaceHolder) {thread.setRunning (true)؛ thread.start ()؛ }

نحتاج أيضًا إلى إيقاف الخيط عند تدمير السطح. كما كنت قد خمنت ، ونحن نتعامل مع هذا في surfaceDestroyed طريقة. ولكن نظرًا لأنه قد يستغرق بالفعل عدة محاولات لإيقاف سلسلة الرسائل ، سنضعها في حلقة ونستخدمها محاولة و قبض على مرة أخرى. مثل ذلك:

Override public void surfaceDestroyed (حامل SurfaceHolder) {boolean retry = true؛ بينما (أعد المحاولة) {try {thread.setRunning (false) ؛ thread.join ()؛ } catch (InterruptedException e) {e.printStackTrace ()؛ } إعادة المحاولة = خطأ ؛ }}

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

مؤشر ترابط = MainThread (getHolder () ، هذا) ؛ setFocusable (صحيح)؛

الآن انت تستطيع أخيرا في الواقع اختبار هذا الشيء! هذا صحيح ، انقر فوق "تشغيل" و ينبغي فعلا تشغيل دون أي أخطاء. الاستعداد ليكون في مهب!

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

القيام الرسومات

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

Override public void Draw (Canvas canvas) {super.draw (canvas)؛ if (canvas! = null) {canvas.drawColor (Color.WHITE)؛ الطلاء الطلاء = الطلاء الجديد () ؛ paint.setColor (Color.rgb (250، 0، 0))؛ canvas.drawRect (100 ، 100 ، 200 ، 200 ، الطلاء) ؛ }}

شغِّل هذا ويجب أن يكون لديك الآن مربع أحمر جميل في أعلى يسار شاشة بيضاء. هذا بالتأكيد تحسن.

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

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

سيقوم هذا الفصل برسم نقش على قماش اللوحة وسيبدو هكذا

CharacterSprite فئة خاصة صورة نقطية خاصة؛ CharacterSprite العامة (صورة نقطية bmp) {image = bmp؛ } رسم الفراغ العام (Canvas canvas) {canvas.drawBitmap (الصورة ، 100 ، 100 ، فارغة) ؛ }}

الآن لاستخدام هذا ، ستحتاج إلى تحميل الصورة النقطية أولاً ثم استدعاء الفئة من GameView. إضافة إشارة إلى CharacterSprite characterSprite ثم في surfaceCreated الطريقة ، أضف السطر:

characterSprite = new CharacterSprite (BitmapFactory.decodeResource (getResources ()، R.drawable.avdgreen))؛

كما ترون ، يتم تخزين الصورة النقطية التي نزّلها في الموارد وتسمى avdgreen (كانت من لعبة سابقة). الآن كل ما عليك القيام به هو تمرير تلك الصورة النقطية إلى الفئة الجديدة في رسم طريقة مع:

characterSprite.draw (قماش)؛

الآن انقر فوق "تشغيل" وسترى الرسم الخاص بك يظهر على الشاشة! هذا هو BeeBoo. اعتدت رسمه في الكتب المدرسية.

ماذا لو أردنا أن نجعل هذا الرجل الصغير يتحرك؟ بسيطة: نقوم فقط بإنشاء متغيرات x و y لمواقعه ثم تغيير هذه القيم في تحديث طريقة.

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

ذ ++؛

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

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

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

تحديث الفراغ العام () {x + = xVelocity؛ y + = yVelocity ؛ إذا ((x & gt؛ screenWidth - image.getWidth ()) || (x & lt؛ 0)) {xVelocity = xVelocity * -1؛ } if ((y & gt؛ screenHeight - image.getHeight ()) || (y & lt؛ 0)) {yVelocity = yVelocity * -1؛ }}

ستحتاج أيضًا إلى تحديد هذه المتغيرات:

كثافة العمليات الخاصة xVelocity = 10 ؛ كثافة العمليات الخاصة yVelocity = 5 ؛ كثافة العمليات الخاصة screenWidth = Resources.getSystem (). getDisplayMetrics (). كثافة العمليات الخاصة screenHeight = Resources.getSystem (). getDisplayMetrics ().

الاقوي

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

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

سأقوم أيضًا بتحديث يركض الطريقة من أجل قياس المدة التي تستغرقها كل حلقة لعبة ثم إلى وقفة حلقة اللعبة تلك مؤقتًا إذا كانت متقدمة على targetFPS. سنقوم بعد ذلك بحساب المدة الآن استغرق ثم طباعة ذلك حتى نتمكن من رؤيته في السجل.

Override public void run () {long startTime؛ وقت طويلميليس. وقت طويل إجمالي وقت طويل = 0 ؛ int frameCount = 0 ؛ وقت طويل المستهدف = 1000 / targetFPS ؛ بينما (قيد التشغيل) {startTime = System.nanoTime () ؛ قماش = لاغ جرب {canvas = this.surfaceHolder.lockCanvas ()؛ متزامن (surfaceHolder) {this.gameView.update () ؛ this.gameView.draw (قماش)؛ }} catch (Exception e) {} أخيرًا {if (canvas! = null) {try {surfaceHolder.unlockCanvasAndPost (canvas)؛ } catch (Exception e) {e.printStackTrace ()؛ }}} timeMillis = (System.nanoTime () - startTime) / 1000000؛ waitTime = targetTime - timeMillis؛ جرب {this.sleep (waitTime) ؛ } catch (استثناء e) {} totalTime + = System.nanoTime () - startTime؛ frameCount ++؛ if (frameCount == targetFPS) {averageFPS = 1000 / ((totalTime / frameCount) / 1000000) ؛ frameCount = 0 ؛ totalTime = 0 ؛ System.out.println (averageFPS)؛ }}}

تحاول لعبتنا الآن قفل FPS على 60 ، ويجب أن تجد أنها تقيس بشكل عام 58-62 FPS ثابتة على جهاز حديث. على المحاكي رغم أنك قد تحصل على نتيجة مختلفة.

حاول تغيير ذلك من 60 إلى 30 وشاهد ما يحدث. اللعبة تبطئ و ينبغي الآن قراءة 30 في logcat الخاص بك.

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

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

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

التالىدليل المبتدئين لجافا

14 مارس 2018 14 مارس 2018تبدأ جميع التفاعلات مع مساعد Google بميزة "موافق" أو "Google" أو "مهلا" ، أو "اكتشاف الكلمات الرئيسية من Google"....

مساعد Google قوي جدًا بالفعل ، حيث يقدم دعمًا شاملاً للصوت والنص. لكن شركة البحث تحاول جعل مساعدها الافتراضي أكثر سهولة من خلال ميزة Action Block.في أحد التدوينات التي تعلن عن الميزة ، لاحظت Google أن...

المواد شعبية