בעיות עם טיימר...

ahillel

New member
בעיות עם טיימר...

שלום לכולם! נוצרה לי בעיה עם ה FPS. כדי לשמור על קצב קבוע של הרצת המשחק, סידרתי שהלולאה תיהיה בעצם טיימר שמתקתק פעם ב 16 מיליסקנד, מה שאמור לתת לי תוצאה של 62 תיקתוקים בשניה. (62 FPS) לאחר מספר נסיונות גיליתי שהמשחק לא רץ בקצב אחיד. אז הוספתי טיימר נוסף שמתקתק כל 1000 מיליסקנד, שהתפקיד שלו זה למדוד כמה FPS [באמת] יש לי בכל שניה נתונה של משחק. ואכן גיליתי שקצב התיקתוקים (FPS) משתנה ביחס לכמות הפקודות שהתוכנית צריכה לבצע בכל תיקתוק. שאלה 1: האם טיימר (של Visual Studio) לא אמור ליהיות מדוייק?! כלומר מסונכרן עם השעון של המחשב ולא תלוי בכמות הפעולות שהוא צריך לבצע כל תיקתוק? אח"כ ניסיתי לפתור את הבעיה ע"י שינוי הINTERVAL (קצב) של הטיימר ביחס לכמות הפריימים האמיתיים שהוא נותן. הבעיה היא שהINTERVAL באמת השתנה, אך למראית עין בלבד. בפועל הוא נשאר זהה למה שהיה בתחילת התוכנית. שאלה 2: איך אני משנה INTERVAL של טיימר (ככה שהוא באמת ישתנה ולא רק ויזואלית)? שאלה 3: למישהו יש רעיון טוב יותר לפיתרון? חשבתי אולי לנסות לעבוד ישירות עם השעון של המחשב (שכחתי את השם שלו). שאלה 4: איך אתם בד"כ עובדים עם FPS ?
 

De-Panther

New member
אתה לא יכול לבנות על זה שהFPS יהיה קבוע... זה

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

ahillel

New member
האמת שלא כל כך הבנתי

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

De-Panther

New member
אני דיי גרוע במתמטיקה... אבל ממה שאני זוכר...

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

freak2100

New member
עקרונית...

אתה צודק בנוסחה, רק בלי הסינוס זה המיקום הנוכחי פלוס הזמן שעבר כפול המהירות, משהו כזה מה שאתה נתת זה לתנועה מעגלית או משהו בסגנון מה שעושים זה דבר כזה אתה צריך לחשב כמה זמן עבר בין הפריים הקודם לפריים הנוכחי ואת המהירות של העצם לשמור במהירות לשנייה, למשל ואז לעשות:
myObject.x += speed_x*time;​
משהו כזה, כשmyObject.x בדוגמה הזאת זה המיקום של האובייקט על ציר הx, הspeed_x זה המהירות על ציר x והtime זה הזמן שעבר חשוב להקפיד על יחידות מתאימות, למשל מיקום בפיקסלים, זמן בשניות ומהירות בפיקסלים לשנייה.
 

De-Panther

New member
כן הבנתי את זה כשדיברתי איתו במסנג'ר../images/Emo3.gif ואת..

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

freak2100

New member
כן

וכמובן שאחד חלקי "הזמן שעבר" זה הFPS, ככה מודדים אותו
 

yoniBLA

New member
תגובה

בשאלה1 אתה שואל איך לבצע פעולה כלשהי במשך זמן שאינו תלוי ב"כמות הפקודות" שהפעולה מכילה. אני אשמח אם מי ששולח תשובה יוכל להכניס לשם את הקוד של unreal כדי שירוץ לי על המחשב ב500 fps (למה לא? הרי אנחנו רוצים שמשהו ירוץ ללא תלות בכמות הפקודות שהוא מכיל). לתשובה האמיתית: אתה לא עובד נכון. המבנה לא צריך להיות כך. אני מבין שאתה מריץ את הקוד של המשחק שלך בכל קפיצה של השעון, למה שלא פשוט תריץ את הקוד של המשחק שלך כל הזמן? ככה תגיע לFPS מקסימאלי. בהמשך תתקל בבעיה אחרת, המשחק ירוץ מהר מדי במחשבים מסויימים לעומת במחשבים אחרים, וזו בעיה שניתן לפתור ע"י פקודות sleep שבודקות את הFPS הנוכחי ובמקרה הצורך מאטות אותו.
 

voguemaster

New member
אל תעבוד עם טיימר

קודם כל, הטיימר בעל רזולוציה נמוכה, כלומר הזמן המינימלי בין אירועי TIMER הוא 16 מילישניות כמו שכתבת. גם אם תרצה רזולוציה טובה יותר לא תקבל אותה משם. הדבר השני הוא הזמן שלוקח לקוד שלך להתבצע. אם יוצא שלקוד שלך לוקח יותר מ-16 מילי לבצע את מה שהוא צריך, זה יעכב את האירועים הבאים. למה ? כי אתה מטפל כל פעם באירוע אחד בלבד ועד שלא סיימת את הטיפול והחזרת את ה"שליטה" למערכת, אתה לא יכול לקבל את האירוע הבא. באופן עקרוני, לולאות של משחק נכתבות בצורה כזו שכל עוד האפליקציה במצב IDLE אתה מבצע את הדברים שאתה צריך. ממש לולאה במלוא מובן המילה, כשתנאי העצירה הוא בד"כ טיפול בהודעת WM_QUIT. בכל אופן, אתה יכול לחפש מידע בגוגל אם תחפש game loop ותתחיל לקרוא ולהבין מה קורה שם ומי נגד מי.
 
למעלה