מנוע הרנטגן אינו ידוע למדי מחוץ למדינות חבר העמים, ומעטים מודדים מכירים אותו כאן, וזה לא מפתיע - רק 3 משחקים יצאו עליו. אבל כמעט כל גיימר מכיר את המשחקים האלה - זוהי טרילוגיית S.T.A.L.K.E.R., אחת מסדרות המשחקים האיכותיות הבודדות שיצאו במרחב הפוסט-סובייטי. זה התברר כל כך מרגש שמודים חדשים מופיעים אפילו עכשיו, 8 שנים לאחר השחרור. משחק אחרוןסדרה (Call of Pripyat, 2009). וחלק מהאופנים הפכו לאייקוניים, שינו את המשחק באופן קיצוני - הם הוסיפו בינה מלאכותית חכמה יותר, מכוניות, עוד כלי נשק, משימות סיפור חדשות ואפילו מיקומים. אבוי - המשך הסדרה, המשחק S.T.A.L.K.E.R. 2 הוקפא רשמית, אבל רבים מחכים לו בדיוק כמו Half-Life 3.
ההיסטוריה של הופעת המנוע
המנוע פותח לחלוטין על ידי אולפן המשחקים האוקראיני GSC Game World, המתכנתים Ales Shishkovtsov ו- Oleksandr Maksimchuk עבדו על החלק הגרפי של המנוע (הם עבדו גם על פרויקט Metro 2033 ב-4A Games). ההדגמה הראשונה של המנוע נערכה בשנת 2001:
כפי שניתן לראות, ה-S.T.A.L.K.E.R. זה אפילו לא היה קרוב - ההדגמה הייתה יותר כמו הג'ונגל של Far Cry 1. עם זאת, גם אז המנוע היה די מתקדם - הוא עבד על DirectX 7 (מאוחר יותר, נוספה תמיכה ב-DirectX 8 ו-9 לשחרור של Shadows של צ'רנוביל בשנת 2007), נתמך במיפוי פרטים, Lightmap , AI מתקדם ומרקמים ברזולוציה גבוהה - עד 4,000,000 מצולעים יכולים להיות במסגרת אחת. עם זאת, כדי שמחשבים של אז ימשכו את כל היופי הזה, גודל מיקום המשחק היה צריך להיות מוגבל מאוד - זה יכול להיות לא יותר מ-2 מטרים רבועים. ק"מ ונטען מיד ובשלמותו, אך היו מעברים בין מיקומים עם מסכי טעינה. X-Ray נכתב ב-C/C++ באמצעות מקורות Microsoft DirectX SDK, עם מהדר שפת LUA "lua.JIT.1.1.4" מצורף אליו. בזמן העבודה, הספריות Microsoft Visual C ++ 7.1, Creative EAX (טכנולוגיה ליצירת אפקטים קוליים סביבה), ODE (מנוע פיזיקה פתוח), OpenAL (ממשק תכנות יישומים (API) לעבודה עם נתוני אודיו, GameSpy Client (רכיב מרובה שחקנים) ו-Color Picker.
פיתוח מנוע
כמו כל פרויקט בנייה ארוך טווח, במהלך 6 השנים מרגע יציאת המנוע ועד להופעת המשחק הראשון בו, הוא רכש עוד ועוד "טובים" חדשים כמו:
- תמיכה בכל מאיצי ה-D3D מהדור השלישי, מ-GeForce 2 ומעלה;
- ויזואליזציה מותאמת לטכנולוגיית TnL (טרנספורמציה ותאורה - מנגנון הממיר אובייקט תלת מימדי ממסגרת ייחוס אחת לאחרת);
- טכנולוגיית תאורה והצללה דחויים, המאפשרת להשיג נאמנות גבוהה בעיבוד תאורה עם מורכבות גיאומטרית גבוהה של הסצנה;
- טכנולוגיית רמת פירוט מתקדמת לכל הגיאומטריה;
- דמויות וכלי נשק מפורטים מאוד;
- מערכת אנימציה מעורבת במהירות גבוהה המסוגלת למספר בלתי מוגבל של אינטרפולציה של עצמות ופעולות מודולריות;
- תמיכה עבור SSE/3Dnow! טכנולוגיות עבור מעבדי אינטלו-AMD, בהתאמה, המאפשרים לך לייעל את העומס עליהם;
- מערכת נראות לא ליניארית מבוססת פורטל;
- טכנולוגיות חיסום/תרומה דינמיות (השבתת העיבוד של אובייקטים שנמצאים מחוץ למצלמה או במרחק רב);
- טכנולוגיית מטמון הניתנת להתאמה לחומרה;
- תאורה דינמית צבעונית וצללים "רכים" דינמיים;
- מקורות אור מונפשים הניתנים להרס;
- בחירת מקור אור מתקדם, מיזוג ופיצול, הטלת צללים לפי דמויות;
- מערכת חלקיקים עם פיזיקה אמיתית;
- מערכת הצללה מתקדמת;
- שינוי דינמי של מזג האוויר, ביום ובלילה.
למשחק היחיד במנוע הזה, Shadows of Chernobyl, היו בתחילה שני ממשקי API לבחירה בהגדרות - DirectX 8 עם התכונות שתוארו לעיל, ו-DirectX 9, שמוסיף עוד כמה אפקטים גרפיים:
- עיבוד נקודה צפה בטווח דינמי גבוה (HDR);
- מיפוי בליטות, מיפוי רגיל ומיפוי פרלקסה ( סוגים שוניםמרקם הקלה);
- תאורה דינמית לחלוטין, צללים רכים;
- עומק שדה (עומק שדה), טשטוש תנועה (טשטוש בתנועה), בלום (טשטוש אור בקצוות האובייקט) וקרני אור דינמיות.
חיים
תכונה נוספת של המנוע שמפתחים יכולים להתגאות בה היא מערכת הבינה המלאכותית A-Life (חיים מלאכותיים). המפתחים עצמם מתארים זאת כך:
השורה התחתונה היא שהדמויות במשחק חיות את חייהן וקיימות כל הזמן, ולא רק כשהשחקן רואה אותן. [...] הצגנו שני מונחים המאפיינים 2 מודלים של התנהגות אופי הנבדלים במידת הפירוט: לא מקוון ומקוון. ההתנהגות הלא מקוונת של הדמות פשוטה מאוד מבחינת פירוט: הדמות לא משחקת אנימציות, קולות, לא מנהלת מלאי באופן אקטיבי, לא בונה נתיבים מוחלקים מפורטים (למרות שהיא בונה נתיבים לפי גרף הניווט הגלובלי, אבל על כך בהמשך ), וכו. להתנהגות מקוונת, לעומת זאת, יש פירוט מלא. הָהֵן. ניתן לשקול שהתנהגות לא מקוונת היא פרי התנהגות מקוונת.
במערכת שלנו, בזמן שהשחקן משחק ברמה שלו, דמויות אחרות חיות ברמות אחרות, כלומר. נמצאים במצב לא מקוון, כלומר. להשתמש בהתנהגות לא מקוונת. יתרה מכך, בגלל האוכלוסייה הגדולה, לא לכל הדמויות באותה רמה יש התנהגות מקוונת, אלא רק לאלה שנמצאות ברדיוס נתון מהשחקן (זה עשוי להיות תלוי ברמות, בדרך כלל בסביבות 150 מטר) או לפי בקשת המשחק מעצבים.
כדי ליישם זאת, הסימולטור עוקב אחר תנועת השחקן והאובייקטים במצב לא מקוון ומתרגם אותם לאונליין / לא מקוון. בעת חישוב המעבר של אובייקטים, נעשה שימוש בטריק סטנדרטי עם אינרציה: רדיוס המעבר הלא מקוון גדול יותר מרדיוס המעבר המקוון.
לאחר מכן, ראוי להזכיר את הניווט של אובייקטים באינטרנט ובאופן לא מקוון. יש לנו רמות במשחק, שלכל אחת מהן נוצר גרף ניווט, שדמויות משתמשות בו כדי לנוע באינטרנט. אנחנו קוראים לזה גרף מפורט. עבור כל גרף מפורט נוצר גם האנלוג הפחות מפורט שלו, שאת קודקודיו ניתן לחבר עם קודקודי אותו גרף ברמה/ים אחרת. הָהֵן. לאחר שילוב כל הגרפים הללו יחד, נקבל גרף המשלב את כל הרמות. הוא משמש את הדמויות כדי לעבור לא מקוון. זה משמש גם על ידי דמויות מקוונות כשהן מבצעות את שלהן יעדים אסטרטגיים. לדוגמה, אם דמות מקוונת מחליטה ללכת לרמה אחרת, אז הוא בונה נתיב לאורך הגרף הגלובלי, ואז בונה נתיב לאורך הגרף המפורט של הרמה שלו מהמיקום שלו לנקודת הגרף הגלובלי. אם הנקודה הזו כבר נמצאת ברמה אחרת, אז הוא מבצע טלפורטציה לשם ועובר אוטומטית למצב לא מקוון. כדי למנוע את זה מתרחש מול השחקן, הגדרנו את נקודות המעבר לדמויות המשחק יותר מנקודות המעבר של השחקן, אי שם "מעבר לפינה"
כפי שאתה יכול לראות, ה-AI איכותי מאוד, ולאורך כל המשחק אין תחושה שה-Zone מת - כמה אירועים מתרחשים כל הזמן: יריות, מפגש עם סטוקרים שונים, מוטנטים, הופעת הודעות חדשות ב-PDA , וכו.
מנוע רנטגן 1.5
שנה לאחר מכן, לאחר יציאתו של Shadows of Chernobyl, בשנת 2008, יצא חלק חדש במשחק, Clear Sky. למשחק נוספו כלי נשק ומיקומים חדשים, כמו גם תמיכה ב-API חדש - DirectX 10. זה שיפר משמעותית את איכות המים והחלקיקים, כמו גם הוספת תמיכה למשטחים רטובים (כלומר, המשטח נראה אחרת לפני ואחרי גשם) ומיפוי פרלקס תלול (תצוגה מציאותית של עצמים בולטים על מרקם שטוח - למשל, אבנים בולטות בקיר). אבל באופן כללי, הגרפיקה הייתה ברמה של החלק הקודם של המשחק:
בחלק האחרון של הטרילוגיה, Call of Pripyat, שיצא ב-2009, המנוע קיבל תמיכה ב-DirectX 11. עם זאת, למרבה הצער, המנוע בן ה-8 לא משך את כל התכונות שלו, כך שנוספו רק טסל (התהליך של הוספת מצולעים קמורים חדשים לרשת מצולעת על מנת להגדיל את פירוט הרשת, במילים אחרות, עצמים קמורים הפכו למציאותיים יותר). רמה כלליתהגרפיקה נשארה זהה:
מנוע פיזיקה
X-Ray משתמש במנוע הפיזיקה החופשי Open Dynamics Engine (ODE). התכונות שלו:
- עיבוד התנגשות במהירות גבוהה (מהיר יותר מ- MathEngine מסחרי, Havok וכו'), זיהוי התנגשות מותאם עבור מספר גדולבקשות בסביבת פולי גבוה;
- הדמיה ריאליסטית של בליסטיקה, תנועה, פיזיקת מכוניות וכו'.
העוקב. 2 על מנוע רנטגן 2 הוכרז באוגוסט 2010, המשחק היה אמור לצאת בשנת 2012. עם זאת, בדצמבר 2011, פיתוח המשחק הופסק, וטרם נמשך, למרות שאולפן המשחקים GSC שמפתח את המשחק עדיין קיים - ב בספטמבר 2016, הוא הוציא את המשחק Cosacks 3. ידוע שבזמן שהפרויקט הוקפא, המנוע היה מוכן ב-70-80%, ונעשו גם כמה רמות ודמויות של משחק. המשחק היה אמור להיות עולם חלק, ומנוע הפיזיקה היה Havok. בהתחשב בגיל ההתפתחות של S.T.A.L.K.E.R. סביר להניח ש-2 לא ישוחרר לעולם, ויהפוך לפרויקט "נצחי" כמו Half-Life 3.
X-Ray Engine היא שפת תכנות שנוצרה על ידי GSC Game World עבור שימוש פנימי. כל מי ששיחק במשחק המחשב Stalker שמע על החברה הזו. מנוע ה-SDK (ערכת פיתוח תוכנה) הרשמי וקוד המקור לשפת התכנות של המשחק משמשים את יוצרי המודים הלא רשמיים.
בתהליך יצירת Stalker - Shadow of Chernobyl, המפתחים השתמשו ב-X-Ray, וגם הוציאו שתי גרסאות של המשחק שהמשיכו את המקור: Clear Sky ו-Call of Pripyat. גרסה שונה של ה"מנוע" שימשה ליצירת פרויקט Stalker 2, אך הפיתוח נעצר כבר ב-2011.
מַטָרָה
מפתחי משחקים משתמשים במנוע ה-X-Ray כדי ליצור אופנים חדשים. Stalker הוא משחק מרובה חלקים, אשר שוחררו לו הרבה שינויים. כדי לעזור למפתחי מודים, GSC Game World יצרה כלי SDK. מודים רבים שוחררו לכל חלק במשחק עם איכות גרפית ושינויים שונים.יוצרי המנוע הייחודי שכחו "לאשר" אותו במסמכים רשמיים. המפתחים הראשונים של מודים יצרו אותם חצי אפויים. במהלך הפיתוח של המודים הראשונים וכתיבת סקירה זו, היו הרבה הוראות ופורומים נושאיים. הודות להוראות אלה, אנשים מתקשרים ומשתפים את החוויה שלהם עם ה-SDK.
מפרטים
הגרסה הסופית של המנוע פועלת על כלי אבחון וספריית DirectX 11. לשפת התכנות יש תמיכה באור נפחי ובאפקטי עשן מורכבים, והיא גם מאפשרת לרנדר סצנות משחק מורכבות ועובדת עם פיזיקת Ragdoll.בגרסה הראשונה של שפת התכנות, המפתחים הוסיפו צללים רכים למשחק. בזמן יציאת החלק הראשון של המשחק, אלמנט גרפי כזה היה משהו חדש ומעניין מבחינה טכנית, במיוחד עבור משחק עם חלל גדול ושטח פתוח.
תכונות עיקריות
- SDK רשמי ליוצרי מפות ששונו למשחק;
- שפת התכנות תומכת בספריות DirectX 11;
- יצירת פיזיקה עם תנועה מציאותית ומערכת AI משלו (A-Life);
- הכנסת טכנולוגיה היוצרת טקסטורות תבליט של חפצים;
- תמיכה בצללים רכים ואור נפחי;
- הצגת כארבעה מיליון מצולעים במסגרת אחת;
- שפת התכנות של המשחק אינה מאושרת ואינה מופצת רשמית;
- ציור סצנות משחק מורכבות ותמיכה בפיזיקה של הדור הבא.
הפרויקט, יחד עם כל התלות שלו, מורכב בקלות ב-Visual Studio 2015. לצורך אימות, השתמשנו בקוד המקור של גירסת המנוע 1.6 מהמאגר ב-GitHub ובמנתח הקוד הסטטי PVS-Studio 6.04, אותו ניתן להוריד מ- הקישור .
העתק הדבק
ראשית, בואו נסתכל על השגיאות הקשורות להעתקת הקוד. התרחיש של התרחשותם ב הזדמנויות שונותבדרך כלל דומה: הם העתיקו את הקוד, שינו חלק מהמשתנים ושכחו כמה. באגים כאלה יכולים להתפשט במהירות דרך בסיס הקוד, וללא מנתח סטטי, קל מאוד לפספס אותם.MxMatrix& MxQuadric::homogeneous(MxMatrix& H) const ( .... unsigned int i, j; for(i=0; i
המנתח זיהה זאת בלולאה המקוננת להמשתנה מוגדל אני, והמשתנה מסומן י, מה שמביא ללולאה אינסופית. סביר להניח, בעת העתקתו, הם פשוט שכחו לשנות אותו.
void CBaseMonster::settings_read(CInifile const * ini, LPCSTR section, SMonsterSettings &data) ( .... if (ini->line_exist(ppi_section,"color_base")) sscanf(ini->r_string(ppi_section,"color_base"), if (ini->line_exist(ppi_section,"color_base")) sscanf(ini->r_string(ppi_section,"color_grey"), "%f,%f,%f", &data.m_attack_effector.ppi.color_gray.r, &data .m_attack_effector.ppi.color_gray.g , &data.m_attack_effector.ppi.color_gray.b); if (ini->line_exist(ppi_section,"color_base")) sscanf(ini->r_string(ppi_section,"color_add"), "% f,%f,%f" , &data.m_attack_effector.ppi.color_add.r, &data.m_attack_effector.ppi.color_add.g, &data.m_attack_effector.ppi.color_add.b); .... )
אזהרות PVS-Studio:
- V581 הביטויים המותנים של האופרטורים "אם" הממוקמים זה לצד זה זהים. קווי בדיקה: 445, 447. base_monster_startup.cpp 447
- V581 הביטויים המותנים של האופרטורים "אם" הממוקמים זה לצד זה זהים. קווי בדיקה: 447, 449. base_monster_startup.cpp 449
/* לעבד משפט יחיד */ static void ProcessStatement(char *buff, int len) ( .... if (strncmp(buff,"\\pauthr\\",8) == 0) ( ProcessPlayerAuth(buff, len ); ) else if (strncmp(buff,"\\getpidr\\",9) == 0) ( ProcessGetPid(buff, len); ) else if (strncmp(buff,"\\getpidr\\",9) == 0) ( ProcessGetPid(buff, len); ) else if (strncmp(buff,"\\getpdr\\",8) == 0) ( ProcessGetData(buff, len); ) else if (strncmp(buff, "\\setpdr\\",8) == 0) ( ProcessSetData(buff, len); ) )
אזהרת PVS-Studio: V517 זוהה השימוש בתבנית "אם (A) (...) אחרת אם (A) (...)". קיימת סבירות לנוכחות שגיאה לוגית. קווי בדיקה: 1502, 1505. gstats.c 1502
כמו בדוגמה הקודמת, כאן נעשה שימוש בשני תנאים זהים ( strncmp(buff,"\\getpidr\\",9) == 0). קשה לומר בוודאות אם זה באג או סתם קוד בלתי ניתן להשגה, אבל בהחלט שווה לבדוק. יתכן שצריכים להיות בלוקים עם getpidr/setpidrבאנלוגיה עם getpdr/setpdr.
class RGBAMipMappedCubeMap ( .... size_t height() const ( return cubeFaces.height(); ) size_t width() const ( return cubeFaces.height(); ) .... );
אזהרת PVS-Studio: V524 זה מוזר שגוף הפונקציה "רוחב" שווה ערך לחלוטין לגוף הפונקציה "גובה". tpixel.h 1090
שיטות גוֹבַה()ו רוֹחַב()בעלי אותו גוף. בהתחשב בכך שממדי פני הקוביה מחושבים, ייתכן שלא תהיה כאן שגיאה. אבל עדיף לשכתב את השיטה רוֹחַב()בצורה הבאה:
size_t width() const ( return cubeFaces.width(); )
שימוש לרעה ב-C++
C++ היא שפה נפלאה שנותנת למתכנת הרבה אפשרויות... לירות לעצמו ברגל בצורה אכזרית במיוחד. התנהגות לא מוגדרת, דליפות זיכרון וכמובן שגיאות הקלדה – שגיאות מסוג זה יידונו בסעיף הנוכחי.תבנית
אזהרת PVS-Studio: V591 פונקציה Non-void אמורה להחזיר ערך. _matrix33.h 435
חסר בסוף השיטה להחזיר *זה. על פי התקן, קוד כזה יוביל להתנהגות לא מוגדרת. מכיוון שערך ההחזרה הוא הפניה, סביר להניח שהדבר תקרוס את התוכנית בעת ניסיון לגשת לערך ההחזרה.
ETOOLS_API int __stdcall ogg_enc(....) ( .... FILE *in, *out = NULL; .... input_format *format; .... in = fopen(in_fn, "rb"); if(in == NULL) החזר 0; format = open_audio_file(in, &enc_opts); if(!format)( fclose(in); return 0; ); out = fopen(out_fn, "wb"); if(out == NULL) ( fclose(out); return 0; ) .... )
אזהרת PVS-Studio: V575 מצביע האפס מועבר לפונקציה "fclose". בדוק את הטיעון הראשון. ogg_enc.cpp 47
דוגמה מעניינת למדי. המנתח זיהה שהטיעון בשיחה לסגורשווים nullptr, מה שהופך את הקריאה לפונקציה חסרת טעם. אפשר להניח שהם היו צריכים לסגור את הנחל ב.
void NVI_Image::ABGR8_To_ARGB8() ( // מחליף RGB עבור כל הפיקסלים assert(IsDataValid()); assert(GetBytesPerPixel() == 4); UINT hxw = GetNumPixels(); עבור (UINT i = 0; i< hxw; i++)
{
DWORD col;
GetPixel_ARGB8(&col, i);
DWORD a = (col >> 24) && 0x000000FF; DWORD b = (קול >> 16) && 0x000000FF; DWORD g = (קול >> 8) && 0x000000FF; DWORD r = (col >> 0) && 0x000000FF; col = (א<< 24) | (r << 16) | (g << 8) | b;
SetPixel_ARGB8(i, col);
}
}
אזהרות PVS-Studio:
- V560 חלק מביטוי מותנה תמיד נכון: 0x000000FF. nvi_image.cpp 170
- V560 חלק מביטוי מותנה תמיד נכון: 0x000000FF. nvi_image.cpp 171
- V560 חלק מביטוי מותנה תמיד נכון: 0x000000FF. nvi_image.cpp 172
- V560 חלק מביטוי מותנה תמיד נכון: 0x000000FF. nvi_image.cpp 173
אפשרות נכונה:
DWORD a = (קול >> 24) & 0x000000FF; DWORD b = (קול >> 16) & 0x000000FF; DWORD g = (קול >> 8) & 0x000000FF; DWORD r = (col >> 0) & 0x000000FF;
דוגמה נוספת לקוד מוזר:
VertexCache::VertexCache() ( VertexCache(16); )
אזהרת PVS-Studio: V603 האובייקט נוצר אך אינו בשימוש. אם ברצונך לקרוא לבנאי, יש להשתמש ב-"this->VertexCache::VertexCache(....)". vertexcache.cpp 6
במקום לקרוא לבנאי אחד מהאחר כדי לאתחל את המופע, אובייקט חדש מסוג מטמון קודקוד. כתוצאה מכך, האיברים של האובייקט שנוצר יישארו לא מאותחלים.
BOOL CActor::net_Spawn(CSE_Abstract* DC) ( .... m_States.empty(); .... )
אזהרת PVS-Studio: V530 יש להשתמש בערך ההחזר של הפונקציה "ריק". actor_network.cpp 657
המנתח מזהיר שהערך המוחזר על ידי הפונקציה אינו בשימוש. נראה שהמתכנת פישל בשיטות ריק()ו ברור(): ריק()לא מנקה את המערך, אבל בודק אם הוא ריק.
שגיאות כאלה מתרחשות לעתים קרובות בפרויקטים שונים. הבעיה היא שהשם ריק()לא מובן מאליו: יש שתופסים את זה כפעולה - הסרה. כדי למנוע אי בהירות כזו, עדיף להוסיף את הפעלים יש, הוא לתחילת השיטה: אכן, זה ריק()עם ברור()קשה לבלבל.
אזהרה דומה:
V530 נדרש להשתמש בערך ההחזר של הפונקציה "ייחודי". uidragdroplistex.cpp 780
size_t xrDebug::BuildStackTrace(EXCEPTION_POINTERS* exPtrs, char *buffer, size_t capacity, size_t lineCapacity) ( memset(buffer, capacity*lineCapacity, 0); .... )
אזהרת PVS-Studio: V575 הפונקציה "memset" מעבדת אלמנטים של "0". בדוק את הטיעון השלישי. xrdebug.cpp 104
כשמתקשרים memsetהטיעונים מתערבבים וכתוצאה מכך המאגר לא מאופס לאפס, כפי שהתכוונו במקור. שגיאה כזו יכולה לחיות בפרויקט במשך זמן רב מאוד, מכיוון שקשה מאוד לזהות אותה. במקומות כאלה, מנתח סטטי בא לעזרתו של מתכנת.
שימוש נכון memset:
memset(buffer, 0, capacity*lineCapacity);
השגיאה הבאה קשורה לביטוי לוגי מורכב שגוי.
void configs_dumper::dumper_thread(void* my_ptr) ( .... DWORD wait_result = WaitForSingleObject(this_ptr->m_make_start_event, INFINITE); while (wait_result != WAIT_ABANDONED) ...| (wait)WAIT_result .AI=)
אזהרת PVS-Studio: V547 הביטוי הוא תמיד נכון. כנראה יש להשתמש באופרטור "&&" כאן. configs_dumper.cpp 262
ביטויים כמו "x != a || x != b" הם תמיד נכונים. סביר להניח, במקום האופרטור || האופרטור && היה מרומז.
תוכל לקרוא עוד על שגיאות בביטויים לוגיים במאמר "ביטויים לוגיים ב-C/C++. איך אנשי מקצוע עושים טעויות".
void SBoneProtections::reload(const shared_str& bone_sect, IKinematics* kinematics) ( .... CInifile::Sect &protections = pSettings->r_section(bone_sect); עבור (CInifile::SectCIt i=protections.Data.begin(); .Data.end() != i; ++i) ( string256 buffer; BoneProtection BP; .... BP.BonePassBullet = (BOOL) (atoi(_GetItem(i->second.c_str(), 2, buffer) )>0.5f); .... ) )
אזהרת PVS-Studio: V674 ה-"0.5f" מילולי מסוג "float" מושווה לערך מסוג "int". boneprotection.cpp 54
המנתח זיהה השוואה של ערך מספר שלם עם קבוע אמיתי. ייתכן שכאן, באנלוגיה, היה צריך להשתמש בפונקציה אטופ, אבל לא atoi, אחרת כדאי לשכתב את ההשוואה הזו כדי שהיא לא תיראה חשודה. עם זאת, רק המפתח שכתב את זה יכול לדעת בוודאות אם הדוגמה הזו שגויה או לא.
class IGameObject: Public Virtual IFactoryObject, Public Virtual ISpatial, Public Virtual ISheduled, Public Virtual IRenderable, Public Virtual ICollidable (public: .... Virtual u16 ID() const = 0; .... ) BOOL CBulletManager::test_callback(const collide::ray_defs& rd, אובייקט IGameObject*, פרמטרים LPVOID) ( bullet_test_callback_data* pData = (bullet_test_callback_data*) params; SBullet* bullet = pData->pBullet; if((object->ID() ==_id) bullet &&> (כדור->מרחק_זבוב
אזהרת PVS-Studio: V595 נעשה שימוש במצביע ה"אובייקט" לפני שהוא אומת כנגד nullptr. קווי בדיקה: 42, 47. level_bullet_manager_firetrace.cpp 42
בדיקת מצביע לְהִתְנַגֵדלמען שוויון nullptrמגיע לאחר דחוי object->ID(). במקרה מתי לְהִתְנַגֵדהוא nullptr, זה יקרוס את התוכנית.
#ifdef _EDITOR BOOL WINAPI DllEntryPoint(....) #else BOOL WINAPI DllMain(....) #endif ( switch (ul_reason_for_call) ( .... case DLL_THREAD_ATTACH: if (!strstr(GetCommandLine(), "-editor ")) CoInitializeEx(NULL, COINIT_MULTITHREADED); timeBeginPeriod(1); break; .... ) return TRUE; )
אזהרת PVS-Studio: V718 אין לקרוא לפונקציה "CoInitializeEx" מהפונקציה "DllMain". xrcore.cpp 205
בגוף DllMainאינך יכול להשתמש בחלק מפונקציות WinAPI, כולל CoInitializeEx.אתה יכול לאמת זאת על ידי קריאת תיעוד MSDN. אי אפשר לתת עצה חד משמעית כיצד לשכתב את הפונקציה הזו, אבל כדאי להבין שמצב כזה הוא מסוכן, מכיוון שהוא יכול להוביל למבוי סתום או להתרסקות.
טעויות בסדרי עדיפויות
int sgetI1(לא סימן char **bp) ( int i; if (flen == FLEN_ERROR) return 0; i = **bp; if (i > 127) i -= 256; flen += 1; *bp++; return i ;)אזהרת PVS-Studio: V532 שקול לבדוק את ההצהרה של דפוס "*pointer++". התכוון כנראה: "(*מצביע)++". lwio.c 316
השגיאה קשורה לשימוש בתוספת. למען הבהירות, אנו משכתבים את הביטוי הזה, וממקמים סוגריים:
*(bp++);
כלומר, תהיה תזוזה של אי תוכן בכתובת bp,אלא המצביע עצמו, שהוא חסר משמעות בהקשר הזה. מתחת לקוד יש קטעים של הטופס *bp += N, ולכן הגעתי למסקנה שזו טעות.
מיקום הסוגריים יעזור למנוע שגיאה כזו, שתהפוך את סדר החישובים למובנה יותר. גם טכניקה טובה היא להשתמש constלטיעונים שלא צריכים להשתנות.
אזהרות דומות:
- V532 שקול לבדוק את ההצהרה של דפוס "*pointer++". התכוון כנראה: "(*מצביע)++". lwio.c 354
- V532 שקול לבדוק את ההצהרה של דפוס "*pointer++". התכוון כנראה: "(*מצביע)++". lwob.c 80
אזהרת PVS-Studio: V563 ייתכן שענף "אחר" זה חייב לחול על הצהרת "אם" הקודמת. hit_memory_manager.cpp 368
בקטע הזה, הסניף אַחֵרשייך לשני אםבשל האסוציאטיביות הימנית שלו, שאינה זהה לעיצוב קוד. למרבה המזל, מקרה זה אינו משפיע על פעולת התוכנית, עם זאת, זה יכול לסבך את תהליך איתור באגים ובדיקה.
ההמלצה פשוטה - מניחים פלטה מתולתלת בענפים מורכבים יותר או פחות.
void HUD_SOUND_ITEM::PlaySound(HUD_SOUND_ITEM& hud_snd, const Fvector& position, const IGameObject* אב, bool b_hud_mode, bool looped, u8 index) ( .... hud_snd.m_activeSnd->snd.set_volume(hudactive_sndhudmode *volume_sndhudmode) psHUDSoundVolume:1.0f); )
אזהרת PVS-Studio: V502 אולי האופרטור "?:" פועל בצורה שונה ממה שהיה צפוי. לאופרטור "?:" יש עדיפות נמוכה יותר מאופרטור "*". hudsound.cpp 108
לאופרטור המותנה המשולש יש עדיפות נמוכה יותר מכפל, ולכן סדר הפעולות הוא:
(hud_snd.m_activeSnd->volume * b_hud_mode)?psHUDSoundVolume:1.0f
ברור שהקוד הנכון צריך להיראות כך:
hud_snd.m_activeSnd->volume * (b_hud_mode?psHUDSoundVolume:1.0f)
ביטויים המכילים אופרטור שליש הם מרובים אחרתענפים או פעולות AND / OR הם המקרים שבהם עדיף לשים סוגריים נוספים.
אזהרות דומות:
- V502 אולי האופרטור "?:" עובד בצורה שונה ממה שהיה צפוי. לאופרטור "?:" יש עדיפות נמוכה יותר מאופרטור "+". uihudstateswnd.cpp 487
- V502 אולי האופרטור "?:" עובד בצורה שונה ממה שהיה צפוי. לאופרטור "?:" יש עדיפות נמוכה יותר מאופרטור "+". uicellcustomitems.cpp 106
השוואות נוספות
void CDestroyablePhysicsObject::OnChangeVisual() ( if (m_pPhysicsShell)( if(m_pPhysicsShell)m_pPhysicsShell->Deactivate(); .... ) .... )אזהרת PVS-Studio: V571 בדיקה חוזרת. התנאי "if (m_pPhysicsShell)" כבר אומת בשורה 32. destroyablephysicsobject.cpp 33
דוגמה זו בודקת פעמיים m_pPhysicsShell. סביר להניח שהבדיקה השנייה מיותרת.
void CSE_ALifeItemPDA::STATE_Read(NET_Packet &tNetPacket, גודל u16) ( .... if (m_wVersion > 89) if ((m_wVersion > 89)&&(m_wVersion< 98))
{
....
}else{
....
}
}
אזהרת PVS-Studio: V571 בדיקה חוזרת. התנאי "m_wVersion > 89" כבר אומת בשורה 987. xrserver_objects_alife_items.cpp 989
קוד מוזר מאוד. האם שכחו את הביטוי כאן אחר כך if (m_wVersion > 89)או סדרה שלמה אחרת-אם. שיטה זו דורשת התייחסות מפורטת יותר של מפתח הפרויקט.
void ELogCallback(void *context, LPCSTR txt) ( .... bool bDlg = ("#"==txt)||((0!=txt)&&("#"==txt)); if (bDlg) ( int mt = ("!"==txt)||((0!=txt)&&("!"==txt))?1:0; .... ) )
אזהרות PVS-Studio:
- V590 שקול לבדוק את הביטוי "(0 != txt) && ("#" == txt)". הביטוי מוגזם או מכיל טעות הדפסה. elog.cpp 29
- V590 שקול לבדוק את הביטוי "(0 != txt) && ("!" == txt)". הביטוי מוגזם או מכיל טעות הדפסה. elog.cpp 31
bool bDlg = ("#"==txt)||("#"==txt); int mt = ("!"==txt)||("!"==txt)?1:0;
שגיאות בסוגי נתונים
Float CRenderTarget::im_noise_time; CRenderTarget::CRenderTarget() ( .... param_blur = 0.f; param_gray = 0.f; param_noise = 0.f; param_duality_h = 0.f; param_duality_v = 0.f; param_noise_fps = _1noise_scale param .f; im_noise_time = 1/100; im_noise_shift_w = 0; im_noise_shift_h = 0; .... )
אזהרת PVS-Studio: V636 הביטוי "1/100" נוצק באופן מרומז מסוג "int" לסוג "float". שקול להשתמש בקאסט מסוג מפורש כדי למנוע אובדן של חלק חלקי. דוגמה: כפול A = (כפול)(X) / Y;. gl_rendertarget.cpp 245
הערך של הביטוי 1/100 הוא 0 מכיוון שמתבצעת פעולת חלוקת מספרים שלמים. כדי לקבל את הערך 0.01f, אתה צריך להשתמש מילולי אמיתי, לשכתב את הביטוי: 1/100.0f. למרות שייתכן שהתנהגות זו נועדה על ידי המחבר, ואין כאן טעות.
CSpaceRestriction::merge(....) const ( .... LPSTR S = xr_alloc
אזהרת PVS-Studio: V579 הפונקציה strconcat מקבלת את המצביע וגודלו כארגומנטים. ייתכן שזו טעות. בדוק את הטיעון הראשון. space_restriction.cpp 201
פוּנקצִיָה strconcat, לוקח את אורך המאגר כפרמטר הראשון. בַּלָם סהכריז כ LPSTR, כלומר, כמצביע למחרוזת. גודל של (S)יהיה שווה לגודל המצביע בבתים, כלומר. sizeof(char *), לא מספר התווים במחרוזת. כדי לחשב את האורך, השתמש strlen(S).
class XRCDB_API MODEL ( .... u32 status; // 0=ready, 1=init, 2=building .... ) void MODEL::build (Fvector* V, int Vcnt, TRI* T, int Tcnt, build_callback * bc, void* bcp) ( .... BTHREAD_params P = ( this, V, Vcnt, T, Tcnt, bc, bcp ); thread_spawn(build_thread,"CDB-construction",0,&P); while (S_INIT = = status) Sleep(5); .... )
אזהרת PVS-Studio: V712 שימו לב שהמהדר עשוי למחוק מחזור זה או להפוך אותו לאינסוף. השתמש במשתנים נדיפים או בפרימיטיבים של סנכרון כדי להימנע מכך. xrcdb.cpp 100
המהדר יכול להסיר את הסימון S_INIT == סטטוסכאופטימיזציה, שכן המשתנה סטָטוּסלא השתנה בלולאה. כדי להימנע מהתנהגות זו, עליך להשתמש נָדִיףמשתנים או סוגים של סנכרון נתונים בין שרשורים.
אזהרות דומות:
- V712 שימו לב שהמהדר עשוי למחוק את המחזור הזה או להפוך אותו לאינסוף. השתמש במשתנים נדיפים או בפרימיטיבים של סנכרון כדי להימנע מכך. levelcompilerloggerwindow.cpp 23
- V712 שימו לב שהמהדר עשוי למחוק את המחזור הזה או להפוך אותו לאינסוף. השתמש במשתנים נדיפים או בפרימיטיבים של סנכרון כדי להימנע מכך. levelcompilerloggerwindow.cpp 232
אזהרת PVS-Studio: V547 ביטוי "squad->get_index(this) == u32(- 1)" הוא תמיד שקר. טווח הערכים של סוג תווים ללא סימן: . ai_rat.cpp 480
על מנת להבין מדוע הביטוי הזה תמיד שקרי, הבה נחשב את הערכים של האופרנדים הבודדים. u32(-1) הוא 0xFFFFFFFF או 4294967295. הסוג המוחזר על ידי השיטה squad->get_index(....), - u8, כך שהערך המקסימלי שלו הוא 0xFF או 255, שזה בהחלט פחות מ-u32(-1). בהתאם, ערכה של השוואה כזו תמיד יהיה שֶׁקֶר. קל לתקן את הקוד הזה על ידי שינוי סוג הנתונים ל-u8:
squad->get_index(this) == u8(-1)
אותו אבחון עובד עבור השוואות מיותרות של משתנים ללא סימנים:
מרחב השמות ALife ( typedef u64 _TIME_ID; ) ALife::_TIME_ID CScriptActionCondition::m_tLifeTime; IC bool CScriptEntityAction::CheckIfTimeOver() ( return((m_tActionCondition.m_tLifeTime >= 0) && ((m_tActionCondition.m_tStartTime + m_tActionCondition.m_tLifeTime)< Device.dwTimeGlobal));
}
אזהרת PVS-Studio: V547 ביטוי "m_tActionCondition.m_tLifeTime >= 0" הוא תמיד נכון. ערך הסוג הלא חתום הוא תמיד >= 0. script_entity_action_inline.h 115
מִשְׁתַנֶה m_tLifeTimeהוא ללא סימן, אז הוא תמיד גדול או שווה לאפס. אם זו בדיקה נוספת או שגיאה בלוגיקה מוסתרת כאן, זה תלוי המפתח לשפוט.
אזהרה דומה:
V547 ביטוי "m_tActionCondition.m_tLifeTime< 0" is always false. Unsigned type value is never < 0. script_entity_action_inline.h 143
ObjectFactory::ServerObjectBaseClass * CObjectItemScript::server_object (קטע LPCSTR) const ( ObjectFactory::ServerObjectBaseClass *object = nullptr; try ( object = m_server_creator(section); ) catch(std::exception e) ( Msg("Exception ] הועלה בעת יצירת אובייקט שרת מ- " "מקטע [%s]", e.what(),section); return (0); ) .... )
אזהרת PVS-Studio: V746 סוג חיתוך. חריג צריך להיתפס לפי הפניה ולא לפי ערך. object_item_script.cpp 39
פוּנקצִיָה std::exception::what()הוא וירטואלי וניתן להגדיר אותו מחדש במחלקות בירושה. בדוגמה זו, החריג נתפס לפי ערך, כך שמופע המחלקה יועתק וכל המידע על הסוג הפולימורפי יאבד. דבר אל מה()במקרה כזה זה חסר טעם. יש לתפוס את החריג באמצעות הפניה:
catch(const std::exception& e) (
שונות
void compute_cover_value (....) ( .... float value ; .... if (value< .999f) { value = value; } .... }אזהרת PVS-Studio: V570 המשתנה "ערך" מוקצה לעצמו. compiler_cover.cpp 260
מִשְׁתַנֶה ערךמוקצה לעצמו. למה לעשות את זה לא ברור. אולי היה צריך לתת לזה משמעות אחרת.
void CActor::g_SetSprintAnimation(u32 mstate_rl, MotionID &head, MotionID &torso, MotionID &legs) ( SActorSprintState& sprint = m_anims->m_sprint; bool jump = (mstate_rl&mcFall) || (mstate_rl&rl&mcFall) || (mstate_rl)&rlanding_(mcstating_rl)&mstatat | _rl&mcL anding2) | | (mstate_rl&mcJump); .... )
אזהרת PVS-Studio: V501 ישנם תתי-ביטויים זהים "(mstate_rl & mcLanding)" משמאל ומימין ל-"||" מַפעִיל. actoranimation.cpp 290
סביר להניח שזו רק בדיקה נוספת. mstate_rl & mcLanding, אבל לעתים קרובות אזהרות כאלה מאותתות על שגיאה בלוגיקה וערכי ה-enum שלא נבדקו.
אזהרות דומות:
- V501 ישנם תתי-ביטויים זהים "HudItemData()" משמאל ומימין לאופרטור "&&". huditem.cpp 338
- V501 ישנם תתי-ביטויים זהים "list_idx == e_outfit" משמאל ומימין ל-"||" מַפעִיל. uimptradewnd_misc.cpp 392
- V501 ישנם ביטויי משנה זהים "(D3DFMT_UNKNOWN == fTarget)" משמאל ומימין ל-"||" מַפעִיל. hw.cpp 312
אזהרת PVS-Studio: V519 למשתנה מוקצים ערכים פעמיים ברציפות. אולי זו טעות. קווי בדיקה: 57, 58. relation_registry.cpp 58
המנתח זיהה ששני ערכים מוקצים בשורה למשתנה אחד. במקרה זה, זה נראה כאילו זה רק קוד מת ויש להסירו.
void safe_verify(....) ( .... printf("שגיאה חמורה (%s): לא הצליח לאמת נתונים\n"); .... )
אזהרת PVS-Studio: V576 פורמט שגוי. צפוי מספר שונה של ארגומנטים בפועל בעת קריאה לפונקציה "printf". צפוי: 2. נוכח: 1. entry_point.cpp 41
בתפקוד printfלא עברו מספיק ארגומנטים: הפורמט "%s" מציין שיש להעביר מצביע למחרוזת. מצב זה יכול להוביל לשגיאת גישה לזיכרון ולסיום תוכנית חריג.
0) התקן את Visual Studio 2008 SP1 (מקצועי או צוות, בניתי אותו בראשון), ה-service pack מארכיון engine.vc2008.fixed.rar מתאים רק לגרסה האנגלית של הסטודיו, לרוסית אתה יהיה צורך להוריד אותו בנפרד.
1) צור תיקיה בדיסק, יש בה תיקיה נוספת.
2) בתיקייה זו אנו מניחים רק את התיקיה engine.vc2008 מהארכיון "engine.vc2008.fixed - הפרויקט vs2008 שתיקנתי", אנחנו לא נוגעים בתיקייה SDK משם.
3) קח את תיקיית ה-SDK מהארכיון "stasvn\sources\engine.vc2005-2008(~1.6.02 benchmark) - מרץ 2010", מתיקיית המשנה מקורות.
שמנו אותו בתיקייה אחת אל engine.vc2008
4) כעת, נוסף על כך, אנו מדווחים על תיקיית SDK מארכיון engine.vc2008.fixed.rar, מסכימים להחליף את כל הקבצים
5) הורד שני ערכות SDK של DirectX מאתר האינטרנט של מיקרוסופט - מרץ 2009 ויוני 2010. (המשקל של כל אחד הוא כ-500 מגה-גב), אתה יכול להשתמש רק בגרסת 2009, אבל אז לא תוכל לבנות את xrRender_R4. (קישור: שגיאה קטלנית LNK1181: לא יכול לפתוח את קובץ הקלט "d3d11.lib"), ואם אתה משתמש רק ב-2010, המשחק לא יתחיל עם R4.
לאחר התקנת שני DX SDK, ודא שהם רשמו את הנתיבים שלהם לאולפן, קבצי SDK 2010 חייבים להיות לאחר 2009, כפי שמוצג באיור:
הדבר נכון גם למקטעים של קבצי הפעלה ו-Include files. אם יש לך שאלות כלשהן, חפש בגוגל "חיבור directx sdk visual studio 2008"
אם גרסאות ה-SDK שגויות (או שהיא לא מחוברת), היומן ישבע בהיעדר קבצים כמו d3dXX.lib \ .h)
אין צורך להעביר תיקיות מ-DirectX SDK שכבר מותקן לשום מקום. מספיק להגדיר את הנתיבים אליהם באופן גלובלי עבור הסטודיו (או עבור כל פרויקט באופן ידני)
הערה מ-loxotron: פשוט העתק ושנה את השם של d3d11_beta.lib ל-d3d11.lib בתיקייה עם ה-sdk הישיר, או אפילו טוב יותר, הורד והתקן את DX SDK אוגוסט 2009 ואל תתעסק עם גרסאות לא מתאימות.
6) לכל מקרה, אתה יכול גם להתקין SDK \ OpenALwEAX.exe, אבל אני לא בטוח שזה נחוץ באופן קריטי.
7) הפעל את הפרויקט דרך ..\CoP\Project\engine.vc2008\engine.sln. כאשר הוא נטען, בחלק העליון של האולפן, אנו משנים את מצב הבנייה מ-Debug_Dedicated (או כל אחר) ל-Release. לאחר מכן, בצד שמאל \ ימין תהיה רשימה של תיקיות עם קבצי מנוע, אנחנו צריכים, קודם כל, את התיקיה 3rd_party - לחץ לחיצה ימנית עליה ובחר Build \ Build.
אם הכל תקין, אז בסוף היומן למטה יכתוב על 11 פרויקטים מוצלחים (או המספר יהיה קטן יותר אם כמה פרויקטים כבר נבנו בעבר, היומן ידווח גם על "דילוג \ מעודכן" על כך) 0
אספתי לחלוטין את כל הפרויקטים ללא שגיאות. (אזהרות אינן נחשבות לשגיאות מן המניין)
8) באנלוגיה, מלמעלה למטה, ניתן לבנות Dlls אחרים, אין צורך לבנות את התיקיות editor\dedicated\utils\plugins - הן לא חלות על המנוע. בניית xrGame.dll ייקח הכי הרבה זמן. השאר מהירים מספיק.
אגב, אין צורך לאסוף את כל ה-DLL. אתה יכול רק צריך. כשהם מוכנים - צור תיקיית bin נקי בתיקיית המשחק. זרוק לשם את כל קבצי ה-dll שנוצרו (אתה יכול יחד עם .pdb). במידת הצורך, תוכל להעלות את הקבצים החסרים מה- RFP המקורי של bin (תיקון שני), אם המשחק דורש אותם. (כמו wrap_oal.dll)
התחלתי את המשחק מה-Stalker-COP.exe המקורי
אם הכל תקין, אז ביומן\קונסולה של המשחק, מבנה המשחק ותאריך הבנייה יצוינו בשורות הראשונות.
- תוֹכֶן
-
לאדה XRAY, יחד עם דגם Vesta, ניתן כעת לכנות התקווה והעמוד החדש של AvtoVAZ. המכוניות הללו הן שמייצגות את פני החברה וסבב חדש בפיתוחה. אין זה מפתיע שפיתוח ה-X-Ray האצ'בק החדש בוצע בזהירות רבה. יתר על כן, תשומת לב מיוחדת הוקדשה לא רק למראה, אלא גם למרכיב הטכני. והמנוע, כידוע, הוא "לב המכונית", ולכן המנועים תמיד היו בראש סדר העדיפויות של מהנדסי החברה.
תיאור קצר של מנועי לאדה X Ray.
רשימת מנועי לאדה X Ray
בסך הכל, ההאצ'בק יקבל שלושה מנועים, וכמה יחידות מקומיות דוללו עם אחד "חו"ל". רשימת מנועים:
מפרטים ומאפייני עיצוב
כל יחידות הכוח של הדגם החדש מודרניות למדי ועומדות בכל הקריטריונים העדכניים החלים על פלח זה.
VAZ-21129
זהו מנוע בנזין ביתי שיוצר כבר זמן רב ומותקן גם בדגמי AvtoVAZ אחרים, כולל לאדה וסטה.
- נפח - 1,596 ס"מ³;
- תצורה - בשורה;
- מיקום - רוחבי;
- מספר צילינדרים - 4;
- מספר שסתומים - 16;
- הספק מרבי - 106 ליטר. עם. (78.2 קילוואט) ב-5,800 סל"ד;
- מומנט מרבי - 148 ננומטר ב-4,200 סל"ד;
- כונן תזמון - רצועה;
- דינמיקה - 11.4 שניות;
- מהירות מרבית - 176 קמ"ש;
- יחס דחיסה - 11 יחידות;
- קוטר צילינדר - 82 מ"מ;
- מהלך בוכנה - 75.6 מ"מ;
- תקנים סביבתיים - יורו-5;
- דלק - AI-95;
- צריכת דלק (עיר / כביש מהיר / מצב מעורב) - 9.3 ליטר / 7.2 ליטר / 5.9 ליטר.
- פוטנציאל - 400+ HP. עם.
- ללא אובדן משאב - 150 ליטר. עם.
מנוע X Ray VAZ 21129.
מנוע Lada X Ray VAZ-21129 נוצר על בסיס מנוע סדרת VAZ-21127, המיועד לדגם פריורה. בוצעו בו מספר שינויים ושיפורים. המשמעותיים ביותר הם השימוש בסט דשים בסעפת היניקה, שדרכם משתנה אורכו, מה שמבטיח פעולה במהירויות נמוכות וגבוהות במצב האופטימלי. בנוסף, בתכנון המנוע, המהנדסים נטשו את חיישן זרימת האוויר ההמונית. במקום זאת, סופקו שני מכשירים נוספים - אלו הם חיישני טמפרטורת אוויר וחיישני לחץ מוחלט. פתרון כזה מספק אפשרות לשליטה מלאה יותר על התערובת הדליקה, וגם מבטל את הסבירות של מהפכות "שחייה" במצב סרק.
מאחורי הנפח הרגיל של 1.6 ליטר ו-16 שסתומים, ישנם ניואנסים רבים.
גם בתכנון המנוע יושמו פתרונות חדשים בנושא המתלה של היחידה המותקנת על גבי תת-מסגרת ובוצעו שינויים במערכות הפליטה והיניקה. אמצעים אלו הבטיחו למנוע, בין היתר, ירידה ברעש הפעולה, כמו גם ירידה ברעילות ובצריכת הדלק.
הסיפור הזה מפרט את מנוע VAZ 21129:
HR16DE
מנוע רנו-ניסאן H4M-HR16DE סופק על ידי שותפי AvtoVAZ מחברת אליאנס רנו ניסאן. הוא מיוצר במשך זמן רב והותקן בהצלחה בדגמים רבים אחרים של חברות צרפתיות ויפניות - אלה הם ניסאן טיידה, ניסאן וינגרוד, ניסאן נוט, לאדה וסטה, ניסאן קשקאי ואחרות.
מנוע ה-X-Ray HR16DE במלוא הדרו.
- נפח - 1,598 ס"מ³;
- תצורה - בשורה;
- מיקום - רוחבי;
- מספר צילינדרים - 4;
- מספר שסתומים - 16;
- סוג כוח - הזרקת דלק מבוזרת עם בקרה אלקטרונית;
- הספק מרבי - 110 ליטר. עם. (81 קילוואט) ב-5,500 סל"ד;
- מומנט מרבי - 150 ננומטר ב-4,000 סל"ד;
- כונן תזמון - שרשרת;
- דינמיקה - 11.1 שניות;
- מהירות מרבית - 181 קמ"ש;
- יחס דחיסה - 10.7 יחידות;
- קוטר צילינדר - 76 מ"מ;
- מהלך בוכנה - 88 מ"מ;
- תקנים סביבתיים - יורו-4/5;
- דלק - AI-92/95;
- צריכת דלק (עיר / כביש מהיר / מצב מעורב) - 8.9 ליטר / 6.8 ליטר / 5.6 ליטר.
- פוטנציאל - 150+ HP. עם.
- ללא אובדן משאב - 125 ליטר. עם.
ליחידת הכוח הזו לאדה X Ray יש מספר תכונות. המאפיין ביותר הוא הפחתת ההספק - אם בדגמים אחרים הוא משתנה בין 114 ל-118 כ"ס. s., אז במקרה של X Ray זה הצטמצם ל-110 ליטר. עם., שנעשה על מנת להתאים את המנוע הזה למציאות של רוסיה ושאר מדינות חבר העמים.
השימוש בשרשרת בהנעת תזמון הופכת אותה א-פריורית לאמינה יותר.
לכן, במקום החגורה המוכרת לבעלי לאדה, משתמשים בשרשרת בעיצובה, מה שמגביר משמעותית את האמינות, מכיוון שהיא לא נשברת, והיא לא נמתחת בקרוב. אין היום מפצים הידראוליים אופנתיים - במקום אותם יש שסתומים מתכווננים רגילים. עם זאת, הליך כוונון הדוחף לא יידרש לפני 80,000 - 100,000 ק"מ. בין שאר המאפיינים, ניתן לייחד את השימוש בקומפלקס לשינוי תזמון השסתומים, קיבוע מחליף הפאזות ישירות על פיר היניקה, נוכחות של זוג חרירים בכל צילינדר, וגם שימוש במצערת מסוג אלקטרוני.
הדחייה של מרימים הידראוליים הופכת לצורך להתאים את השסתומים.
בנוסף, בתהליך המודרניזציה צומצמו מחווני החיכוך של רכיבי יחידת הכוח של Lada X Ray. זה הושג באמצעות שימוש בציפוי פלואור במוביל השרשרת, ליטוש (מראה), כמו גם עיבוד של גל הארכובה. במצב סרק צומצמו ההפסדים (דלק ושאיבה), דבר המובטח על ידי הגדלת זווית ההמרה C-VTC, וכן על ידי חישוב מחדש של הבקרה (זמנית).
VAZ-21179
זהו מנוע ביתי חדש, שפותח במיוחד עבור דגמי ה-X Ray ו-Vesta. יחידת הכוח של סדרת VAZ 21126 נבחרה כבסיס לה, שממנה הושאל בלוק הצילינדר. עם זאת, כאן מסתיים הדמיון ביניהם.
החזק ביותר בשורה הוא מנוע VAZ-21179.
- נפח - 1,774 ס"מ³;
- תצורה - בשורה;
- מיקום - רוחבי;
- מספר צילינדרים - 4;
- מספר שסתומים - 16;
- סוג כוח - הזרקת דלק מבוזרת עם בקרה אלקטרונית;
- הספק מרבי - 122 ליטר. עם. (90 קילוואט) ב-6,050 סל"ד;
- מומנט מרבי - 170 ננומטר ב-3,750 סל"ד;
- כונן תזמון - רצועה;
- מספר גלי זיזים - 2 (סוג DOHC);
- דינמיקה - 10.9 שניות;
- מהירות מרבית - 186 קמ"ש;
- יחס דחיסה - 9.8 יחידות;
- מהלך בוכנה - 84 מ"מ;
- תקנים סביבתיים - יורו-5;
- דלק - AI-95;
- צריכת דלק (עיר / כביש מהיר / מצב מעורב) - 8.6 ליטר / 6.8 ליטר / 5.8 ליטר.
- פוטנציאל - אין נתונים;
- ללא אובדן משאב - ללא נתונים.
מנוע ה-Lada X Ray הזה שונה בצורה מדהימה ממנועי VAZ אחרים. בתכנון יחידת הכוח נעשה שימוש בשסתום מצערת חדש, נטול הנעה מכנית, ראש הצילינדר צויד בשסתומים חדשים (קלי משקל) מבית Mahle, ולווסת הפאזה הובאו תעלות שמן נוספות.
שסתום המצערת נטול הנעה מכנית.
מהלך בוכנה גדול יותר הבטיח עלייה בנפח העבודה, גל הארכובה מאופיין ברדיוס ארכובה מוגדל, ותעלות היניקה של האספן מבית Ecoalliance (רוסיה) מוגדלות בקוטר ל-39 מ"מ. חיישן החמצן מסופק על ידי Bosch, ומשאבת החמצן מסופקת על ידי GMB (קוריאה). אותה חברה קוריאנית אחראית לאספקת משאבת הנפט בעלת הביצועים הגבוהים.
גל ארכובה גדל ברדיוס הארכובה.
קבוצת מוט חיבור ובוכנה (סוג קל משקל) מגיעה מהמותג Federal Mogul, וחברת INA הגרמנית מספקת מותחני רצועות שיניים אוטומטיים המצוידים בזוג גלילים. מסילת הדלק נרכשת מקונצרן קונטיננטל. החרירים שלו מתאפיינים בביצועים מוגברים, כתוצאה מכך התרסיס מותאם במיוחד לעבודת מנוע ה-X Ray החדש.
גלי הזיזים עצמם מגיעים מקוריאה.
כפי שניתן לראות, למרות פיתוח רוסי, חלק ניכר מהרכיבים נרכש מחברות זרות.
הסרטון מציג את תהליך הרכבת מנוע 1.8 ליטר חדש עבור Lada X Ray: