כותב את משחק האנדרואיד הראשון שלך באמצעות Corona SDK

מְחַבֵּר: Randy Alexander
תאריך הבריאה: 1 אַפּרִיל 2021
תאריך עדכון: 26 יוני 2024
Anonim
The Great Gildersleeve: Gildy’s New Car / Leroy Has the Flu / Gildy Needs a Hobby
וִידֵאוֹ: The Great Gildersleeve: Gildy’s New Car / Leroy Has the Flu / Gildy Needs a Hobby

תוֹכֶן


הקטגוריה הפופולרית ביותר בחנות Google Play הייתה תמיד משחקים. למרות שכולנו ככל הנראה משתמשים באפליקציות פרודוקטיביות מרכזיות כמו דפדפן אינטרנט, לקוח דוא"ל ואפליקציית מסרים מיידיים, המשחקים עדיין נשארים חלק חשוב מחוויית המובייל. לכן אין זה מפתיע שרבים מהאנשים שרוצים ללמוד להתפתח לאנדרואיד רוצים להתחיל לעשות משחק. כמו כן, בואו נהיה כנים, כתיבת משחק היא עומס שלם יותר כיף מפיתוח אפליקציית פריון!

השפה הרשמית של אנדרואיד היא ג'אווה וסביבת הפיתוח הרשמית היא סטודיו אנדרואיד. אם אתה רוצה לבדוק Java, אני מציע את הדרכת היסודות של Java שלנו, ואם אתה רוצה ללמוד כיצד לכתוב אפליקציה באמצעות Android Studio, אני מציע לך לבדוק את ההדרכה שלנו בנושא כתיבת אפליקציית Android הראשונה שלך. עם זאת אולפני Java ו- Android אינם הדרכים היחידות להתפתח עבור אנדרואיד. תוכל למצוא סקירה כללית של השפות וה- SDK הזמינים במדריך שלנו: אני רוצה לפתח אפליקציות אנדרואיד - אילו שפות עלי ללמוד?

אחד ה- SDK המצוינים במדריך שפות התכנות הוא Corona, SDK של צד שלישי המיועד בעיקר לכתיבת משחקים. במקום ג'אווה קורונה משתמשת בלואה, שפת תסריט מהירה שקל ללמוד ועם זאת עוצמתית. עם זאת, קורונה אינה ה- SDK המשחקים הנייד היחיד שמשתמש בלואה, דוגמאות ידועות אחרות כוללות Cocos2d-X, Marmalade ו- Gideros.


הורד והתקן

כדי להתחיל עם קורונה תצטרך להוריד ולהתקין את ה- SDK. עבור לאתר קורונה ולחץ על כפתור ההורדה. יהיה עליך ליצור חשבון (שהוא בחינם) לפני שתוכל להוריד את הערכה. אם אתה רוצה לבנות קובץ .apk בפועל ולא רק להריץ את התוכנית שלך באמולטור, תצטרך להתקין את Java 7, עם זאת לא תצטרך להתקין את SDK אנדרואיד. כדי להתקין את ערכת הפיתוח של Java 7 היכנס לאתר של אורקל, חפש את החלק שנקרא "Java SE Kit Kit 7u79" והורד את הגרסה למחשב האישי שלך.

לאחר התקנת קורונה, עליכם להפעיל אותה. זהו תהליך חד פעמי, שהוא בחינם. הפעל את סימולטור קורונה והסכים לרישיון. הזן את כתובת הדוא"ל והסיסמה שבה השתמשת לצורך ההורדה ולחץ על כניסה.

התחלת הפרויקט

מתוך סימולטור Corona לחץ על "פרויקט חדש." הזן שם לאפליקציה שלך בשדה "שם היישום:" והשאיר את שאר ההגדרות בברירת המחדל שלהם. לחץ על "אישור."

כעת יופיעו שלושה חלונות. השניים הראשונים הם סימולטור קורונה והתפוקה הסימולרית של קורונה. קורונה תפתח גם חלון סייר קבצים המציג את הקבצים לפרויקט שלך.


רוב הקבצים (כ 23 מהם) בספריית הפרוייקט מיועדים לסמל היישום! הקובץ החשוב ביותר עבורנו כרגע הוא main.luaמכיוון שכאן נכתוב את הקוד עבור האפליקציה שלנו.

מבוא ללואה

לפני שנתחיל לכתוב את הקוד, עלינו לעשות סיור במתן שריקה בלואה. מתורגמן הלואה (זכור שזו שפת תסריטים, לא שפה מורכבת) זמין עבור Windows, OS X ו- Linux. עם זאת זה מובנה לקורונה, כך שכרגע אינך צריך להתקין שום דבר נוסף. הדרך הקלה ביותר לשחק עם לואה היא להשתמש בהדגמה חיה מקוונת.

אתה יכול למצוא הרבה הדרכות טובות על לואה באופן מקוון וכדאי להעיף מבט במדריך ההפניה של לואה, תכנות בלואה, לימוד הליאו. הדרכה ומדריך הצגה לואה.

להלן תוכנית קטנה של לואה שתראה לכם כמה מתכונות המפתח של לואה:

פונקציה מקומית doubleIt (x) להחזיר x * 2 סוף עבור i = 1,10,1 לעשות x = doubleIt (i) אם (x == 10) ואז להדפיס ("עשרה") אחר להדפיס (doubleIt (i)) סוף סוף

הקוד שלמעלה מציג שלוש קונסטרוקציות חשובות של לואה: פונקציות, לולאות, ואם הצהרות. הפונקציה כפול () זה פשוט מאוד, זה רק מכפיל את הפרמטר שהועבר איקס.

הקוד העיקרי הוא א ל לולאה מ 1 עד 10. זה מתקשר כפול () עבור כל איטרציה. אם ערך ההחזר הוא 10 (כלומר מתי אני הוא 5) ואז הקוד מדפיס את "עשר" אחרת הוא פשוט מדפיס את התוצאה של כפול ().

אם יש לך חווית קידוד כלשהי, קוד הדוגמה אמור להיות קל מספיק למעקב. אם אתם מחפשים ללמוד תכנות בסיסית אז אני מציע שתשתמש בחלק מהמשאבים המקושרים למעלה כדי לחדד את כישוריכם.

כותב את המשחק

כתיבת תוכניות בסיסיות בקורונה היא פשוטה. אתה צריך לדאוג רק לקובץ אחד, main.lua, ותן לקורונה לעשות את כל ההרמה הכבדה. המשחק שאנחנו הולכים לכתוב הוא משחק "ברז" פשוט. בלון או פצצה ייכשלו במסך. אם השחקן מקיש על הבלון הוא קלע נקודה, הוא מקיש על פצצה ואז התוצאה תחולק ב -2, כעונש. כדי לכתוב את הקוד שאתה צריך לערוך main.lua. אתה יכול לעשות זאת בכל עורך טקסטים.

ל- Corona SDK יש מנוע מובנה בפיזיקה דו מימדית, מה שמקל על משחקי בנייה קל מאוד. השלב הראשון בכתיבת המשחק הוא לאתחל את מנוע הפיזיקה:

פיזיקה מקומית = דורשים ("פיסיקה") פיזיקה. התחל ()

הקוד די מסביר את עצמו. פיזיקת המודול נטענת ומוזמנת, היא מוקצית למשתנה פיזיקה. כדי לאפשר את המנועphysics.start () נקרא.

בשלב הבא אנו יוצרים כמה משתנים מועילים אשר יהיו שימושיים לא רק למשחק הפשוט הזה, אלא גם למשחקים מורכבים יותר. חציW ו חצי ח החזק את הערכים לחצי מרוחב המסך ולחצי מגובה המסך:

halfW = display.contentWidth * 0.5 halfH = display.contentHight * 0.5

ה תצוגה אובייקט הוא אובייקט מוגדר מראש שאותו קורונה מעמידה לרשות העולם.

עכשיו מגיע הצעד הראשון שלמעשה גורם למשהו לקרות על המסך:

מקומי bkg = display.newImage ("night_sky.png", halfW, halfH)

כמו גם נכסים כמו תוכן גובה ו תוכן רוחב, ה תצוגה לאובייקט יש גם הרבה פונקציות שימושיות. ה תמונה חדשה() הפונקציה קוראת קובץ תמונה (במקרה זה .png) ומציגה אותו על המסך. אובייקטי תצוגה מוצגים בשכבות, מכיוון שמדובר בתמונה הראשונה שאנחנו מציבים על המסך, זה תמיד יהיה הרקע (אלא אם כן הקוד מפורש לעשות משהו כדי לשנות את זה). הפרמטרים חציW ו חצי ח אומר לקורונה למקם את התמונה באמצע.

בשלב זה תוכלו להריץ את הקוד באמולטור ולראות את תמונת הרקע. אם תשמור את הקובץ אמולטור יבחין שהקובץ השתנה ומציע להפעיל מחדש. אם זה לא קורה, השתמש בקובץ-> הפעל מחדש.

מכיוון שהמשתמש יקלע נקודות להקשה על בלונים, עלינו לאתחל משתנה ציון ולהציג את הציון על המסך:

ציון = 0 ציון טקסט = תצוגה. חדש טקסט (ציון, חצי וואט, 10)

הציון יישמר במשתנה שזכה לדמיון ציון,ו ציון טקסט הוא האובייקט שמציג את הציון. כמו תמונה חדשה(), newText () שים משהו על המסך, בטקסט במקרה זה. מאז ציון טקסט הוא משתנה גלובלי אז נוכל לשנות את הטקסט בכל נקודה. אבל נגיע לזה בקרוב.

אתה יכול להפעיל מחדש את האמולטור ולראות את התוצאה של תצוגה 0 לראש החלק של המסך.

משמאל: רק הרקע. מימין: רקע וציון.

עכשיו מגיע משהו קצת יותר מסובך, אבל אל דאגה אני אסביר את זה שורה אחר שורה:

פונקציה מקומית balloonTouched (אירוע) אם (event.phase == "התחיל") ואז Runtime: removeEventListener ("enterFrame", event.self) event.target:removeSelf () score = score + 1 scoreText.text = score end end

הקוד שלמעלה מגדיר פונקציה הנקראת balloonTouched () שנקרא בכל פעם שמכינים על בלון. עדיין לא אמרנו לקורונה להתקשר לפונקציה הזו בכל פעם שהכפתור על הכדור פורח, זה יבוא אחר כך, אבל כשאנחנו מבצעים זאת הפונקציה שמתקשרת.

הקש או אירוע מגע יש כמה שלבים, רבים לתמוך גרירה. המשתמש מניח את האצבע על חפץ, זהו השלב "התחל". אם הם מחליקים את האצבע לכיוון כלשהו, ​​זהו השלב ה"זז ". כאשר המשתמש מרים את האצבע מהמסך, זהו השלב "הסתיים".

השורה הראשונה של balloonTouched () בודק שאנו נמצאים בשלב "התחל". אנו רוצים להסיר את הבלון ולהגדיל את התוצאה בהקדם האפשרי. אם הפונקציה נקראת שוב לשלבים אחרים כמו "הסתיים", הפונקציה לא עושה דבר.

בתוך האם הצהרה הן ארבע שורות קוד. בואו נעסוק בשניים האחרונים ראשונים, מכיוון שהם פשוטים יותר.ציון = ציון + 1 רק מגדיל את התוצאה בזה אחר זהscoreText.text = ניקוד משנה את טקסט הניקוד על המסך כך שישקף את הניקוד החדש. זוכר איך אמרתי את זהציון טקסט היה גלובלי וניתן היה לגשת אליו בכל מקום, ובכן זה מה שאנחנו עושים כאן.

עכשיו לשתי השורות הראשונות. ברגע שבלון או פצצה נופלים בתחתית המסך הם עדיין קיימים בזיכרון של האפליקציה, זה פשוט שאי אפשר לראות אותה. ככל שהמשחק מתקדם מספר העצמים האלה מחוץ למסך יגדל בהתמדה. לכן עלינו להיות בעלי מנגנון שמוחק עצמים ברגע שהם לא נראים. אנו עושים זאת בפונקציה שנקראתמחוץ למסך, שעוד לא כתבנו. פונקציה זו תיקרא פעם למסגרת במהלך המשחק. לאחר הקשה על בלון אז עלינו למחוק אותו ולהסיר את השיחה שבודקת אם הבלון עבר מחוץ למסך.

השורהevent.target: remove Self () מוחק את הבלון. כאשר אירוע מגע מתרחש אחד הפרמטרים של פונקציית המאזין הואאירוע פרמטר. הוא מספר את הפונקציה על האירוע ואיזה סוג אירוע הוא, למשל.שלב. זה גם אומר לנו איזה בלון הושלם,אירוע. הremoveSelf () פונקציה עושה מה שהיא אומרת שהיא עושה, היא מוחקת את האובייקט (במקרה זה בלון).

השורה שלפני כן מסירה את המאזין "enterframe", שהיא הפונקציה שנקראת כל מסגרת כדי לראות אם הבלון נפל מתחתית המסך. אנו נבחן זאת ביתר פירוט כאשר אנו באים לכתוב אתמחוץ למסך פונקציית המאזינים.

אז, לסכם מחדש.balloonTouched ()בודק שזו תחילת רצף המגע. לאחר מכן הוא מסיר את המאזין "enterframe", שהיא הפונקציה שנקראת כל מסגרת כדי לראות אם הבלון נפל מתחתית המסך. לאחר מכן הוא מוחק את הבלון, מעלה את הניקוד ומציג את הניקוד החדש.

זה היה עבור בלונים, עכשיו אנחנו צריכים משהו דומה לפצצות:

פונקציה מקומית bombTouched (אירוע) אם (event.phase == "התחיל") ואז Runtime: removeEventListener ("enterFrame", event.self) event.target:removeSelf () score = math.floor (score * 0.5) scoreText.text = סוף סוף ציון

כפי שאתה יכול לראות שהקוד דומה מאוד, למעט שבמקום להגדיל את הניקוד, הכפיל מוכפל ב 0.5 (כלומר חלקי 2). ה math.floor () הפונקציה מסייגת את התוצאה למספר השלם הקרוב ביותר. אז אם לשחקן היה ציון 3 וטפח על פצצה, התוצאה החדשה הייתה 1, ולא 1.5.

הזכרתי את מחוץ למסך () לתפקד קודם. פונקציה זו תיקרא כל פריים כדי לבדוק אם אובייקט נעלם מהמסך. הנה הקוד:

פונקציה מקומית מחוץ למסך (עצמי, אירוע) אם (self.y == nil) ואז להחזיר סוף אם (self.y> display.contentHeight + 50) ואז זמן פעולה: removeEventListener ("enterFrame", עצמי) עצמי: removeSelf () סוף סוף

במחשוב יש מצב המכונה מצב גזע. זה המקום בו שני דברים עומדים להתרחש, אך האחד עשוי להתרחש קודם, או לפעמים השני עשוי לקרות קודם. זה מירוץ. תנאי מירוץ מסוימים אינם נראים מכיוון שדבר אחד תמיד קורה קודם, אך הם יכולים לגרום לבאגים מעניינים באותו יום, בתנאים הנכונים, הדבר השני קורה קודם ואז המערכת נשברת!

יש מצב מירוץ במשחק הפשוט הזה מכיוון ששני דברים יכולים להתרחש קרובים זה לזה מאוד: בלון שמקישים אותו וה מחוץ למסך () הפונקציה נקראת כדי לראות אם הבלון נעלם מהמסך. התוצאה היא שניתן לקרוא לקוד למחיקת הבלון ואז ל - מחוץ למסך () פונקציה נקראת (שזה קורה כמו 30 פעמים בשנייה). כדי לעקוף את רצף האירועים המוזר הזה מחוץ למסך () פונקציה צריכה לבדוק אם y ערך האובייקט הוא אפס (null) או לא. אם זה אפס זה אומר שהאובייקט כבר נמחק, אז המשך הלאה, אלה לא היבשנים שאנחנו מחפשים.

אם האובייקט עדיין מופעל, בדוק את מיקומו, אם הוא עבר 50 פיקסלים מהמסך אז מחק אותו והסר את המאזין כך מחוץ למסך () פונקציה לא תתקשר שוב לאובייקט זה. הקוד כדי לוודא את זהמחוץ למסך () נקרא כל מסגרת היא חלק מהקטע הקוד הבא.

כל הנחת היסוד של המשחק הזה היא שבלונים או פצצות חדשות ימשיכו להפיל את המסך. לכן אנו זקוקים לפונקציה שתיצור בלון חדש או פצצה חדשה:

פונקציה מקומית addNewBalloonOrBomb () startX = math.random (display.contentWidth * 0.1, display.contentWidth * 0.9) אם (math.random (1,5) == 1) אז - BOMB! פצצה מקומית = display.newImage ("bomb.png", startX, -300) physics.addBody (פצצה) bomb.enterFrame = offscreen זמן פעולה: addEventListener ("enterFrame", פצצה) פצצה: addEventListener ("touch", bombTouched) אחר - בלון בלון מקומי = display.newImage ("red_balloon.png", startX, -300) physics.addBody (balloon) balloon.enterFrame = offscreen זמן פעולה: addEventListener ("enterFrame", balloon) בלון: addEventListener ("מגע", "מגע", סוף סוף

השורה הראשונה של הפונקציה מחליטה מאיפה הבלון ייפול מה- איקס מטוס. אם הבלון או הפצצה תמיד נשרו באמצע, זה לא יהיה מעניין במיוחד! לכןהתחל הוא מספר אקראי בין 10 אחוז ל 90 אחוז מרוחב המסך.

הבא נבחר מספר אקראי בין 1 ל 5.אם המספר הוא 1 אז הפצצה תוטל. אם זה 2, 3, 4 או 5 אז בלון ייפול. המשמעות היא שהפצצות יוטלו בסביבות 20 אחוז מהזמן.

קוד הפצצה והבלון דומים למדי. ראשית מוצגת התמונה (פצצה או בלון) באמצעותתמונה חדשה(). שלה איקס העמדה היא שלהתחל בעוד שלה y המיקום מוגדר ל- -300, כלומר בחלקו העליון של המסך. הסיבה לכך היא שאנחנו רוצים שהאובייקט ייפול מחוץ לאזור המסך לאזור הגלוי ואז מחוץ לתחתית. מכיוון שאנו משתמשים במנוע הפיזיקה של הדו-מימד, טוב לתת לאובייקט קצת מרחק ראשוני ליפול, כך שהוא יכול להשיג מהירות מסוימת.

הקריאה לphysics.addBody () מצלם את התמונה שטעינה על ידי תמונה חדשה() והופך אותו לאובייקט במנוע הפיזיקה. זה מאוד עוצמתי. ניתן להפוך כל קובץ תמונה לגוף המגיב לכוח המשיכה והתנגשויות רק על ידי שיחהphysics.addBody ().

שלוש השורות האחרונות של קוד הפצצה או הבלון הציבו את המאזינים. הגדרתenterFrame המאפיין אומר לקורונה לאיזה פונקציה להתקשר לכל מסגרת ולקריאהזמן פעולה: addEventListener () מגדיר את זה. לבסוף הקריאה לבלון: addEventListener () אומר לקורונה לאיזו פונקציה להתקשר אם נגע בפצצה או בבלון.

ועכשיו המשחק כמעט מושלם. אנחנו רק צריכים עוד שתי שורות קוד:

addNewBalloonOrBomb () timer.performWithDelay (500, addNewBalloonOrBomb, 0)

השורה הראשונה גורמת לכך שהפצצה או הבלון הראשונים נופלים על ידי קריאה מפורשתaddNewBalloonOrBomb (). השורה השנייה מגדירה טיימר שיתקשר אליוaddNewBalloonOrBomb () כל חצי שנייה (500 אלפיות השנייה). המשמעות היא שבלון או פצצה חדשים ייפלו כל חצי שנייה.

כעת תוכלו להריץ את המשחק באמולטור.

להלן הרישום המלא של main.lua, את קוד המקור המלא של הפרויקט למשחק זה תוכלו למצוא כאן ב- GitHub.

------------------------------------------------------ --------------------------------------- - - בלון נופל ומשחק פצצה - נכתב על ידי גארי סימס עבור - ------------------------------------------- ---------------------------------------------- -- תתחיל את הפיזיקה של מנוע הפיזיקה הפיזיקה המקומית = דורשים ("פיזיקה") physics.start () - חישוב חצי רוחב המסך וגובהו חציW = display.contentWidth * 0.5 halfH = display.contentHight * 0.5 - הגדר את הרקע המקומי bkg = display.newImage ("night_sky.png", halfW, halfH) - ציון ציון = 0 scoreText = display.newText (score, halfW, 10) - נקרא כאשר הנגן על הבלון על ידי השחקן - הגדל את התוצאה על ידי בלון פונקציה מקומי אחד נגע ( אירוע) אם (event.phase == "התחיל") ואז Runtime: removeEventListener ("enterFrame", event.self) event.target:removeSelf () score = score + 1 scoreText.text = score end end - נקרא כאשר הפיצוץ טופח על ידי השחקן - מחצית התוצאה כפונקציה מקומית בפנדל bombTouched (אירוע) אם (event.phase == "התחיל") ואז Runtime: removeEventListener ("enterFrame", event.self) event.target:removeSelf () score = math.floor (score * 0.5) scoreText.text = סוף סוף סוף - מחק אובייקטים שנפלו מה בחלק התחתון של המסך פונקציה מקומית מחוץ למסך (עצמי, אירוע) אם (self.y == nil) ואז להחזיר סוף אם (self.y> display.contentHeight + 50) ואז Runtime: removeEventListener ("enterFrame", עצמי) עצמי: removeSelf () סוף סוף - הוסף בלון נופל חדש או הפצצה מקומית פונקציה addNewBalloonOrBomb () - אתה יכול למצוא red_ballon.png ו- bomb.png ברשימה המקומית GitHub startX = math.random (display.contentWidth * 0.1, display.contentWidth * 0.9) אם (math.random (1,5) == 1) אז - BOMB! פצצה מקומית = display.newImage ("bomb.png", startX, -300) physics.addBody (פצצה) bomb.enterFrame = offscreen זמן פעולה: addEventListener ("enterFrame", פצצה) פצצה: addEventListener ("touch", bombTouched) אחר - בלון בלון מקומי = display.newImage ("red_balloon.png", startX, -300) physics.addBody (balloon) balloon.enterFrame = offscreen זמן פעולה: addEventListener ("enterFrame", balloon) בלון: addEventListener ("מגע", "מגע", balloonTouched) קצה קצה - הוסף בלון או פצצה חדש עכשיו addNewBalloonOrBomb () - המשך להוסיף בלון או פצצה חדשים כל טיימר של 0.5 שניות. ביצוע עםithelay (500, addNewBalloonOrBomb, 0)

הצעדים הבאים

השלב הבא הוא לשחק את המשחק במכשיר אנדרואיד אמיתי. לבניית קובץ .apk לחץ על File-> Build for Android ... ומלא את השדות. התוצאה תהיה קובץ .apk שתוכלו להעתיק למכשיר ואז להתקין. עליכם לוודא שהגדרתם את המכשיר שיאפשר התקנת אפליקציה ממקורות לא ידועים. לאמזון יש כמה תיעוד טוב בנושא, מכיוון שאתה צריך גם להגדיר את זה להתקנת האפליקציה של אמזון. לקורונה יש גם מדריך כיצד לחתום, לבנות ולבדוק את האפליקציה שלכם במכשירי אנדרואיד.

כאשר המשחק מותקן בהצלחה במכשיר, הדבר הבא לעשות הוא לשפר את המשחק. לדוגמה, מדוע לא לנסות להוסיף "פופ" או "המפץ" נשמע כל מה שמופיעה בלון או פצצה. לקורונה יש ממשק API לזה:media.playEventSound ().

או מדוע לא לנסות להוסיף סוג שלישי של אובייקט, נניח דחיפה סופר שמכפיל את הניקוד הנוכחי, או מה דעתך על מוזיקת ​​רקע מסוימת?

לעטוף

כתיבת משחקים עם קורונה היא די ישר מכיוון ש- SDK מטפל בדברים כמו OpenGL והיא כוללת מנוע מובנה בפיזיקה 2D. כמו כן, לואה קל ללמוד ולא אמור להיות קשה לאף אחד שיש לו אפילו מינימום ניסיון בתכנות. באתר Coronalabs יש המון תיעוד כולל המון מדריכים והדרכות.

בפחות ממאה שורות קוד יש לנו משחק עבודה. אוקיי, זה לא הולך לזכות בפרסים, עם זאת הוא מראה את העוצמה והגמישות של ה- Corona SDK.

מצד שני, אתה מקבל חריץ רגיל מדמיע ב- Xiaomi Redmi Note 7 Pro. איזה עיצוב אתה מעדיף תלוי לחלוטין בך. חשבתי שלמרות שההודעות ממוקמות מעט מחוץ למרכז בגלל חור האגרוף תהיה בעיה, אבל זה משהו שבקושי שמתי לב א...

השמועה של סמסונג גלקסי נוט 10 עשויה להגיע עם ארבע מצלמות אחוריות, לפי הספקולציות שלamMobile אתמול. אף על פי שזה לא ציין מקור, האתר אמר כי המכשיר הקרוב עשוי לכלול את הגדרת המצלמה הרביעית, מה שמאפשר למכ...

מומלץ על ידי ארה"ב