Online Rust Playground
use async_std::task;
use std::thread::sleep;
use std::time::Duration;
async fn fn1() {
let two_secs = Duration::from_secs(2);
for _ in 0..5 {
sleep(two_secs);
println!("-");
}
}
async fn fn2() {
let one_sec = Duration::from_secs(1);
for _ in 0..5 {
sleep(one_sec);
println!("+");
}
}
fn main() {
println!("Hello, concurrent!");
let task1 = task::spawn(async {
fn1().await;
});
let task2 = task::spawn(async {
fn2().await;
});
task::block_on(task1);
task::block_on(task2);
}
Rust
понедельник, 27 июля 2020 г.
вторник, 21 июля 2020 г.
Rust, Multithread
Online Rust Playground
//Multithread
use std::thread;
use std::sync::mpsc;
fn main() {
//Создаем канал связи между параллельными потоками
let (p_tx, p_rx) = mpsc::channel();
//Создаем параллельный поток и биндим к ручке
let handle = thread::spawn(move || {
//Получаем данные из основного потока
let d = p_rx.recv().unwrap();
//Обрабатываем данные в параллельном потоке
calc(d);
});
//Основной поток:
//Создаем данные для обработки
let data = Data { str: "parallel!".to_string() };
//Передаем данные в параллельный поток
p_tx.send(data).unwrap();
//Сводим потоки через ручку
handle.join().unwrap();
}
//Функция для обработки данных в параллельном потоке
fn calc(data: Data) {
println!("Hello {}", data.str);
}
//Данные для передачи между потоками
struct Data {
str: String,
}
//Multithread
use std::thread;
use std::sync::mpsc;
fn main() {
//Создаем канал связи между параллельными потоками
let (p_tx, p_rx) = mpsc::channel();
//Создаем параллельный поток и биндим к ручке
let handle = thread::spawn(move || {
//Получаем данные из основного потока
let d = p_rx.recv().unwrap();
//Обрабатываем данные в параллельном потоке
calc(d);
});
//Основной поток:
//Создаем данные для обработки
let data = Data { str: "parallel!".to_string() };
//Передаем данные в параллельный поток
p_tx.send(data).unwrap();
//Сводим потоки через ручку
handle.join().unwrap();
}
//Функция для обработки данных в параллельном потоке
fn calc(data: Data) {
println!("Hello {}", data.str);
}
//Данные для передачи между потоками
struct Data {
str: String,
}
понедельник, 13 июля 2020 г.
Rust, Bitwise operators
Online Rust Playground
Бит как единица хранения информации.
fn main() {
//shift left: <<
//01 -> 10 = 2
let a = 1 << 1;
println!("{}", a);
//shift right: >>
//10 -> 01 = 1
let b = 2 >> 1;
println!("{}", b);
//or: |
//01 or 10 -> 11 = 3
let c = 1 | 2;
println!("{}", c);
//and: &
//01 and 10 -> 00 = 0
let d = 1 & 2;
println!("{}", d);
}
Бит как единица хранения информации.
fn main() {
//shift left: <<
//01 -> 10 = 2
let a = 1 << 1;
println!("{}", a);
//shift right: >>
//10 -> 01 = 1
let b = 2 >> 1;
println!("{}", b);
//or: |
//01 or 10 -> 11 = 3
let c = 1 | 2;
println!("{}", c);
//and: &
//01 and 10 -> 00 = 0
let d = 1 & 2;
println!("{}", d);
}
воскресенье, 12 июля 2020 г.
Rust, Loops, Iterators
Online Rust Playground
pub struct Items {
minimum: i32,
step: i32,
maximum: i32,
}
impl Iterator for Items {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
if self.minimum >= self.maximum {
return None;
}
let current = self.minimum;
self.minimum += self.step;
Some(current)
}
}
fn main() {
println!("-> Loops");
loops();
println!("-> Iterator");
iter();
}
//Loops
fn loops() {
println!("loop");
let mut n = 0;
loop {
n += 1; //step
if n > 5 {
break;
}
println!("{}", n);
}
println!("while");
let mut m = 0;
while m < 5 {
m += 1; //step
println!("{}", m)
}
println!("for - range");
for mut i in (0..5).step_by(2) {
i += 1;
println!("{}", i);
}
println!("for - idx");
for (idx, i) in (1..=5).enumerate().step_by(2) {
println!("{}: {}", idx, i);
}
println!("for - array");
let arr = [1, 2, 3];
for a in arr.iter().step_by(2) {
println!("{}", a);
}
}
//Iterator
fn iter() {
let mut it = Items {
minimum: 2,
step: 3,
maximum: 15,
};
println!("loop");
loop {
match it.next() {
Some(v) => println!("loop {}", v),
None => break,
}
}
println!("while");
it = Items {
minimum: 3,
step: 4,
maximum: 15,
};
while let Some(n) = it.next() {
println!("while {}", n)
}
println!("for");
it = Items {
minimum: 5,
step: 10,
maximum: 50,
};
for i in it {
println!("for {}", i);
}
}
pub struct Items {
minimum: i32,
step: i32,
maximum: i32,
}
impl Iterator for Items {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
if self.minimum >= self.maximum {
return None;
}
let current = self.minimum;
self.minimum += self.step;
Some(current)
}
}
fn main() {
println!("-> Loops");
loops();
println!("-> Iterator");
iter();
}
//Loops
fn loops() {
println!("loop");
let mut n = 0;
loop {
n += 1; //step
if n > 5 {
break;
}
println!("{}", n);
}
println!("while");
let mut m = 0;
while m < 5 {
m += 1; //step
println!("{}", m)
}
println!("for - range");
for mut i in (0..5).step_by(2) {
i += 1;
println!("{}", i);
}
println!("for - idx");
for (idx, i) in (1..=5).enumerate().step_by(2) {
println!("{}: {}", idx, i);
}
println!("for - array");
let arr = [1, 2, 3];
for a in arr.iter().step_by(2) {
println!("{}", a);
}
}
//Iterator
fn iter() {
let mut it = Items {
minimum: 2,
step: 3,
maximum: 15,
};
println!("loop");
loop {
match it.next() {
Some(v) => println!("loop {}", v),
None => break,
}
}
println!("while");
it = Items {
minimum: 3,
step: 4,
maximum: 15,
};
while let Some(n) = it.next() {
println!("while {}", n)
}
println!("for");
it = Items {
minimum: 5,
step: 10,
maximum: 50,
};
for i in it {
println!("for {}", i);
}
}
понедельник, 24 февраля 2020 г.
Владение ресурсами в Rust. Часть 5.
Мы уже знаем, что при передаче владения по ссылке, всегда происходит контроль ее времени жизни (lifetime). Время жизни ссылки зависит от времени жизни ресурса (область памяти, в которой хранятся данные). Время жизни ссылки не может быть больше, чем время жизни данных, на которые она ссылается. Время жизни данных начинается в точке размещения их в памяти (объявление и инициализация переменной) и заканчивается при выходе из блока видимости (очистка памяти). Время жизни ссылки начинается в точке ее объявления и инициализации и заканчивается при выходе из блока видимости. Главное правило – ссылка не может появиться раньше, чем данные, на которые ссылается и существовать после уничтожения данных, на которые ссылается.
В простом случае компилятор легко находит ошибки, но при работе со структурами данных, их методами или функциями, это сделать значительно труднее, т.к. не возможно однозначно определить время жизни ссылок, их составляющих, на этапе компиляции. Например, у нас есть структура, в которой есть поле - ссылка. Для правильной работы требуется, чтобы время жизни ссылки на такую структуру не превышало времени жизни ссылки, содержащейся в ней. В этих случаях потребуется участие программиста. Для того чтобы определить это участие, на уровне языка введен инструмент позволяющий определить отношение между временем жизни. Про инструмент мы говорили в статье Владение ресурсами в Rust. Часть 4. Для того чтобы облегчить это определение для работы с функциями, компилятор использует специальные правила (Lifetime Elision) для самостоятельного определения времени жизни в наиболее распространенных случаях, про них мы поговорим сегодня более подробно. Этих правил три, первое направлено на входные параметры функции, остальные два на возвращаемое значение.
Первое правило – Если параметры для функции содержат несколько ссылок, то для каждой из них определяется отдельное время жизни.
Второе правило – Возвращаемой ссылке присваивается время жизни единственной ссылки в параметрах.
Третье правило – Возвращаемой ссылке присваивается время жизни self-ссылки из нескольких ссылок в параметрах.
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
impl Point {
pub fn new(x: i32, y: i32) -> Self {
Point {
x,
y,
}
}
}
#[derive(Debug)]
struct Line<'a> {
start: &'a Point,
end: &'a Point,
}
impl<'a> Line<'a> {
//Custom lifetime
pub fn new(start: &'a Point, end: &'a Point) -> Self {
Line {
start,
end,
}
}
}
#[derive(Debug)]
struct PolyLine<'a> {
points: Vec<&'a Point>,
}
impl<'a> PolyLine<'a> {
pub fn new() -> Self {
PolyLine {
points: Vec::new()
}
}
//Rule #1
pub fn add_point(&mut self, point: &'a Point) {
self.points.push(point);
}
//Rule #3
pub fn get_point_by_indx(&self, _p: &Point, indx: usize) -> &Point {
self.points.get(indx).unwrap()
}
//Rule #2
pub fn via(p: &Point) -> &Point {
p
}
}
fn main() {
let point_1 = Point::new(0, 0);
let point_2 = Point::new(5, 5);
let line_1 = Line::new(&point_1, &point_2);
let line_2 = Line::new(&point_2, &point_1);
println!("{:?},\n{:?};", line_1, line_2);
let mut poly_line_1 = PolyLine::new();
poly_line_1.add_point(PolyLine::via(&point_1));
poly_line_1.add_point(&point_2);
println!("{:?}", poly_line_1);
println!("{:?}", poly_line_1.get_point_by_indx(&point_1,1));
}
Первое правило – Если параметры для функции содержат несколько ссылок, то для каждой из них определяется отдельное время жизни.
Второе правило – Возвращаемой ссылке присваивается время жизни единственной ссылки в параметрах.
Третье правило – Возвращаемой ссылке присваивается время жизни self-ссылки из нескольких ссылок в параметрах.
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
impl Point {
pub fn new(x: i32, y: i32) -> Self {
Point {
x,
y,
}
}
}
#[derive(Debug)]
struct Line<'a> {
start: &'a Point,
end: &'a Point,
}
impl<'a> Line<'a> {
//Custom lifetime
pub fn new(start: &'a Point, end: &'a Point) -> Self {
Line {
start,
end,
}
}
}
#[derive(Debug)]
struct PolyLine<'a> {
points: Vec<&'a Point>,
}
impl<'a> PolyLine<'a> {
pub fn new() -> Self {
PolyLine {
points: Vec::new()
}
}
//Rule #1
pub fn add_point(&mut self, point: &'a Point) {
self.points.push(point);
}
//Rule #3
pub fn get_point_by_indx(&self, _p: &Point, indx: usize) -> &Point {
self.points.get(indx).unwrap()
}
//Rule #2
pub fn via(p: &Point) -> &Point {
p
}
}
fn main() {
let point_1 = Point::new(0, 0);
let point_2 = Point::new(5, 5);
let line_1 = Line::new(&point_1, &point_2);
let line_2 = Line::new(&point_2, &point_1);
println!("{:?},\n{:?};", line_1, line_2);
let mut poly_line_1 = PolyLine::new();
poly_line_1.add_point(PolyLine::via(&point_1));
poly_line_1.add_point(&point_2);
println!("{:?}", poly_line_1);
println!("{:?}", poly_line_1.get_point_by_indx(&point_1,1));
}
Перегуд В.
пятница, 14 февраля 2020 г.
Game loop in Rust + SDL2
Cargo.toml
----------
[dependencies.sdl2]
version = "0.33"
default-features = false
features = ["ttf","image","gfx","mixer"]
main.rs
--------
mod game;
mod game_fsm;
use crate::game::Game;
use std::time::Duration;
use std::time::Instant;
const FPS: f64 = 60.0;
const DELAY_TIME: f64 = 1000.0 / FPS;
fn main() {
let sdl2_init = Game::new("GAME", 1366, 768);
//
match sdl2_init {
Ok(mut game) => {
println!("Run game");
game.init();
while game.is_running() {
let frame_start = Instant::now();
game.events();
game.update();
game.render();
let frame_end = Instant::now();
let frame_time = elapsed_ms(frame_start, frame_end);
//println!("Current frame time: {} ms", frame_time);
if frame_time < DELAY_TIME {
std::thread::sleep(Duration::from_millis((DELAY_TIME - frame_time) as u64));
}
}
println!("Exit game");
game.clean();
}
Err(e) => {
println!("SDL2 Error: {}", e);
}
}
}
pub fn elapsed_ms(t1: Instant, t2: Instant) -> f64 {
// pls see code in book: Beginning Rust: From Novice to Professional, Carlo Milanesi
}
game.rs
--------
extern crate sdl2;
use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::{Sdl, EventPump};
use sdl2::render::WindowCanvas;
use crate::game_fsm::{GameFSM, GameStateType};
use crate::game_fsm::game_state_type::PlayState;
pub struct Game {
running: bool,
ctx: Sdl,
cvs: WindowCanvas,
evt: EventPump,
fsm: Option<GameFSM>,
last_frame: u32,
}
impl Game {
pub fn new(_title: &str, _width: u32, _height: u32) -> Result<Self, String> {
//init
let sdl_context = sdl2::init()?;
let video_subsystem = sdl_context.video()?;
let window = video_subsystem.window(_title, _width, _height)
.position_centered()
.build().unwrap();
let canvas = window.into_canvas().build().unwrap();
let event_pump = sdl_context.event_pump()?;
//return
Ok(Game {
running: true,
ctx: sdl_context,
cvs: canvas,
evt: event_pump,
fsm: None,
last_frame: 0,
})
}
pub fn init(&mut self) {
let game_fsm = GameFSM::new();
self.fsm = Some(game_fsm);
//self.cvs.set_draw_color(Color::RGB(255, 255, 255));
}
pub fn events(&mut self) {
for event in self.evt.poll_iter() {
match event {
Event::Quit { .. } |
Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
println!("[Esc]");
self.running = false;
}
Event::KeyDown { keycode: Some(Keycode::Space), .. } => {
println!("[Space]");
//let play_state = GameStateType::Play(PlayState::new());
//self.fsm.as_mut().unwrap().change_game_states_by_type(play_state);
}
_ => {}
}
}
}
pub fn update(&mut self) {
let mut timer = self.ctx.timer().unwrap();
let mut delta_time:f64 = (timer.ticks() - self.last_frame) as f64 / 1000.0;
delta_time = if delta_time > 0.05 { 0.05 } else { delta_time };
self.last_frame = timer.ticks();
//self.fsm.unwrap().update(delta_time);
//println!("Current delta time: {} ms", delta_time);
}
pub fn render(&mut self) {
self.cvs.set_draw_color(Color::RGB(0, 0, 0));
self.cvs.clear();
//self.fsm.unwrap().render();
self.cvs.present();
}
pub fn clean(&mut self) {
//self.fsm.unwrap().clean();
}
pub fn is_running(&self) -> bool {
self.running
}
pub fn quit(&mut self) {
self.running = false;
}
}
----------
[dependencies.sdl2]
version = "0.33"
default-features = false
features = ["ttf","image","gfx","mixer"]
main.rs
--------
mod game;
mod game_fsm;
use crate::game::Game;
use std::time::Duration;
use std::time::Instant;
const FPS: f64 = 60.0;
const DELAY_TIME: f64 = 1000.0 / FPS;
fn main() {
let sdl2_init = Game::new("GAME", 1366, 768);
//
match sdl2_init {
Ok(mut game) => {
println!("Run game");
game.init();
while game.is_running() {
let frame_start = Instant::now();
game.events();
game.update();
game.render();
let frame_end = Instant::now();
let frame_time = elapsed_ms(frame_start, frame_end);
//println!("Current frame time: {} ms", frame_time);
if frame_time < DELAY_TIME {
std::thread::sleep(Duration::from_millis((DELAY_TIME - frame_time) as u64));
}
}
println!("Exit game");
game.clean();
}
Err(e) => {
println!("SDL2 Error: {}", e);
}
}
}
pub fn elapsed_ms(t1: Instant, t2: Instant) -> f64 {
// pls see code in book: Beginning Rust: From Novice to Professional, Carlo Milanesi
}
game.rs
--------
extern crate sdl2;
use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::{Sdl, EventPump};
use sdl2::render::WindowCanvas;
use crate::game_fsm::{GameFSM, GameStateType};
use crate::game_fsm::game_state_type::PlayState;
pub struct Game {
running: bool,
ctx: Sdl,
cvs: WindowCanvas,
evt: EventPump,
fsm: Option<GameFSM>,
last_frame: u32,
}
impl Game {
pub fn new(_title: &str, _width: u32, _height: u32) -> Result<Self, String> {
//init
let sdl_context = sdl2::init()?;
let video_subsystem = sdl_context.video()?;
let window = video_subsystem.window(_title, _width, _height)
.position_centered()
.build().unwrap();
let canvas = window.into_canvas().build().unwrap();
let event_pump = sdl_context.event_pump()?;
//return
Ok(Game {
running: true,
ctx: sdl_context,
cvs: canvas,
evt: event_pump,
fsm: None,
last_frame: 0,
})
}
pub fn init(&mut self) {
let game_fsm = GameFSM::new();
self.fsm = Some(game_fsm);
//self.cvs.set_draw_color(Color::RGB(255, 255, 255));
}
pub fn events(&mut self) {
for event in self.evt.poll_iter() {
match event {
Event::Quit { .. } |
Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
println!("[Esc]");
self.running = false;
}
Event::KeyDown { keycode: Some(Keycode::Space), .. } => {
println!("[Space]");
//let play_state = GameStateType::Play(PlayState::new());
//self.fsm.as_mut().unwrap().change_game_states_by_type(play_state);
}
_ => {}
}
}
}
pub fn update(&mut self) {
let mut timer = self.ctx.timer().unwrap();
let mut delta_time:f64 = (timer.ticks() - self.last_frame) as f64 / 1000.0;
delta_time = if delta_time > 0.05 { 0.05 } else { delta_time };
self.last_frame = timer.ticks();
//self.fsm.unwrap().update(delta_time);
//println!("Current delta time: {} ms", delta_time);
}
pub fn render(&mut self) {
self.cvs.set_draw_color(Color::RGB(0, 0, 0));
self.cvs.clear();
//self.fsm.unwrap().render();
self.cvs.present();
}
pub fn clean(&mut self) {
//self.fsm.unwrap().clean();
}
pub fn is_running(&self) -> bool {
self.running
}
pub fn quit(&mut self) {
self.running = false;
}
}
Vasili Perahud
воскресенье, 9 февраля 2020 г.
Компонентная система на Rust.
Сначала давайте посмотрим, что у нас под капотом. Мы уже много говорили про владение ресурсами и знаем, что по правилам, которые нельзя нарушать, на один ресурс нам разрешается иметь либо одну модифицирующую ссылку, либо несколько не модифицирующих. Также мы можем передать владение с помощью перемещения (оптимально) или копирования. При перемещении старый владелец удаляется, что не удобно, а при копировании, данные дублируются, что не эффективно. В си++ таких ограничений нет, хочешь несколько модифицирующих указателей на ресурс, пожалуйста, удобно, но не безопасно, один из них может удалить ресурс и второй про это никак не узнает. Нам конечно могут помочь умные указатели, но они не обязательное правило, что делает нарушение этого правила возможным. Тоже самое про перемещение владения, в Rust, для пользовательских типов оно происходит по умолчанию, это значит, что, если в пользовательском типе есть ссылка на ресурс, она будет перемещена, что исключит наличие двух ссылок на один ресурс. Для того чтобы произвести копирование, придется переопределить интерфейс копирования, в котором можно будет создать копию ресурса. В си++ наоборот, по умолчанию создается две ссылки на ресурс, что не безопасно, и можно определить или не определять конструкторы и операторы копирования. Все по причине обратной совместимости. Но если нет жестких правил, нет гарантии безопасности.
Теперь про решения. Объектный подход, а именно классы и наследование, позволяют выстраивать иерархию типов и получать доступ к родителям и потомкам. Одна из возможностей в си++ иметь указатель на себя, создает циклическую связь, что невозможно в Rust по правилам, которые описывают время жизни типов, при которых потомок не может жить дольше родителя или ссылка на ресурс не может жить дольше самого ресурса. Вызов модифицирующего метода из типа, блокирует возможность получения одновременного модифицирующего или не модифицирующего доступа к полям этого же типа. Это требует специфического управления ресурсом, при котором мы не можем получать к нему параллельный модифицирующий доступ, но зато можем получить последовательный, передавая ресурс по цепочке от одной функции к другой. Не удобно? Не знаю. Пока для меня это ново, но подобные ограничения требуют альтернативных подходов. И они есть. Они другие. Лучше или хуже не мне судить. Например, возможность хранить значения в перечислениях, значительно упрощает иерархию объектов, которую придется выстраивать в си++. Удобный отбор по образцу с деструктуризацией данных, все это позволяет решать задачи без необходимости применять интерфейсы и наследование для полиморфизма. Возможность их использовать тоже есть, но не является основой. В качестве примера – кусочек компонентной системы (entity component system, ecs).
//Component types
#[derive(Debug, Eq, PartialOrd, PartialEq, Hash, Clone)]
enum ComponentType {
Transform(TransformComp),
Sprite(SpriteComp),
}
trait ComponentTrait {
fn init(&self) { println!("Default init method fo component"); }
fn update(&mut self) { println!("Default update method fo component"); }
fn draw(&self) { println!("Default draw method fo component"); }
}
//Transform Component
#[derive(Debug, Eq, PartialOrd, PartialEq, Hash, Clone)]
struct TransformComp {
owner: Option<String>,
x: i32,
y: i32,
}
impl TransformComp {
pub fn new(_x: i32, _y: i32) -> Self {
TransformComp {
owner: Option::None,
x: _x,
y: _y,
}
}
pub fn set_owner(&mut self, _owner: String) {
self.owner = Option::Some(_owner);
}
pub fn get_owner(&self) -> String {
match self.owner.as_ref() {
Some(own) => format!("{:?}", own),
None => format!("_"),
}
}
}
impl ComponentTrait for TransformComp {
fn init(&self) {
//
println!("For {} Init transform component. x:{}, y:{}", self.get_owner(), self.x, self.y);
}
fn update(&mut self) {
self.x += 1;
self.y += 1;
println!("For {} Update transform component. x += 1, y += 1", self.get_owner());
}
fn draw(&self) {
//
println!("For {} Draw transform component. x:{}, y:{}", self.get_owner(), self.x, self.y);
}
}
//Sprite Component
#[derive(Debug, Eq, PartialOrd, PartialEq, Hash, Clone)]
struct SpriteComp {
owner: Option<String>,
texture: String,
}
impl SpriteComp {
pub fn new(_text: String) -> Self {
SpriteComp {
owner: Option::None,
texture: _text,
}
}
pub fn set_owner(&mut self, _owner: String) {
self.owner = Option::Some(_owner);
}
pub fn get_owner(&self) -> String {
match self.owner.as_ref() {
Some(own) => format!("{:?}", own),
None => format!("_"),
}
}
}
impl ComponentTrait for SpriteComp {
fn init(&self) {
//
println!("For {} Init sprite component. I am {}", self.get_owner(), self.texture);
}
fn update(&mut self) {
//
println!("For {} Update sprite component. I am {} of 80 level", self.get_owner(), self.texture);
}
//use default method
// fn draw(&self) {
// //
// println!("For {} Draw sprite component. I am great {}", self.get_owner(), self.texture);
// }
}
//Entity
struct Entity {
name: String,
components_vec_by_type: Vec<ComponentType>,
}
impl Entity {
pub fn new(_name: &str) -> Self {
Entity {
name: _name.to_string(),
components_vec_by_type: Vec::new(),
}
}
pub fn add_comp_to_vec_by_type(mut self, mut _cmp: ComponentType) -> Self {
match _cmp {
ComponentType::Transform(mut cmp) => {
cmp.set_owner(self.name.to_string());
self.components_vec_by_type.push(ComponentType::Transform(cmp));
}
ComponentType::Sprite(mut cmp) => {
cmp.set_owner(self.name.to_string());
self.components_vec_by_type.push(ComponentType::Sprite(cmp));
}
};
self
}
pub fn get_comps_by_type(&mut self) -> &mut Vec<ComponentType> {
&mut self.components_vec_by_type
}
pub fn get_comps_by_trait(&mut self) -> Vec<&mut dyn ComponentTrait> {
let mut components_vec_by_trait: Vec<&mut dyn ComponentTrait> = Vec::new();
for cmp_type in self.components_vec_by_type.iter_mut(){
match cmp_type {
ComponentType::Transform( cmp) => {
components_vec_by_trait.push( cmp);
}
ComponentType::Sprite( cmp) => {
components_vec_by_trait.push( cmp);
}
};
}
components_vec_by_trait
}
}
fn main() {
//New Components
let tc1 = ComponentType::Transform(TransformComp::new(0, 0));
let sc1 = ComponentType::Sprite(SpriteComp::new("Wizard".to_string()));
//Add to Entity
let mut ent1 = Entity::new("Bob")
.add_comp_to_vec_by_type(tc1)
.add_comp_to_vec_by_type(sc1);
//Access by Component Type (enum)
for cmp_type in ent1.get_comps_by_type().iter_mut() {
match cmp_type {
ComponentType::Transform(cmp) => {
println!("Owner: {:?}", cmp.owner);
cmp.init();
cmp.update();
cmp.draw();
}
ComponentType::Sprite(cmp) => {
println!("Owner: {:?}", cmp.owner);
cmp.init();
cmp.update();
cmp.draw();
}
}
}
//Access by Component Trait (interface)
println!("Entity: {:?}", ent1.name);
for cmp in ent1.get_comps_by_trait().iter_mut(){
cmp.init();
cmp.update();
cmp.draw();
}
//
}
Перегуд В.
Подписаться на:
Сообщения (Atom)

