1
votes

I'm fairly new to Rust and I've been trying to get a simple game working with ggez.

Now, normally in C++ or C# I would structure my game around having an instance of a "master" class that takes care of settings, frame limiting, window creation, event handling, etc and "state" classes that are held by the master class. I would pass a pointer to the master class when creating the state class (something like game_master*) so that the state class can access the resources of the master class.

In Rust I can't pass a &mut self because the state could potentially outlive the reference.

pub fn new(_ctx: &mut Context) -> GameMaster {
    let game = GameMaster {
        state: None,
        pending_state: None
    };

    game.state = Some(Box::new(TestState::new_with_master(&mut game))) <----- NOPE
    game
}

I think this could be solved with lifetimes but I haven't found a way to get lifetimes working with traits. Passing the master in as a reference on every function call doesn't work either because only one mutable reference can be held at a time.

fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
    if self.state.is_some() {
        (*self.state.as_mut().unwrap()).update(ctx, &mut self) <----- NOPE
    } 
    else {
        Ok(())
    }
}

Is there no good way to do this in Rust?

1

1 Answers

0
votes

I have a similar problem a while ago but I think the only choices are:

  1. use Rc<RefCell<>> everywhere. Remember to also use Weak or add a special destroy method if you ever need to garbage collect these objects since they hold reference to each other.

  2. use raw pointers and unsafe code. The problem is that with unsafe deference, you also lose the mutability check (RefCell ensures only one mutable reference exists at a time) in addition to the lifetime check.