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:
Menu.hs:54:17:
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.
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:
- Sketch out and implement a menu system (what should happen when the program opens? buttons are clicked? etc.)
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.
- Textures are completely white on the only 64-bit OS I've tested on, which is also my main desktop >:(
- When the textures do appear (on 32-bit systems), the bottom left of each one has a strange dark shading to it.
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'.