为什么这Yampa球弹跳进入一个无限循环?

问题描述:

我试图用Yampa框架模拟一个弹跳球:给定一个初始x位置,高度和速度,球应该根据重力规则弹跳。信号功能需要一个“提示 - 事件”作为输入,这个想法是“当球被倾斜时,速度应该翻倍”。为什么这Yampa球弹跳进入一个无限循环?

球弹跳得很好,但每次发生小费事件时,该功能都会进入无限循环。我想我可能需要添加一个延迟(dSwitch,pre,notYet?),但我不知道如何。任何帮助,将不胜感激!

{-# LANGUAGE Arrows #-} 

module Ball where 

import FRP.Yampa 

type Position = Double 
type Velocity = Double 
type Height = Double 

data Ball = Ball { 
     height :: Height, 
     width :: Position, 
     vel :: Velocity 
} deriving (Show) 

type Tip = Event() 

fly :: Position -> (Height, Velocity) -> SF Tip (Ball, Event (Height,Velocity)) 
fly w0 (h0, v0) = proc tipEvent -> do 
    let tip = (tipEvent == Event()) 
    v <- (v0+) ^<< integral -< -10.0 
    h <- (h0+) ^<< integral -< v 
    returnA -< (Ball h w0 v, 
       if h < 0 then Event (0,(-v*0.6)) 
        else if tip then Event (h, (v*2)) 
        else NoEvent) 

bounce w (h,v) = switch (fly w (h,v)) (bounce w) 

runBounce w (h,v) = embed (bounce 10 (100.0, 10.0)) (deltaEncode 0.1 [NoEvent, NoEvent, NoEvent, Event(), NoEvent]) 

编辑:我设法避免通过反馈标志尖端发生时的无限循环,但仍然不觉得自己做了正确的方式...

fly :: Position -> (Height, Velocity, Bool) -> SF Tip (Ball, Event (Height,Velocity,Bool)) 
fly w0 (h0, v0, alreadyTipped) = proc tipEvent -> do 
    let tip = tipEvent == Event() && (not alreadyTipped) 
    v <- (v0+) ^<< integral -< -10.0 
    h <- (h0+) ^<< integral -< v 
    returnA -< (Ball h w0 v, 
       if h < 0 then Event (0,(-v*0.6), False) 
        else if tip then Event (h, (v*2), True) 
        else NoEvent) 

bounce w (h,v,alreadyTipped) = switch (fly w (h,v,alreadyTipped)) (bounce w) 

后几天的黑客攻击我想我找到了答案。诀窍是使用notYet将切换事件延迟到下一个时间点,以便在“旧”小费事件结束时进行切换(并因此发起递归调用fly)。 second函数确保只有结果元组(Ball, Event (..))的第二部分将通过notYet。这消除了无限循环,但也改变了语义:切换现在发生在一个“时间步”后,这又导致不同的速度。

这Yampa的东西其实很不错,可悲的是没有太多的文档可以找到。我仍然无法找出preiPre函数的优点,我认为它们可以用在类似的环境中。

fly :: Position -> (Height, Velocity) -> SF Tip (Ball, Event (Height,Velocity)) 
fly w0 (h0, v0) = proc tipEvent -> do 
    let tip = tipEvent == Event() 
    v <- (v0+) ^<< integral -< -10.0 
    h <- (h0+) ^<< integral -< v 
    returnA -< (Ball h w0 v, 
       if h < 0 then Event (0,-v*0.6) 
        else if tip then Event (h, v*2) 
        else NoEvent) 

bounce w (h,v) = switch (fly w (h,v) >>> second notYet) (bounce w) 
+0

iirc的描述在The Yampa Arcade论文中。 – 2011-07-03 12:28:58