Bu, “The Impatient Programmer’s Guide to Bevy and Rust: Build a Video Game from Scratch” adlı Rust-Bevy tutorial seriyasının 1-ci hissəsidir. Bu layihənin yeni versiyaları ilə bağlı yeni məlumatlar təqdim olun.Bu bölmənin kodu buradadır. Qrupumuzun yanına daxil olun Hazırda burada At the end of this chapter, you’ll be able to achieve the results in the GIF below: Tədbirlər Setmə Setmə Əgər qurulmamışsanız Buna baxmayaraq, lütfen Bunu qurmaq üçün. Rüstəm Resmi yol göstəricisi Create a fresh project: cargo new bevy_game cd bevy_game Open and add Bevy: Cargo.toml [dependencies] bevy = "0.16.1" Mən düşünürəm ki, sizin JavaScript və ya Python kimi bir dili var. Sistemlərdə düşünmək Oyunçunun keyboard girişindən çıxmasına imkan verən basit bir oyun qurmaq üçün nə ehtiyacımız var? Dünya sistemi: Oyunçunun hərəkət edə biləcəyi bir oyun dünyası yaratmaq. Giriş sistemi: Keyboard girişini izləyin və oyunçunun hareketinə çevirin. Yukarıda deyilən model oyunların qurulması, yaratma / qurmaq və oyun dünyasının entitetlərini dəyişdirmək və yeniləməkdə çox yayılmışdır. VVD - Hollandiyada futbolçu bu adla tanımır, orada VVD daha çox mərkəz-sağı təmsilən edən siyasi partiyanın adının qısaltması kimi bilinir - artıq sorğu-suala ehtiyacı olmayan ulduzdu. Güncellemə: Düşmənləri oyunçuya yönəltmək, düşmənlərin toplarla vurulmadığını, ölü düşmənləri çıxartmaq və yeni düşmənlər doğurmaq. İndi bizdə bu tip problemlər var Bu prinsiplər Bevy-i həm güclü, həm də anlayışlılaşdırır - bu konsepti anladığınızda, bevy ilə inşa etmək daha asanlaşır. setup and update system “Settings” adlanan bir funksiya düşünün ki, bu sizi “komandalar” adlandırır və sizə istədiyiniz hər şeyi yaratma və ya yaratma imkanını verir. // Pseudo code, doesn't compile fn setup(mut commands: Commands) { // Create anything you want commands.spawn() } What’s mut? VVD - Hollandiyada futbolçu bu adla tanımır, orada VVD daha çox mərkəz-sağı təmsilən edən siyasi partiyanın adının qısaltması kimi bilinir - artıq sorğu-suala ehtiyacı olmayıb. Xatırladaq ki, “Rust” bu bilgiləri bütün bug-ləri önləmək üçün istifadə edir. mut mut Şirkət ? And what’s this mut commands: Commands Bu, oyun dünyasına şeyləri ekləməyə imkan verir.Rust açıq tipləri sevir, bu yüzden Bu problemin nəticəsi ilə bağlı bir çox problemlər var, lakin bu problemlər həll olunmalıdır. :Commands What’s a type? Bir tip Rust-a nə tür bir qiymətlə işləyirsiniz – sayı, tekst, zamanlayıcılar, Bevy komandaları və s. Bir dəfə kompilator tipini bildikdən sonra, onun üzərində etdiyiniz hər bir işin anlamlı olduğunu kontrol edə bilər. Isn’t this too much work? Bu, hatalardan qaçırır və performansınızla kömək edir, bəlkə: Bir sayıya bir şəriət qoymaya çalışırsanız, kompilator oyunu çalışdırmadan əvvəl sizi durdurur. A və "Rust" yalnız iki sayıdır, bu yüzden Rust tam olaraq iki sayı saxlayır, heç bir sürpriz ekstra yer yoxdur, bu, oyun entitetləri minlərlə olduğunda şeyləri sürətləndirir. Vec2 "Vec2" objektini JavaScript və ya Python vasitəsilə yaratdığınızda, yalnız iki sayı depolayırsınız. "Runtime" tip metadata, özəllik bilgiləri və prototip referanslarını daxil edir - basit 8-baitli məlumat strukturunu ~48-baitlik memoriaya çevirir. Rust-un tip sistemi kompilasiya vaxtında işləyir. İki f32 sahəsi ilə bir Vec2 strukturu açıqladığınızda, yalnız 8 bayt, başqa metadata yoxdur. 1000 oyun varlıqları ilə, bu fərq dramatik olur: Language Memory Usage Overhead Rust 8KB None Dynamic language ~48KB+ 6x overhead Rüstəm 8 kq heç Dinamik dil 48 kB daha çox 6x üstündə Daha kiçik, öngörülə bilmə layoutları daha yaxşı CPU cache istifadə anlamına gelir, bu doğrudan hər bir çerçevədə minlərlə entitet işlədiyiniz oyunlarda daha sürətli çərşənbə qiymətlərinə çevrilir. kompilator oyununuzu çalışdırmaqdan əvvəl tip hatalarını yaxalayır və qısa bellek paketi onu sürətləndirir. Kameranın qurulması What should we setup first? Bizə bir kameraya ehtiyac var, çünki heç bir şey ekranda bir olmadan görünür. //Pseudo code, don't use this yet fn setup(mut commands: Commands) { commands.spawn(Camera2d) } What’s Camera2d? “Bevy”in 2D kamera paketidir.Onu saxlayın və 2D sahnənizin hazır görünüşünü alırsınız. Camera2d What’s a bundle? VVD - Hollandiyada futbolçu bu adla tanımır, orada VVD daha çox mərkəz-sağı təmsilən edən siyasi partiyanın adının qısaltması kimi bilinir. Bu, pozisyonu, teksturi, rəng tonu və görünürlükləri dəstəkləyir; bu paket bir çağırışda bir sprit entiteti verir. SpriteBundle Bizim funksiyamızı qeyd etmək Başlamaq üçün start-up funksiyasına baxmalıyıq. Güncellemə Növbəti kod src/main.rs // Replace your main.rs with the following code. use bevy::prelude::*; fn main() { App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .run(); } fn setup(mut commands: Commands) { commands.spawn(Camera2d); } What’s bevy::prelude? Bir neçə ildir ki, futbolçuların başlanğıcı ilə bağlı problemlər var. və Mütəxəssislər, matematik yardımçıları və s. bevy::prelude App Commands What’s App::new()…? Oyunu yaradıb. Ətraflı məlumatlar, audio və digər sistemlər Start-up funksiyalarımıza baxın və Əməliyyatın başlanğıcı ilə bağlı problemlər var. App::new() add_plugins(DefaultPlugins) add_systems(Startup, setup) run() Why register a startup function? What does it do? Biz ilk baxışdan əvvəl bir dəfə start-up sistemləri çalışdırırıq, kameraları, oynatıcıları və digər şeyləri açdıqdan sonra var olması lazım olan şeyləri qurmaq üçün istifadə edirik. What’s bevy main loop? Start-updan sonra, Bevy ana çöküşünə girir: içkiləri soruşur, sistemlərinizi sürətləndirir, dünyanı güncəlir və bir çöküş göstərir. Onu sürürük cargo run “Yup, biz yalnız kamera qurduq, şimdi oyunçumuza əlavə edəcəyik. Oyunçunun qurulması Artıq bizim oyunçularımız var! və Əvvəla, bu, hər şeyin ilə Bu sistemlərlə işləmək mümkündür. Setup System Update System Entity Components Xatırladaq ki, bir entitet təkcə bir ID-yə (təkcə bir sosial təhlükəsizlik numarası kimi) və komponentlərə bağlı məlumatlar kimi gedir.Onun üçün oyunçumuz üçün, hərəkət hündürlüyü, sağlığı, ya da xüsusiyyətləri kimi komponentlərə ehtiyacımız var. . struct “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”ndadır. Xatırladaq ki, futbolçularımız bu problemləri həll edə bilərlər, lakin futbolçularımız bu problemləri həll edə bilərlər. struct Player // Place this before main function in main.rs #[derive(Component)] struct Player; Why tag? Sonraki İçerikDünyanın bir çox ölkələrində işləmək lazımdır – VİDEO Yalnız heroimizə bağlıdır, sistemlər Bevy-yə “Mənə Player tag-ı olan entiteti verin” deyə soruşur və yalnız o biri ilə işləyir. Player What’s this #[derive(component)]? VVD - Hollandiyada futbolçu bu adla tanımır, orada VVD daha çox mərkəz-sağı təmsilən edən siyasi partiyanın adının qısaltması kimi bilinir - artıq sorğu-suala ehtiyacı olmayan ulduzdu. Avtomobillərin təchizatı və təchizatı aparılmalıdır. Xatırladaq ki, bu, bizim üçün çox vacibdir, lakin bizim üçün çox vacibdir. derive #[derive(Component)] Player What’s a component, and why should the player be a component? Bir komponent bir entitetə bağlı bir məlumat parçasıdır. pozisyon, sürət, sağlıq, və hətta “bu oyunçu” fikrinin hamısı komponentlərdə yaşayır. Daha sonra bu entitet üçün sorğu-sual edə bilərik, daha çox komponent (sağlamlıq və ya inventar kimi) daxil edə bilərik və Bevy sistemlərinin yeniləməyə ehtiyacı olan entitetləri seçəcəyik. Player Hazırda biz “@” simbolu ilə ekranda karakterimizi göstərəcəyik. // Replace existing setup function in main.rs with the following code fn setup(mut commands: Commands) { commands.spawn(Camera2d); // Code Update Alert // Append the following lines to your setup function. commands.spawn(( Text2d::new("@"), TextFont { font_size: 12.0, font: default(), ..default() }, TextColor(Color::WHITE), Transform::from_translation(Vec3::ZERO), Player, )); } Bir neçə ildir ki, bu, bir neçə ildir ki, bir neçə ildir ki, bir neçə ildir ki, bir neçə ildir ki, bir neçə ildir ki, bir neçə ildir ki, bir neçə ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir. Bu da entitetin tanımlanmasını təmin edir. commands.spawn(( ... )) Player What’s a tuple? “Rust” hər bir pozisyonu izləyib, belə ki, hər bir pozisyonu izləyib. İki ildir ki, bir-birinə bir-birini qoymaq lazım deyil. (Text2d::new("@"), TextColor(Color::WHITE)) Whats an entity? Xatırladaq ki, “Bevy”in komponentləri bir-birinə bağlamaq üçün istifadə etdiyi tək bir ID-dir, amma bir dəfə komponentləri bağladığınızda bu ID oyun dünyasında bir şey göstərir. Hər bir paket özü ilə yeni bir entitet və listə bölünən komponentlər yaratır, ki, bu da belə görünür: Entity Components it carries #42 Camera2d #43 , , , , Text2d("@") TextFont TextColor Transform Player #42 Baxış Camera2d # 43 Baxış və və və və Text2d("@") TextFont TextColor Transform Player Bir neçə saat sonra, bu varlıqlar dünyada yaşayır, sistemlər onları götürdükləri etiketlər (komponentlər) ilə ortaya çıxara bilərlər. Biz bunu daha sonra belə şeylər etmək və ya onları canlandırmaq, ya da onları düşmənlərə hücum etmək kimi istifadə etmək istəyirik. Oyunçuların aktivliyi Artıq bizim yaradıcılığımızı for player movement! Think about what we need to move a player: Update System Təsadüfi: Həyatın nə olduğunu bilmək Qiyamət vaxtı: Qiyamət vaxtına baxmayaraq Oyunçunun pozisyonu - həqiqətən, oyunçunu dəyişmək üçün Başqa oyun motorlarında, bu sistemləri bir-birinə manual olaraq bağlamaq üçün vaxt ayırırsınız.Ancaq burada Bevy'in büyüsü var - yalnız funksiyalarınızda ehtiyacınız olan şeyləri soruşursunuz, və Bevy otomatik olaraq bunu təmin edir! Moving Player funksiyasını yazırıq. // Append this code to main.rs fn move_player( // "Bevy, give me keyboard input" input: Res<ButtonInput<KeyCode>>, // "Bevy, give me the game timer" time: Res<Time>, // "Bevy, give me the player's position" mut player_transform: Single<&mut Transform, With<Player>>, ) { let mut direction = Vec2::ZERO; if input.pressed(KeyCode::ArrowLeft) { direction.x -= 1.0; } if input.pressed(KeyCode::ArrowRight) { direction.x += 1.0; } if input.pressed(KeyCode::ArrowUp) { direction.y += 1.0; } if input.pressed(KeyCode::ArrowDown) { direction.y -= 1.0; } if direction != Vec2::ZERO { let speed = 300.0; // pixels per second let delta = direction.normalize() * speed * time.delta_secs(); player_transform.translation.x += delta.x; player_transform.translation.y += delta.y; } } What’s Res? Xatırladaq ki, bu, bir neçə ildir, bir neçə ildir, bir neçə ildir, bir neçə ildir, bir neçə ildir. gives you the game’s master clock, so every system reads the same “time since last frame” value. Res<Time> Explain Single<&mut Transform, With>? İndi isə bu problemin bir hissəsi var. komponentləri var və bu da Təsadüfi: The Bir neçə oyunçu var idi, bu ekstraktor şikayət edərdi, bu, single-hero oyun üçün mükəmməldir. Single<&mut Transform, With<Player>> Transform Player &mut Transform What’s Vec2::ZERO? Hər iki qiymətin sıfır olduğu iki boyutlu vektordur: Biz onu keyboard girişini oxumadan əvvəl başlanğıcı yönü kimi istifadə edirik. Vec2::ZERO Vec2 { x: 0.0, y: 0.0 } What’s this KeyCode::… pattern? və Sonrakı xəbərNeftçi: “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ”nin “Qəbələ simply asks Bevy whether that key is held down during the current frame. KeyCode::ArrowLeft KeyCode::ArrowRight input.pressed(KeyCode::ArrowLeft) Xatırladaq ki, futbolçularımız, futbolçularımız, futbolçularımız, futbolçularımız, futbolçularımız, futbolçularımız, futbolçularımız, futbolçularımız, futbolçularımız var. converts the vector to length 1 so diagonal movement isn’t faster than straight movement. Saniyədə nə qədər pixel çəkmək lazımdır? Xatırladaq ki, bu, bir neçə ildir ki, bu, bir neçə ildir ki, bir neçə ildir ki, bir neçə ildir ki, bir neçə ildir ki, bir neçə ildir ki, bir neçə ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir ki, bir ildir. normalize() speed time.delta_secs() Movement sisteminin qurulması // Update main function fn main() { App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .add_systems(Update, move_player) // Line update alert .run(); } Why is move_player added as Update? What’s Update? Hər bir qələbə qazanırıq, hər bir qələbə qazanırıq. Planlaşdırma VVD - Hollandiyada futbolçu bu adla tanımır, orada VVD daha çox mərkəz-sağı təmsil edən siyasi partiyanın adının qısaltması kimi bilinir - artıq sorğu-suala ehtiyacı olmayan ulduzdu. move_player Update Update So does systems mean functions we want bevy to execute at a particular time, like initial setup or on every game loop update? Bir sistem yalnız Rust funksiyasıdır ki, Bevy-ə “Startup vaxtında məni çalışdırma” və ya “her güncellemədə məni çalışdırma” deyən bir baxışla göndərilsin. Bunu davam etdirək. Sprite Graphics xəritədə Biz Universal LPC SpriteSheet Generator istifadə edəcəyik ki, karakterimizə bir neçə kişilik verək. Bütün bunlardan birinin eksportu var. Bu link Bu layihənin hazırlanması üçün hazırlıq proseduru hazırlanıb Bildirilmiş fotoşəkillərdən istifadə edin Bu oyunlardan birini oynayırsanız, birini oynayırsınız. “Src” jurnalının içində. repo src/assets assets Reaksiya kodları Biz daha çox kodu ekləməyə ehtiyac var və main.rs-ə ekləmək oxumaq və anlamak üçün çətin olacaq. Your new.dll file update to the following, also create another file new.dll Çıxışlar içində Kodun bu cür bölünməsi, bir böyük dosyadan hər şeyi etmədən proqnozun genişləndirilməsini asanlaşdırır. mod player; player.rs //main.rs use bevy::prelude::*; mod player; fn main() { App::new() .insert_resource(ClearColor(Color::WHITE)) // We have updated the bg color to white .add_plugins( DefaultPlugins.set(AssetPlugin { // Our assets live in `src/assets` for this project file_path: "src/assets".into(), ..default() }), ) .add_systems(Startup, setup_camera) .run(); } fn setup_camera(mut commands: Commands) { commands.spawn(Camera2d); } Beləliklə, hər bir fotoqrafı beyaz arxa ilə başlayır. .insert_resource(ClearColor(Color::WHITE)) “Bevy”in texture, audio və digər varlıqlar üçün yüklü cihazıdır. Görünür ki, içində Bu da bizim spritlərimizin yaşadığı yerdir. AssetPlugin file_path src/assets Oyun Modulunun yaradılması Artıq bizim əsas app strukturumuz var, biz öz karakteri həyat gətirmək zamanı! Bu, bizim kodlarımızı organizasiya edir və daha sonra daha çox xüsusiyyətlər ekləmək daha asanlaşdırır. player.rs Bu modül bütün konstantları, komponentləri və sistemləri saxlayır ki, oyunçumuz dünyayla hareket etsin, animasyon etsin və onunla əlaqə saxlasın. Player.rs-də aşağıdaki kodu daxil edin // player.rs use bevy::prelude::*; // Atlas constants const TILE_SIZE: u32 = 64; // 64x64 tiles const WALK_FRAMES: usize = 9; // 9 columns per walking row const MOVE_SPEED: f32 = 140.0; // pixels per second const ANIM_DT: f32 = 0.1; // seconds per frame (~10 FPS) #[derive(Component)] struct Player; // Moved from main.rs to here Bu konstantlar spritesheet və hareket matematikası üçün yenidən istifadə etdiyimiz sayıların adlarını verir: tile boyutları, rütbədəki çərşənbə, yürüş hızı və animasiyanın nə qədər sürətli olduğunu. Burada bütün oyunçuların sayı bir modulda qalır. Player Oyunçuların pozulması // Append these lines of code to player.rs #[derive(Component, Debug, Clone, Copy, PartialEq, Eq)] enum Facing { Up, Left, Down, Right, } What’s an enum? Bir neçə ildir ki, bu problemlər həll olunacaq, bir neçə ildir ki, bu problemlər həll olunacaq. Bu variantı bir yerdə təqdim edirik. Facing Why can’t I use a struct here? Bir neçə bürüncə lazım idi ki, bu və Bu, sizin üçün çox faydalı ola bilər, və siz onları sinchronizasiya etməlisiniz.Enum yalnız bir yönü seçmək garanti verir. facing_up:true facing_left:false When to decide between using enum and struct? Bir neçə yerdə işləmək lazımdır, bir neçə yerdə işləmək lazımdır. və Xatırladaq ki, futbolçuların futbolçuların futbolçularını, futbolçuların futbolçularını, futbolçuların futbolçularını, futbolçuların futbolçularının futbolçularını, futbolçuların futbolçularının futbolçularını, futbolçuların futbolçularının futbolçularını, futbolçuların futbolçularının futbolçularını, futbolçuların futbolçularının futbolçularını, futbolçuların futbolçularının futbolçularının futbolçularını, futbolçuların futbolçularının futbolçularını, futbolçuların futbolçularının futbolçularını, futbolçuların futbolçularının futbolçularının futbolçularını, futbolçuların futbolçularının futbolçularını, futbolçuların futbolçularının futbolçularının futbolçularını, futbolçuların futbol x y Why the purpose of adding Debug, Clone, Copy, PartialEq, Eq macros? İndi bizə qonaq qonaq qonaq qonaq. və Dubay polisinin idarə etdiyi superkarlar – bu, artıq çox adi bir hala çevrilib. / Eyni zamanda, eşitməmək üçün eşitməmək lazımdır. Debug Clone Copy PartialEq Eq Why can’t I copy through simple assignment, why should I add these macros? “Rust” onları kopyalaşmaq yerine qiymətləri yerləşdirir, bu yüzden kompilator sizi opt-in edər. və “Dost” deyirlər ki, “dost” və “dost” deyirlər. və İki tərəfdən doğrudan fərqlənək, bu da oyunçunun yönünü dəyişdikdə necə algılayırıq. Copy Clone PartialEq Eq What do you mean by rust moves values, instead of copying? VVD - Hollandiyada futbolçu bu adla tanımır, orada VVD daha çox mərkəz-sağı təmsilən edən siyasi partiyanın adının qısaltması kimi bilinir - artıq sorğu-suala ehtiyacı olmayan ulduzdu. Hər iki variabilin bir-birini dəyişir. Copy Why does the old variable stop owning or die when assigned? Xatırladaq ki, hər bir hissənin yalnız bir sahibi var ki, bu sayda memoriya təhlükəsiz quraşdırılsın. This is a bit going over my head! Yea, qorxmayın, daha çox bölümlərimiz var və onları keçdikcə, bunu başa düşəcəyik. Animatsiya sisteminin komponentləri Biz bir neçə qramı olan bir spritesheetə sahib olduğumuzda ( 9 qramlı yürüş animasiyamız kimi), bu qramların nə qədər sürətli oynadığını kontrol etmək üçün bir yol lazımdır. Bir flipbook kimi düşünün - əgər sayfaları çox yavaş döndərsəniz, animatsiya çirkin görünür. əgər çox sürətli döndərsəniz, nə olduğunu görmürsünüz. Bizə bu vaxtın tam kontrolünü verir, karakterimizin yürüyüş animasiyası düzgün və düzgün görünür. AnimationTimer Sürücülər BeVy Hər bir oyunçunun hər bir oyunçunun nə vaxt bir sonraki animasiyaya keçəcəyini biləcəyi kimi, hər bir tick bir müddət parçasını temsil edir; bir dəfə vaxtı keçdikdə, sayda bir sonraki spritə keçərik. AnimationTimer Timer // Append these lines of code to player.rs #[derive(Component, Deref, DerefMut)] struct AnimationTimer(Timer); #[derive(Component)] struct AnimationState { facing: Facing, moving: bool, was_moving: bool, } What’s Deref, DerefMut macros doing? “Qəbələ”nin qələbəsi ilə bağlı görüşlər Bunu oxuduğumuz zaman və Onu da yazırıq ki, biz də telefonla danışırıq. Onu Öncəki İçerikİnteral hesabı açılmır Deref Timer DerefMut timer.tick(time.delta()) AnimationTimer So we are renaming the Timer to AnimationTimer? “Düşünürəm ki, bu sistemin adını dəyişməyəcəyik. Küçücük bir kitab kimi, bir “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar”, “Dostlar” və “Dostlar” Hər bir oyunçunun öz vaxtı olsaydı, bir neçə heroya ehtiyacımız olurdu. AnimationTimer Timer Timer So it’s an instance of AnimationTime? Əksinə, Bəzən bir dəfədən ibarətdir. Biz oyunçunu doğurduğumuz zaman birini yaratırıq ki, hər bir entitet öz vaxtlayıcı verilərini gətirə bilər.Bu model hər dəfə yeni bir API yazmaq olmadan var olan bir tipə daha bir anlam vermək istəyirsiniz. AnimationTimer Timer Xatırladaq ki, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbolçuların, futbol AnimationState Oyunçuların qələbəsi Şirkətdən keçirdiyimiz təyyarə Xatırladaq ki, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy”, “Bevy” və “Bevy” AssetServer // Append these lines of code to player.rs fn spawn_player( mut commands: Commands, asset_server: Res<AssetServer>, mut atlas_layouts: ResMut<Assets<TextureAtlasLayout>>, ) { // Load the spritesheet and build a grid layout: 64x64 tiles, 9 columns, 12 rows let texture = asset_server.load("male_spritesheet.png"); let layout = atlas_layouts.add(TextureAtlasLayout::from_grid( UVec2::splat(TILE_SIZE), WALK_FRAMES as u32, // columns used for walking frames 12, // at least 12 rows available None, None, )); // Start facing down (towards user), idle on first frame of that row let facing = Facing::Down; let start_index = atlas_index_for(facing, 0); commands.spawn(( Sprite::from_atlas_image( texture, TextureAtlas { layout, index: start_index, }, ), Transform::from_translation(Vec3::ZERO), Player, AnimationState { facing, moving: false, was_moving: false }, AnimationTimer(Timer::from_seconds(ANIM_DT, TimerMode::Repeating)), )); } Əsas səhifə » Gündəm » Gündəm » Gündəm » Gündəm » Gündəm » Gündəm » Gündəm » Gündəm AnimationState { facing, moving: false, was_moving: false } Hər kəsə atəş açan, hər kəsə atəş açan Bir neçə saniyə öncə spritesheet çəkmək olar. AnimationTimer(Timer::from_seconds(ANIM_DT, TimerMode::Repeating)) ANIM_DT ? What’s an AssetServer İŞİD “Bevy”in “File Loader” və “Manager”i, görüntüləri, sesləri və 3D modelləri kimi oyun varlıqlarının yükləməsini və cahil edilməsini təmin edir. AssetServer Telefon çağırdıqda Xatırladaq ki, bu, bir neçə ildir ki, bir neçə ildir ki, bu problemlər həll olunmayıb, bir neçə ildir ki, bu problemlər həll olunacaq. asset_server.load("path/to/sprite.png") This approach is efficient because: Bir çox entitetlər bir-birini bir neçə dəfə yükləmədən paylaşır. Əməliyyatlar yalnız həqiqətən lazım olduğunda aparılır. “Bevy” daha yaxşı performans üçün batch-load varlıqlarını optimize edə bilər Əgər bir varlıq yüklənməsə, bütün oyununuzu məhv etməyəcək Bizim məsələdə, Təsəvvür etmək lazımdır ki, bu, bir neçə ildir ki, bu problemin başlanğıcıdır. asset_server.load("sprites/player.png") Hareket sistemləri Artıq oyunçumuzun bütün ehtiyacı olan komponentləri ilə doğmuş olduğumuzda, oyunçunun hansı yönü ilə üzləşdiyini izləmək üçün var olan hareket sistemimizi yeniləmək lazımdır.Bu, animasyon sisteminin hansı spritesheet rübünün istifadə etməsini bilmək üçün kritikdir - hər bir yön (üstə, aşağı, sol, sağ) sprit atlasımızda başqa bir rübə qarşılaşır. Bu sistem sistemin aktivləşdirilməsi və güncellenməsi Beləliklə, animasiya sistemimiz hər yöndə yürüş animasiyaları üçün doğru sprite satışı seçə bilər. AnimationState // Append these lines of code to player.rs fn move_player( input: Res<ButtonInput<KeyCode>>, time: Res<Time>, mut player: Query<(&mut Transform, &mut AnimationState), With<Player>>, ) { let Ok((mut transform, mut anim)) = player.single_mut() else { return; }; let mut direction = Vec2::ZERO; if input.pressed(KeyCode::ArrowLeft) { direction.x -= 1.0; } if input.pressed(KeyCode::ArrowRight) { direction.x += 1.0; } if input.pressed(KeyCode::ArrowUp) { direction.y += 1.0; } if input.pressed(KeyCode::ArrowDown) { direction.y -= 1.0; } if direction != Vec2::ZERO { let delta = direction.normalize() * MOVE_SPEED * time.delta_secs(); transform.translation.x += delta.x; transform.translation.y += delta.y; anim.moving = true; // Update facing based on dominant direction if direction.x.abs() > direction.y.abs() { anim.facing = if direction.x > 0.0 { Facing::Right } else { Facing::Left }; } else { anim.facing = if direction.y > 0.0 { Facing::Up } else { Facing::Down }; } } else { anim.moving = false; } } Tədbirdə iştirak etmək istəyənlərin sayı artıb Onu dəyişdirmək üçün bizə və Xatırladaq ki, “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirkəti “Snickers” şirk Player Transform AnimationState Animasyonun yaradılması Artıq bütün parçalar yerdədir - oyunçumuz farklı yönlərdə gedə bilər, və biz onların hansı yoldan qarşılaşdıqlarını izləyirik. Xatırladaq ki, bu sistem, oyunçunun yönünü dəyişdirdiyi zaman farklı animatsiya satırları arasında dəyişənin kompleks logiki ilə başa çatır və yürüyüş və qısa vəziyyətlər arasındakı qısa keçidləri təmin edir. // Append these lines of code to player.rs fn animate_player( time: Res<Time>, mut query: Query<(&mut AnimationState, &mut AnimationTimer, &mut Sprite), With<Player>>, ) { let Ok((mut anim, mut timer, mut sprite)) = query.single_mut() else { return; }; let atlas = match sprite.texture_atlas.as_mut() { Some(a) => a, None => return, }; // Compute the target row and current position in the atlas (column/row within the 9-column row) let target_row = row_zero_based(anim.facing); let mut current_col = atlas.index % WALK_FRAMES; let mut current_row = atlas.index / WALK_FRAMES; // If the facing changed (or we weren't on a walking row), snap to the first frame of the target row if current_row != target_row { atlas.index = row_start_index(anim.facing); current_col = 0; current_row = target_row; timer.reset(); } let just_started = anim.moving && !anim.was_moving; let just_stopped = !anim.moving && anim.was_moving; if anim.moving { if just_started { // On tap or movement start, immediately advance one frame for visible feedback let row_start = row_start_index(anim.facing); let next_col = (current_col + 1) % WALK_FRAMES; atlas.index = row_start + next_col; // Restart the timer so the next advance uses a full interval timer.reset(); } else { // Continuous movement: advance based on timer cadence timer.tick(time.delta()); if timer.just_finished() { let row_start = row_start_index(anim.facing); let next_col = (current_col + 1) % WALK_FRAMES; atlas.index = row_start + next_col; } } } else if just_stopped { // Not moving: keep current frame to avoid snap. Reset timer on transition to idle. timer.reset(); } // Update previous movement state anim.was_moving = anim.moving; } // Returns the starting atlas index for the given facing row fn row_start_index(facing: Facing) -> usize { row_zero_based(facing) * WALK_FRAMES } fn atlas_index_for(facing: Facing, frame_in_row: usize) -> usize { row_start_index(facing) + frame_in_row.min(WALK_FRAMES - 1) } fn row_zero_based(facing: Facing) -> usize { match facing { Facing::Up => 8, Facing::Left => 9, Facing::Down => 10, Facing::Right => 11, } } “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da “Bakı”da və , and “Əgər bir oyunçu və ya birdən çox oyunçusu varsa, biz bu oyunçuluğa qapıdan çıxırıq. Xatırladaq ki, Rust və Rust Bunun üçün tip: “Qəbələ tamamilə 1 nəticə qaytarıb” Bu barədə “Qəbələ”nin məlumatı açıqlanıb. let Ok((mut anim, mut timer, mut sprite)) = query.single_mut() else { return; }; anim timer sprite else Result Ok Err Bundan sonra biz Bir “Rust”ın “maybe there is a value” (Məgər bir qiymət var) tipidir. Artıq texture atlası var və biz onu dəyişə bilərik. Bu, bir kartı və ya cache-i kontrol edərkən istifadə etdiyiniz bir modeldir: yalnız arxa bir şeyi qaytardığınızda qiyməti istifadə edin. match Option Some(atlas) None pulls the animation state, timer, and sprite handle for the player. It figures out which row of the atlas matches the current facing, snaps to that row when direction changes, and uses the timer to step through columns at a steady pace. When movement stops we reset the timer so the animation rests on the last frame shown. The helper functions map a facing to the correct row and frame index so the math stays readable. animate_player Player Plugin yaradılması // Append these lines of code to player.rs pub struct PlayerPlugin; impl Plugin for PlayerPlugin { fn build(&self, app: &mut App) { app.add_systems(Startup, spawn_player) .add_systems(Update, (move_player, animate_player)); } } VVD - Hollandiyada futbolçu bu adla tanımır, orada VVD daha çox mərkəz-sağı təmsilən edən siyasi partiyanın adının qısaltması kimi bilinir - artıq sorğu-suala ehtiyacı olmayan ulduzdu. üçün , biz Bevy bir checklist veririk: bu plug-in app-a daxil olduğunda, oyunçunun funksiyasına ehtiyacı olan hər şeyi qurmaq üçün içində kodu çalışdırın. Bir neçə oyunçu ilə bağlı danışıqlar aparılıb. PlayerPlugin Plugin PlayerPlugin main.rs İŞİD Mövzu: “Müqəddəs Məcəllə” – Mövzu Bu sistemlər bizimlə bağlıdır. Planlaşdırılıb ki, O, oyunun başlanğıcını açıqlayıb. və Gəlin içində Bu, bir neçə ildir ki, bu problemlər həll olunacaq, bir neçə ildir ki, bu problemlər həll olunacaq. içərisində Bütün oyunçuları automatik olaraq quraşdırır. build App spawn_player Startup move_player animate_player Update PlayerPlugin App::new() So this build function is an in-built structure, which I have to write? Eyni zamanda, The Tramp isə Con Brennanı “çox pis oğlan” adlandırıb. Biz bu xüsusiyyətə uygulanırıq, bu yüzden Rust bizə vücudun təchiz edilməsini gözləyir.Bevy plugin yüklədikdə bu metodu çağırır, bu yüzden onun içində bütün sistemlərimizi ekləyirik. Plugin build(&self, app: &mut App) What’s a trait? VVD - Hollandiyada futbolçu bu adla tanımır, orada VVD daha çox mərkəz-sağı təmsilən edən siyasi partiyanın adının qısaltması kimi bilinir Tramp: “Mənə bir şey ver Sizin sistemlərinizdən istifadə edə biləcəyim bir funksiya var”. Xatırladaq ki, biz bu prosesdən istifadə edirik və bu prosesdə özümüzü bir-birimizlə paylaşırıq. Başqa bir Bevy plugin kimi davranır, lakin oyunçularımızın spesifik sistemlərini yükləyir. Plugin build PlayerPlugin PlayerPlugin Final integrasiyası // Update the main function in main.rs use crate::player::PlayerPlugin; fn main() { App::new() .insert_resource(ClearColor(Color::WHITE)) .add_plugins( DefaultPlugins.set(AssetPlugin { file_path: "src/assets".into(), ..default() }), ) .add_systems(Startup, setup_camera) .add_plugins(PlayerPlugin) // Update this line .run(); } Bunu davam etdirək. cargo run Bu yazı ilk olaraq mənim blogumda yayımlandı. Bu yazı orijinal olaraq . Mənim blogum Daha çox bölümlər gələcək, son güncellemələr üçün LinkedIn-də mənimlə əlaqə saxlayın, X-də məni takip edin. Linkə X