משחק Pong על מסך Nextion (בלבד!)

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

משחק Pong על מסך Nextion
משחק Pong על מסך Nextion

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

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

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

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

ל-Nextion יש שלושה משתנים מוגדרים מראש לשימוש כללי בקוד (sys0, sys1, sys2), ובעורך התצוגות של Nextion אפשר להוסיף משתנים עם שמות כרצוננו. יצרתי קוד בסיסי לתנועת ה"כדור", בתוך לולאת while אינסופית ובהתחשב במגבלות התחביר (למשל, אסור שיהיה רווח בין המילה if לבין הסוגריים שאחריה, ואי אפשר לשים אופרטורים לוגיים או חשבוניים בתוך התנאי של ה-if). הכדור קפץ על פני המסך בכיף. הגיע הזמן להכניס לתמונה את השחקן.

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


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

* זמן-מה אחרי שכתבתי את זה חשבתי על דרך להתגבר גם על מגבלת ה-50ms, אבל זה לפוסט אחר…

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

המשחק בפעולה, שימו לב שקווי RX/TX לא מחוברים לכלום.
המשחק בפעולה, שימו לב שקווי RX/TX לא מחוברים לכלום (לחצו להגדלה)

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

"פונקציה" לאתחול של מיקום וכיוון הכדור ב-Pong על Nextion
"פונקציה" לאתחול של מיקום וכיוון הכדור ב-Pong על Nextion (לחצו להגדלה)

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

בעקבות ההצלחה של הפרויקטון הזה התחלתי לחשוב על כיוונים נוספים שיוצרי Nextion בטח לא חלמו עליהם. אגב, תוך כדי חיפוש מידע גיליתי שבפורומים של Nextion יש כמה משחקים עם קוד להורדה והסברים – אבל לא מהסוג הדינמי שאני יצרתי. למשל, יש שם איקס עיגול לשני שחקנים אנושיים. אני בודק כעת, כאמור, תזמונים שעוקפים את מגבלת ה-50ms של הטיימרים, יצירה של טבלאות Lookup ועוד. בקיצור, המשך יבוא…

להרשמה
הודע לי על
0 Comments
Inline Feedbacks
הראה את כל התגובות