Marlon Moonglow's Animator

3/5/10, 1:27 pm -- Presentation notes

I'm pretty satisfied with where I've gotten so far. I'm nowhere near finished -- I haven't even started implementing the animation scheme. However, just working on the menu system / mouse and keyboard interaction has been instructive.

For example, I have just implemented the scheme for associating buttons with state changes. These would be simple tasks if I was using a menu toolkit like GTK or QT. Because I'm just writing it using OpenGL it takes more time. I'm also still learning subtleties about Haskell, since this is the first large program I have worked with in this language.

There are also some rendering quirks which I have chosen to ignore for now. I know just enough OpenGL to get basically what I want on the screen, but there are some strange things happening with textures that I need to sort out.

26/4/10, 11:58 pm

Well it turns out I was thinking about the problem of mapping over MmaMenu too much. It occurred to me that all I need is a simple function:

buttonMap :: (MmaButton -> MmaButton) -> MmaMenu -> MmaMenu
buttonMap f m = m {
  playButton = f $ playButton m,
  nextSprtButton = f $ nextSprtButton m,
  prevSprtButton = f $ prevSprtButton m,
  nextBgButton = f $ nextBgButton m,
  prevBgButton = f $ prevBgButton m,
  nextFrameButton = f $ nextFrameButton m,
  prevFrameButton = f $ prevFrameButton m,
  saveButton = f $ saveButton m
It would be nice, though, to somehow tell Haskell to "apply this function to every MmaButton in this custom datatype".

19/4/10, 2:02 pm -- Mapping over an arbitrary type

I've run into a limit of my Haskell knowledge. In order to hook up GUI buttons to mouse events, I would like, in Bindings.hs, to map over my menu type which contains mainly buttons, but also some windows (for showing the current sprite, current background, and current frame):

data MmaMenu = MmaMenu
                 playButton :: MmaButton,

                 -- sprite chooser
                 sprtWindow :: MmaWindow,
                 nextSprtButton :: MmaButton,
                 prevSprtButton :: MmaButton,

                 -- background chooser
                 bgWindow :: MmaWindow,
                 nextBgButton :: MmaButton,
                 prevBgButton :: MmaButton,

                 -- stepper
                 frameWindow :: MmaWindow,
                 nextFrameButton :: MmaButton,
                 prevFrameButton :: MmaButton,

                 saveButton :: MmaButton
               } deriving Show
For sprites this is simple because the sprites in my world state are in a list. Because I'm using a list I can easily filter out only the sprites that are under the mouse using filter and map.

In a previous blog entry, I outlined the notion of a Functor in Haskell. Intuitively, it seems like defining fmap over MmaMenu may help me with this dilemma. But how so? Let's find out the type of fmap:

Prelude> :t fmap
fmap :: (Functor f) => (a -> b) -> f a -> f b

Prelude> :t map
map :: (a -> b) -> [a] -> [b]
I compared it to map's type because sometimes it's easier to understand the class by looking at the instantiation as well. It looks the f in fmap turns into 'list of' when we define it over lists.

Now we can imagine the type of our menuMap to be (a -> b) -> MmaMenu a -> MmaMenu b. Will this work? Let's find out!

instance Functor MmaMenu where
  fmap f m = m {
    playButton = f (playButton m),
    nextSprtButton = f (nextSprtButton m),
    prevSprtButton = f (prevSprtButton m),
    nextBgButton = f (nextBgButton m),
    prevBgButton = f (prevBgButton m),
    nextFrameButton = f (nextFrameButton m),
    prevFrameButton = f (prevFrameButton m),
    saveButton = f (saveButton m)
Aside from looking very messy, this also doesn't work. Intuitively, I didn't think it would work. Now that I look at the typing, however, I can't really point out the problem. Adding to the mystery, GHC gives me the curious error:
    Kind mis-match
    Expected kind `* -> *', but `MmaMenu' has kind `*'
    In the instance declaration for `Functor MmaMenu'
Failed, modules loaded: Util, Rectangle.
I have heard of Kinds, as a sort of meta-type. It looks like I better do some more research. Maybe I'll ask someone who knows Haskell really well.

9/4/10, 3:51 pm

I added some specifications for the menu today. I haven't implemented anything yet (except for a non-functional play button).

Here's a screenshot. mma using all the cpu My program uses too much CPU when idling. I need to look at some of the other Haskell OpenGL programs (probably my favorite, SGdemo) for ideas. Maybe I need to find out how to update the screen only when the mouse moves, or something like that.

7/4/10, 4:17 pm -- Planning for spring quarter

Now that I have some basic structure down, I can start focusing on the program's user experience. Here are my revised spring quarter goals:

I don't think the x86/x86_64 issue is affecting textures, they have worked on x86_64 and not worked on x86. I'm going to ignore the issue for now and just assume it's a problem with certain versions of the Haskell bindings for one of the libraries I'm using (OpenGL, GLUT, and SDL).

11/3/10, 1:37 am -- End of winter quarter

Well this quarter is over and I learned how to use the basics of OpenGL. Next quarter I can focus more on making my program usable, adding more textures, and eventually create a scheme for saving/loading movies. Right now there are also some major kinks I need to work out.

So basically I need to read about texturing.

21/2/10, 9:32 pm -- Some re-planning

I've been coding, finally. I wasn't planning on starting until spring quarter, but it'll help me in my research of different graphics libraries. I think I've settled on OpenGL. I was initially wary of OpenGL because I always assumed it would be too complicated to use without reading the entirety of that big 'red book'. I also used to think that a 3D graphics library would be counter-intuitive for my simple 2D animations. Both of my assumptions have turned out to be fairly true so far, but I'm comforted by my nearly functional toy program. I think I'll be able to wrestle it into a working implementation with some more reading.

This week I'll be setting up the user input handling, and maybe parts of the user interface. Next week I'll be learning how to deal with textures for backgrounds and 'actors'.