موتورهای بازی سازی چگونه کار میکنند؟ (قسمت ۱)

سلام . من محمد مهدی نوروزی قصد دارم با سازوکار های موتورهای بازی سازی و گرافیکی بیشتر آشنا بشم.پس تصمیم گرفتم بشینم و مثل یک پسر خوب یک کتاب انتخاب کنم و بخونمش تا با مسایل گوناگون موجود در دنیای گرافیکی و ۲بعدی و ۳بعدی بیشتر آشنا بشم.این کار رو فعلاً برای سرگرمی انجامش میدم و محرکم که سرچشمه این حرکت شد که برم سراغ این چنین مسایلی چیزی نبود جز metaverse.تصمیم گرفتم هروقت بخشی از کتاب رو خوندم بیام و درس پس بدم.قول نمیدم هر شب یا به طور منظم این اتفاق بیوفته ولی همه تلاشمو میکنم به طور منظم پیش برم و چیزای جدیدی رو که یاد میگیرم به اشتراک بگذارم.اولین مطلب آشنایی با بردارهاست.یک بردار جهت و اندازه داره به شکلی که اگر دو بردار جهت و اندازه یکسان داشته باشن پس با هم برابرن.برای نمایش بردارها از دستگاه‌های مختصات مختلف میشه استفاده کرد.ما از دستگاه معروف کارتزینکه از قبل هم باهاش آشناییم و میدونیم سه جهت x , y , z رو داره استفاده خواهیم کرد.بردار ها میتونن ابعاد زیادی داشته باشن.برای مثال بردار زیر رو فرض میکنیمv = ( v1 , v2 , … , vn)در بردار بالا ما n بعد داریم.و مقدار مربوط به هر بعد رو میتونیم به vi که اینجا منظوراز i شماره بعد هست نسبت بدیم.از اونجایی که میخوایم دنیای ۲ بعدی و ۳ بعدی رو شبیه سازی کنیم پس نیاز داریم بردارهای ۲بعدی و ۳بعدی رو تعریف کنیم.من برای پیاده‌سازی بردارها از زبان برنامه نویسی rust استفاده میکنم.ابتدا یک پروژه جدید رو آغاز میکنم:cargo new wmbهمچنین نیازه که کتابخانه rand رو به پروژه اضافه کنیم:cargo add randو شروع میکنم به تعریف کردن بردارها:برای بردارهای ۲بعدی و ۳بعدی به ترتیب فایل‌های vector2d و vector3d رو ایجاد میکنم.کدهای زیر رو داخل فایل vector2d مینویسیم:pub struct Vector2D {x: f32,y: f32,}impl From<(f32, f32)> for Vector2D {fn from(tup: (f32, f32)) -> Self {Self { x: tup.0, y: tup.1 }}}impl From<&[f32; 2]> for Vector2D {fn from(arr: &[f32; 2]) -> Self {Self {x: arr[0],y: arr[1],}}}impl From<[f32; 2]> for Vector2D {fn from(arr: [f32; 2]) -> Self {Self {x: arr[0],y: arr[1],}}}impl Default for Vector2D {fn default() -> Self {Self {x: Default::default(),y: Default::default(),}}}impl Vector2D {pub fn create(x: f32, y: f32) -> Self {Self { x, y }}}#[cfg(test)]mod tests {use super::*;use rand::Rng;#[test]fn create_test() {let mut rng = rand::thread_rng();let x = rng.gen::<f32>();let y = rng.gen::<f32>();let vec = Vector2D::create(x, y);assert_eq!(x, vec.x);assert_eq!(y, vec.y);}#[test]fn from_tup_test() {let mut rng = rand::thread_rng();let x = rng.gen::<f32>();let y = rng.gen::<f32>();let vec: Vector2D = (x, y).into();assert_eq!(x, vec.x);assert_eq!(y, vec.y);}#[test]fn from_arr_borrowed_test() {let mut rng = rand::thread_rng();let x = rng.gen::<f32>();let y = rng.gen::<f32>();let vec: Vector2D = (&[x, y]).into();assert_eq!(x, vec.x);assert_eq!(y, vec.y);}#[test]fn from_arr_owned_test() {let mut rng = rand::thread_rng();let x = rng.gen::<f32>();let y = rng.gen::<f32>();let vec: Vector2D = [x, y].into();assert_eq!(x, vec.x);assert_eq!(y, vec.y);}}همچنین برای پیاده‌سازی Vector3D میتونیم از کدهای Vector2D استفاده کنیم بهشکلی که یک بعد z به تعریف اصلی اضافه میشه و همچنین باید هنگام تبدیلات وتست ها بعد جدید رو درگیر کنیم.این کار رو به شما میسپارم.گیتهاب پروژهکانال تلگرامعضویت تو کانال تلگرامی به شما کمک میکنه خیلی زودتر به مطالب دست پیدا کنید و همچنین میتونید سوالاتونو از اون طریق بپرسید.کاری از محمد مهدی نوروزی