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'.

16/2/10, 1:06 pm -- Back to imperative programming

After being thoroughly uninspired by a tutorial on Reactive that I could barely understand, I'm returning to the imperative world with Raincat. I've been itching to start programming my project, and learning logical GUI programming hasn't been moving me forward. Maybe I'll come back to that after I have a working prototype.

27/1/10, 3:06 am -- An unnecessary tangent?

I've been thinking about how I want to put those pixels on the screen. It looks like Raincat uses SDL to load textures and OpenGL to render the textures along with strings and vectors. I don't know all the details because I haven't been messing with Raincat, lately.

I just finished reading Wolfgang Jeltch's recent overview of his FRP library, called Grapefruit. I was fascinated by his notion of a vista, which is a Mealy machine represented as a tree with an infinite number of nodes. This data structure is used to record all possible future combinations of occurrences in an event-driven system.

Declarative code has always looked very exotic to me, but I would love to get the hang of it. Unfortunately, there is only support for drawing GUI widgets with the current version of Grapefruit. There is no graphics support right now. Conal Elliott has another Haskell FRP library called Reactive that is a little more mature, but not as cool.

20/1/10, 2:12 am -- Learning about functors

Did you know that in Haskell, a list is a functor? Well, this surprised me. As I was reading Conal Elliott's paper on the Reactive library I lost him not long before he started talking about applicative functors. I soon learned that Functor is just a class, not some intimidating more-abstract version of a function like I had previously imagined whenever my eyes skimmed over that word in #haskell.

Here is the definition for the class Functor:

class Functor f where
    fmap :: (a -> b) -> f a -> f b

You might notice that fmap's type is close to map's type. map applies a function of type (a -> b) to a list of items [a], yielding the new list [b]. If you don't know about functors yet, you can think of fmap as a generalization of map. A functor is just a structure that you can map a function onto.

17/1/10, 1:49 pm -- finally started organizing my schedule

Just been putting together a definitive list of things I need to read.