2015-04-04 78 views
0

我想用挑戰3(https://ocharles.org.uk/blog/posts/2013-08-01-getting-started-with-netwire-and-sdl.html)從netwire 4.0轉換爲使用OpenGL的netwire 5.0。不幸的是,盒子不能反彈。整個代碼如下。在我看來,功能速度不起作用。當箱子與牆壁碰撞時,它不會反彈而停止。我如何糾正我的程序?提前致謝。Netwire 5 - 一個盒子不能彈跳

{-# LANGUAGE Arrows #-} 
import Graphics.Rendering.OpenGL 
import Graphics.UI.GLFW 
import Data.IORef 
import Prelude hiding ((.)) 
import Control.Monad.Fix (MonadFix) 
import Control.Wire 
import FRP.Netwire 


isKeyDown :: (Enum k, Monoid e) => k -> Wire s e IO a e 
isKeyDown k = mkGen_ $ \_ -> do 
    s <- getKey k 
    return $ case s of 
    Press -> Right mempty  
    Release -> Left mempty 


acceleration :: (Monoid e) => Wire s e IO a Double 
acceleration = pure (0) . isKeyDown (CharKey 'A') . isKeyDown (CharKey 'D') 
      <|> pure (-0.5) . isKeyDown (CharKey 'A') 
      <|> pure (0.5) . isKeyDown (CharKey 'D') 
      <|> pure (0) 


velocity :: (Monad m, HasTime t s, Monoid e) => Wire s e m (Double, Bool) Double 
velocity = integralWith bounce 0 
      where bounce c v 
        | c   = (-v) 
        | otherwise = v 

collided :: (Ord a, Fractional a) => (a, a) -> a -> (a, Bool) 
collided (a, b) x 
    | x < a = (a, True) 
    | x > b = (b, True) 
    | otherwise = (x, False) 


position' :: (Monad m, HasTime t s) => Wire s e m Double (Double, Bool) 
position' = integral 0 >>> (arr $ collided (-0.8, 0.8)) 

challenge3 :: (HasTime t s) => Wire s() IO a Double 
challenge3 = proc _ -> do 
    rec a <- acceleration -<() 
     v <- velocity -< (a, c) 
     (p, c) <- position' -< v 
    returnA -< p 


s :: Double 
s = 0.05 
y :: Double 
y = 0.0 
renderPoint :: (Double, Double) -> IO() 
renderPoint (x, y) = vertex $ Vertex2 (realToFrac x :: GLfloat) (realToFrac y :: GLfloat) 

generatePoints :: Double -> Double -> Double -> [(Double, Double)] 
generatePoints x y s = 
    [ (x - s, y - s) 
    , (x + s, y - s) 
    , (x + s, y + s) 
    , (x - s, y + s) ] 


runNetwork :: (HasTime t s) => IORef Bool -> Session IO s -> Wire s e IO a Double -> IO() 
runNetwork closedRef session wire = do 
    pollEvents 
    closed <- readIORef closedRef 
    if closed 
    then return() 
    else do 
     (st , session') <- stepSession session 
     (wt', wire') <- stepWire wire st $ Right undefined 
     case wt' of 
     Left _ -> return() 
     Right x -> do 
      clear [ColorBuffer] 
      renderPrimitive Quads $ 
      mapM_ renderPoint $ generatePoints x y s 
      swapBuffers 
      runNetwork closedRef session' wire' 



main :: IO() 
main = do 
    initialize 
    openWindow (Size 1024 512) [DisplayRGBBits 8 8 8, DisplayAlphaBits 8, DisplayDepthBits 24] Window 

    closedRef <- newIORef False 
    windowCloseCallback $= do 
    writeIORef closedRef True 
    return True 
    runNetwork closedRef clockSession_ challenge3 
    closeWindow 

回答

0

通過經驗,我覺得這裏的技巧是,你在技術上有實際碰撞前反彈幾個像素,因爲如果你發現它時,它發生了,那麼慣性把你方一點點「進入」牆壁,速度不斷顛倒,導致你的方格被堵塞。

Ocharles居然點頭給它的博客文章:

如果該位置落在全球範圍之外,我們調整了廣場(用小小量來阻止它被陷在牆上),並返回碰撞信息。

祝你好運與Netwire 5,我也在玩它,我只是開始喜歡它。 ;)