Rust 当Cell可以';不能用吗?
我对生锈还很陌生,我一直在慢慢地跟随它,这对它所经历的概念有很大的帮助 在创建主菜单的教程中,作者建议读者做“家庭作业”,让主菜单上的标签(“新游戏”、“退出”)在聚焦和非聚焦时设置大小变化动画,而不是跳转到空闲/聚焦大小。这就是我一直有困难的地方 在我开始实施变更之前,代码相关部分的基本布局如下:Rust 当Cell可以';不能用吗?,rust,Rust,我对生锈还很陌生,我一直在慢慢地跟随它,这对它所经历的概念有很大的帮助 在创建主菜单的教程中,作者建议读者做“家庭作业”,让主菜单上的标签(“新游戏”、“退出”)在聚焦和非聚焦时设置大小变化动画,而不是跳转到空闲/聚焦大小。这就是我一直有困难的地方 在我开始实施变更之前,代码相关部分的基本布局如下: // equivalent to 'menu option' struct Action { /// function executed if action chosen func:
// equivalent to 'menu option'
struct Action {
/// function executed if action chosen
func: Box<Fn(&mut Phi) -> ViewAction>,
label: &'static str,
idle_sprite: Sprite, // smaller (32)
focus_sprite: Sprite, // larger (38)
// ...
}
impl Action {
fn new(phi: &mut Phi, label: &'static str, func: Box<Fn(&mut Phi) -> ViewAction>) -> Action {
// ...
}
struct MainMenuView {
actions: Vec<Action>,
selected: i8,
// ...
}
impl MainMenuView {
pub fn new(phi: &mut Phi) -> MainMenuView {
// ...
}
}
impl View for MainMenuView {
fn render(&mut self, phi: &mut Phi, elapsed: f64) -> ViewAction {
// ...
for (i, action) in self.actions.iter().enumerate() {
// ...
}
}
}
fn main() {
::phi::spawn("Arcade Shooter", |phi| {
Box::new(::views::main_menu::MainMenuView::new(phi))
});
}
//相当于“菜单选项”
结构动作{
///如果选择了操作,则执行函数
func:Box ViewAction>,
标签:&'static str,
空闲的精灵:精灵,//更小(32)
焦点_精灵:精灵,//更大(38)
// ...
}
强制作用{
fn新建(phi:&mut phi,标签:&'static str,func:Box ViewAction>)->操作{
// ...
}
结构主菜单视图{
行动:Vec,
选定:i8,
// ...
}
impl主菜单视图{
新发布(phi:&mut phi)->主菜单视图{
// ...
}
}
主菜单视图的impl视图{
fn渲染(&mut self,phi:&mut phi,经过时间:f64)->ViewAction{
// ...
for self.actions.iter()枚举()中的(i,action){
// ...
}
}
}
fn main(){
::phi::spawn(“街机射击手”),| phi |{
框::新建(::视图::主菜单::主菜单视图::新建(phi))
});
}
我对动画的第一个想法是,让它根据idle\u size
和focus\u size
之间的插值大小动态创建一个精灵,使用自焦点改变以来经过的时间,使用Action
上的方法聚焦和散焦来更改用于生成精灵的当前大小
字段对于sprite
字段
这需要对Action
结构进行可变绑定,这需要我花一点时间来解决,因为任何地方都没有let
绑定,但通过更改构造函数似乎几乎是可能的:Action::new(…)->&mut Action
,以及大量显式标记生命周期(这有它自己的问题,但它太长了)。然后我意识到,MainMenuView
也必须是可变绑定的,在这一点上我停止了这条路径(自从启动它以来,我没有成功编译),因为这似乎是一个非常不雅观的解决方案,它使基本上所有东西都是可变的,肯定会打破rust的不变性默认点
然后我想知道我是否可以用一个新的动作创建一个新的MainMenuView
,这个新的sprite
,它可能会工作(将视图更改为另一个MainMenuView
),但是仅仅更改一些文本的大小似乎是一种非常浪费的方式,而且还是非常不雅的
在那之后,我记得Cell
,但是当我尝试为MainMenuView
aVec
执行actions
时,我发现Cell
只适用于Copy
类型。这可能还可以(我没有足够的经验知道),但是Action
的func
字段没有实现Copy
(我不确定它是否可以?),因此Action
不能#[派生(复制)]
。如果不重新构造程序的很大一部分,使Action
中没有func>,就会死路一条
这是我主要问题的结尾-基本上,当你有嵌套的结构,你想有一个深域变异,但不能在其周围放置一个单元格(afaik)?这是一个代码的结构性问题吗,我应该首先避免这个问题?
我还意识到,在Action
中使用Vec
和许多不同大小的精灵进行转换的解决方案将消除上述任何一种可变的需要。这本能地让我感觉有点粗糙,因为它实际上是硬编码一些不必要的东西。我也可以看到实现与帧正确对齐(我也不熟悉与帧定时同步的事情),并为最大fps工作-尽管当构建MainMenuView
时,可以根据最大fps动态创建精灵的数量…用于非复制类型
struct Action {
func: Box<Fn(&mut Phi) -> ViewAction>,
label: &'static str,
sprite: RefCell<Sprite>,
// ...
}
struct操作{
func:Box ViewAction>,
标签:&'static str,
雪碧:RefCell,
// ...
}
如果你能改变一个结构(你要么拥有它,要么对它有一个可变的引用)然后你可以可变地借用它的任何字段。在这种情况下,这意味着如果你有机会变异MainMenuView
,那么你也可以花点时间变异任何操作
。在字段上使用RefCell
或Cell
也可以在你不能变异结构时工作,但是obscures,当值可能发生更改时。RefCell
也有运行时借用恐慌的风险。如果可能,您应该避免RefCell
我不知道这个框架是如何工作的,这会影响这个问题的答案。它看起来像是phi
控制了你的MainMenuView
,这意味着phi
决定了你从那时起何时对它进行变异。如果你从来没有机会定期对MainMenuView
进行变异,那么m动画,这仍然是可能的。避免RefCell
的另一个选项可能是在对selected
进行变异时对动画进行编码,并计算它在绘图调用期间对绘图的影响。例如,如果在更改选择时存储时间戳,则可以在绘图时计算