ABA


"בעיות עם דיוק אחרי הנקודה"
גירסת הדפסה        
קבוצות דיון פיתוח, תיכנות ובניית אתרים נושא #15805 מנהל    סגן המנהל    מפקח   Winner    צל"ש   מומחה  
אשכול מספר 15805
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   11:57   10.04.10   
אל הפורום  
  בעיות עם דיוק אחרי הנקודה  
 
   ערכתי לאחרונה בתאריך 10.04.10 בשעה 12:32 בברכה, ronen333
 
שבת שלום חבר'ה .
לא מדובר בעוד אלגוריתם מסובך או להוציא את העיינים על בעיות קטנות, אלא הצעת רעיון לגבי התמודדות עם דיוק אחרי הנקודה.

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

עשיתי את הפוקצית המרה מפיקסל למטריצה הבאה:


public static void ConvertPositionToMatrix(Vector2 position, out int row, out int col)
{
position -= new Vector2(Game1.BOARD_WIDTH_OFFSET, Game1.BOARD_HEIGHT_OFFSET);
row = (int)(position.Y / BOARD_SQURE);
col = (int)(position.X / BOARD_SQURE);
}

וכאמור ההפוכה לה, ממטריצה למקום פיסי:

public static Vector2 ConvertMatrixToPosition(int row, int col)
{
return new Vector2(col * BOARD_SQURE + BOARD_WIDTH_OFFSET, row * BOARD_SQURE + BOARD_HEIGHT_OFFSET);
}

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

מה אתם מציעים לעשות? X=
תודה מראש לעוזרים


                                שתף        
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

  האשכול     מחבר     תאריך כתיבה     מספר  
  ספק אם הבנתי מה ביקשת. אבל מה יש לי להפסיד? :) ilanka  10.04.10 12:32 1
     :( זה לא פותר את הבעיה.. ronen333  10.04.10 12:58 2
  תשים לב שבקאסטינג ל-int הוא מבצע עיגול מטה תמיד ldan192  10.04.10 17:29 3
     עשיתי ROUND אבל זה עדיין לא זה.. ronen333  10.04.10 18:23 4
         תשמע, אני לא בטוח שהבנתי למה עשית את זה ldan192  10.04.10 18:34 5
             אני אתאר לך את הרעיון כי אני רואה שלא כל כך קלטת אותי ronen333  10.04.10 19:01 6
                 אם אתה לא יכול להרחיב ל-double וזה קורה אז הפונקציה ldan192  11.04.10 20:49 11
  לפי מה שהבנתי מהתגובה שלך למטה Net_Boy  10.04.10 22:14 7
     עשיתי ROUND, גם עידן הציע את זה ronen333  11.04.10 07:49 8
         תפריד בין מקרים Net_Boy  11.04.10 20:21 9
             מכתב ronen333  11.04.10 20:30 10
                 פונקצית round Net_Boy  11.04.10 22:27 15
                     המקרה השני באמת עזר קצת :) ronen333  13.04.10 07:30 18
  אולי לעבוד עם VeNom  11.04.10 20:49 12
     אבל זה בדיוק אותו הדבר... ronen333  11.04.10 21:17 13
         לא זה לא.. VeNom  11.04.10 21:35 14
             אני אמרתי שהשדות של VECTOR2D הם FLOAT... ronen333  12.04.10 00:23 16
                 אז איפה הבעיה? VeNom  12.04.10 08:38 17
                     זה מה שקורה אצלי ronen333  13.04.10 07:34 19

       
ilanka  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 2.8.02
23571 הודעות, 23 פידבק
   12:32   10.04.10   
אל הפורום  
  1. ספק אם הבנתי מה ביקשת. אבל מה יש לי להפסיד? :)  
בתגובה להודעה מספר 0
 
הנה הצעונת, "בשלוף": אם אתה מתעקש להשתמש בהמרה כזו ואם חשוב לך דיוק של X ספרות אחרי הנקודה, פשוט תכפיל את המספר ב-10 בחזקת X.

למשל, כדי לשמור את המספר 1.234 כ-INT, מבלי לאבד את הדיוק, פשוט הכפל אותו ב-1000, וכך תשמור אותו במקום המתאים במטריצה. כדי להחזירו למקור, פשוט חלק ב-1000

...לנסח את השאלה נכון - זה אפילו יותר חשוב מהתשובה....


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   12:58   10.04.10   
אל הפורום  
  2. :( זה לא פותר את הבעיה..  
בתגובה להודעה מספר 1
 
   ערכתי לאחרונה בתאריך 10.04.10 בשעה 13:24 בברכה, ronen333
 


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   17:29   10.04.10   
אל הפורום  
  3. תשים לב שבקאסטינג ל-int הוא מבצע עיגול מטה תמיד  
בתגובה להודעה מספר 0
 
(גם אם המספר הוא 0.99).
אולי נסה להשתמש בפונקציה שמעגלת לכיוון הנכון.

מעבר לזה, תבדוק מה גודל השגיאה בעיגול.
למה שלא תשתמש ב-double במקום ב-float?
כי אני לא רואה איך עיגול יכול להרוס במיוחד במטריצה שהיא לא באמת עצומה (אלא רק 100x100)


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   18:23   10.04.10   
אל הפורום  
  4. עשיתי ROUND אבל זה עדיין לא זה..  
בתגובה להודעה מספר 3
 
   וזה לא DOUBLE כי ככה בנויה המחלקה VECTOR2D..


הנה דוגמה אחרי דיבוג לככה שזה ממש משפיעה: שלחתי את הPOSITION הזה:
{X:781.5 Y:34.5}
ושהחזרתי אותו לTESTPOSITION  שאמור לצאת עם אותם קורדינטות של POSITION יצא:
{X:774 Y:34}
עכשיו הכמה פיקסלים הבודדים האלה הם אלה שעושים את ההבדל הקטן בין זה שהוא יעלה על מכשול אחד ללא יעלה חחח... אז אני חייב לתקן את זה, השאלה איך..


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   18:34   10.04.10   
אל הפורום  
  5. תשמע, אני לא בטוח שהבנתי למה עשית את זה  
בתגובה להודעה מספר 4
 
אבל אם אתה מתכוון שבגלל שבכל איטרציה (או כניסה בעץ הרקורסיה) אתה בעצם מעתיק עץ חדש עם השינויים החדשים - אז יש פתרון לזה.
אתה מאתחל מטריצה מלאה רק פעם אחת, ובכל העמקה בעץ הרקורסיה אתה מבצע את השינויים על המטריצה המקורית (נניח שתהיה סטטית או העברה by reference).
עם זאת, אתה גם שומר אילו שינויים ביצעת באותה תנועה (למשל ע"י linked list של פעולות).
כשאתה עולה בחזרה מהעץ אתה משחזר את ברוורס את הפעולות ובכך אתה שומר על גודל קבוע יחסית של זכרון.
הזכרון הנוסף יהיה כעומק הפתרון (שבלוח רגיל זה לא אמור להיות קריטי).

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

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


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   19:01   10.04.10   
אל הפורום  
  6. אני אתאר לך את הרעיון כי אני רואה שלא כל כך קלטת אותי  
בתגובה להודעה מספר 5
 
   ערכתי לאחרונה בתאריך 10.04.10 בשעה 19:06 בברכה, ronen333
 
שאני נניח שם נשק במשחק, זה לוקח את הPOSITION שלו ושולח אותה לפונקציה UPDATEMATRIX שכל מה שהיא עושה זה לעדכן את המס' נשק שבמטריצת NODES.
איך היא מגלה את המיקום שלו על המטריצה? באמצעות ConvertPositionToMatrix, שמחזיר דרך הפרמטרים ROW וCOL את התוצאה, של המשבצת שעליה הוא הונח.
ככה אני משנה את המפה שלי במהלך המשחק בטטא של 1.

עכשיו A STAR לא קשור לזה, הוא מחזיר STACK עם המסלול בROW וCOL ומחזיר את הNODES של המטריצה לקדמותם- ככה שזה לא מטריד אותנו.
הבעיה היא שאני רוצה להמיר את המיקום ROW COL חזרה לPOSITION כדי שהאויב ידע לאן ללכת הוא עושה את זה בצורה לא מדויקת (ביגלל איבוד הדיוק שדיברנו) ואז נוצר מצב שהוא עולה על מכשול בגלל חוסר הדיוק.
תמונת המחשה:

המשבצת שהחץ מצביע זה משבצת שיש עליה מכשול
והוא לא אמור להיות חלק מהמסלול (הנקודות האדומות זה המסלול)
זה לא בעיה בA STAR אלא בדיוק אל הנקודות שאליהם הוא הולך.. כי הSTACK בסדר.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   20:49   11.04.10   
אל הפורום  
  11. אם אתה לא יכול להרחיב ל-double וזה קורה אז הפונקציה  
בתגובה להודעה מספר 6
 
עצמה לא טובה (של החישוב).
אי אפשר לעשות דברים בכוח (כמו כפל ב-100 וכו') כי floating point ישאר שכזה.

נסה לחשוב על פונקציית המרה אחרת.
למשל, כל אחד ישמור 2 שדות של x,y ויבצע מניפולציה.
אם במקום 100 תאי זכרון תשתמש ב-200, זה כמעט ושולי (לרוב)


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Net_Boy  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 1.4.02
17151 הודעות, 1 פידבק
   22:14   10.04.10   
אל הפורום  
  7. לפי מה שהבנתי מהתגובה שלך למטה  
בתגובה להודעה מספר 0
 
   כמה דברים

1) הפונקציה שממירה ממיקום פיזי למקום מטריצה היא בסדר - רק במקום לעשות CAST ל int תשתמש בפונקצית round.
כי int תמיד מעגל כלפי מטה.

2) אתה לא יכול להמיר תא של מטריצה לנקודת עולם כי בתא יש כמה נקודות עולם
בגלל זה יש לך סטייה גדולה ב X.
אתה יכול לקבוע שתמיד תוחזר נקודת האמצע בתא לדוגמא אבל עצם העובדה שאתה צריך לעשות המרה כזאת כבר מעידה שיש פה בעייה קטנה - למה אתה צריך להמיר מקורדינאטות מטריצה לקורדינאטות עולם ?



                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   07:49   11.04.10   
אל הפורום  
  8. עשיתי ROUND, גם עידן הציע את זה  
בתגובה להודעה מספר 7
 
   זה לא מספיק טוב.. לא פותר את הבעיה.
ומיפני שהעולם מחולק למשבצות ורציתי לחסוך במקום וזמן ריצה אז החלטתי לחלק את המטריצה לפי המשבצות ולא לפי הפיקסלים.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Net_Boy  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 1.4.02
17151 הודעות, 1 פידבק
   20:21   11.04.10   
אל הפורום  
  9. תפריד בין מקרים  
בתגובה להודעה מספר 8
 
   במקרה שאתה עובר מנקודת עולם לתא במטריצה - הסטייה היא מקסימום בתא אחד
וזה באמת משהו ש ROUND כן אמור לתקן.
איך אתה משווה בין המשתנים שלך ? סתם ככה ? אם כן יש סיכוי טוב שזה לא יעבוד.
כדי לעשות השוואה בין 2 מספרים ממשיים צריך להשתמש בחסם כלשהו (אפסילון)
שבעזרתו אתה קובע את תוצאת היחס.


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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   20:30   11.04.10   
אל הפורום  
  10. מכתב  
בתגובה להודעה מספר 9
 
   ככה פשוט למדתי לעבוד בXNA, אתה עובד שם פיסי עד שזה מגיע לAI, ואז אתה נעזר במבנה נתונים כמו מטריצה.
תוכל בבקשה לפרט יותר לגבי החסם ולמה התכוונת? (וROUND האמת שלא טוב לי.. הוא מקלקל).

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Net_Boy  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 1.4.02
17151 הודעות, 1 פידבק
   22:27   11.04.10   
אל הפורום  
  15. פונקצית round  
בתגובה להודעה מספר 10
 
   במקרה הזה אפילו לא צריך להשתמש באפסילון (צריך רק שרוצים לקבוע שיוויון)


int round(double num)
{
int floor = (int)num;
if( (num-(double)floor) >= 0.5)
return floor+1;
return floor;
}

ובאשר למקרה השני

public static Vector2 ConvertMatrixToPosition(int row, int col)
{
return new Vector2(col * BOARD_SQURE + BOARD_WIDTH_OFFSET + BAORD_SQUARE/2 , row * BOARD_SQURE + BOARD_HEIGHT_OFFSET + BOARD_SQUARE /2);
}


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   07:30   13.04.10   
אל הפורום  
  18. המקרה השני באמת עזר קצת :)  
בתגובה להודעה מספר 15
 
   תודה לא יודע איך לא חשבתי על זה חחח..


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
VeNom  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 7.6.02
7922 הודעות, 1 פידבק
   20:49   11.04.10   
אל הפורום  
  12. אולי לעבוד עם  
בתגובה להודעה מספר 0
 
   ערכתי לאחרונה בתאריך 11.04.10 בשעה 20:54 בברכה, VeNom
 
טיפוס נתונים מקביל ל vector 2
רק שהדאטא ממברס שלו יהיה מסוג

float x;
float y;

וכל פעם שתרצה לגשת למיקום מטריצה תעשה קאסטינג ל int..
עריכה:אם קאסטינג פעולה יקרה כי אני רואה שמדובר כאן במשחק אולי תיצור טיפוס שיכלול גם מיקומי x,y כ int וגם מיקום x,y של float..זה אומנם יגדיל משמעותית את הזכרון אבל זה אמור לפתור את הבעיה הזאת שאם הפתרון של round לא פותר אני לא חושב שיש דרך טובה יותר לפתור.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   21:17   11.04.10   
אל הפורום  
  13. אבל זה בדיוק אותו הדבר...  
בתגובה להודעה מספר 12
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
VeNom  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 7.6.02
7922 הודעות, 1 פידבק
   21:35   11.04.10   
אל הפורום  
  14. לא זה לא..  
בתגובה להודעה מספר 13
 
   אלא אם כן השדות של vector2 הם float ולא int כמו שחשבתי..

public static Vector2 ConvertMatrixToPosition(float row, float col)
{
return new Vector2(col * BOARD_SQURE + BOARD_WIDTH_OFFSET, row * BOARD_SQURE + BOARD_HEIGHT_OFFSET);
}
ושתרצה נגיד להגיד לנק' על המסך אז
int x = (int)Vector2.X;
int y = (int)[email protected];


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   00:23   12.04.10   
אל הפורום  
  16. אני אמרתי שהשדות של VECTOR2D הם FLOAT...  
בתגובה להודעה מספר 14
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
VeNom  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 7.6.02
7922 הודעות, 1 פידבק
   08:38   12.04.10   
אל הפורום  
  17. אז איפה הבעיה?  
בתגובה להודעה מספר 16
 
   אם המטריצה מחזיקה floats תמיד..אתה תמיד תוכל להגיע לנק' הנכונה.
מצד שני אם תרצה להגיע למיקום המתאים במטריצה כל מה שצריך לעשות זה קאסטינג ל int..זה פותר את כל הבעיה..


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   07:34   13.04.10   
אל הפורום  
  19. זה מה שקורה אצלי  
בתגובה להודעה מספר 17
 
   זה לא פותר את הבעיה.. אבל זה הגיוני שזה מה שיקרה, כי יש כמה פיקסלים על משבצת, ואני מאבד את הדיוק שעל המשבצת הזאת, עם ההוספה של NEYBOY זה מבטיח שזה יהיה באמצע.
יכול להיות ששם לא טמונה הבעיה..

תודה בכל זאת על העזרה


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

תגובה מהירה  למכתב מספר: 
 
___________________________________________________________________

___________________________________________________________________
למנהלים:  נעל | תייק בארכיון | מחק | העבר לפורום אחר | מחק תגובות | עגן אשכול
       



© כל הזכויות שמורות ל-רוטר.נט בע"מ rotter.net