Austin Alleman
Austin Alleman

Reputation: 21

How to animate something in Code World Haskell?

I am a new programmer and I am taking a high school course called Introduction to Computational Thinking. We are learning Haskell with Code World, an online IDE. Our assignment is to draw some kites and make them move around a little bit. However, my teacher is not very helpful and the documentation is terrible. The compiler also gives error messages that don't make much sense to me. I know I need to either define two or more frames and flip between them in a loop, but I cannot figure out how to do this. There is also a function called animationOf, but I cannot figure out how to use it either. Even if I copy an example found on another website and try to paste it in Code World to test it, there are a ton of syntax errors.

For example, this will not compile even if I rename the variables to match my variables or try to write my own function like this:

trafficController :: Double -> Picture
   trafficController t
     
     | round (t/3) `mod` 2 == 0 = trafficLight True
     
     | otherwise                = trafficLight False

main :: IO ()
main = animationOf trafficController

That's from a Haskell website and it's not even the same syntax. I'm confused about what "version" of Haskell this even is that we're learning at school because it's seemingly different from every website I look at about Haskell. For example, we use program = drawingOf(whatever) and don't use main. It also tells me weird errors when I try to make my own function like "Double is not in scope", which makes no sense to me. If I have import Standard I think basic types like Double should exist and be usable. Is there another library I have to import?

I tried defining two frames like this:

frame1 = [ kite(3,6,"red"), kite(-5,5,"purple"), kite(3,-5,"lightpink"),
          stickfig, painted(solidRectangle(20,20),"sky blue")]

frame2 = [ kite(3.5,6.5,"red"), kite(-4.5,4.5,"purple"), kite(3.5,-5.5,"lightpink"),
          stickfig, painted(solidRectangle(20,20),"sky blue")]

If I make an array of frames like combined[ frame1,frame2 ], I figured I can flip back and forth between those two to make a simple animation of the kites moving around. However, I can't even figure out how to make a loop to do this because the language feels so awkward to me and the documentation and examples are pretty useless. I've tried reading this documentation here and it doesn't help at all:

https://hackage.haskell.org/package/codeworld-api-0.3.1/docs/CodeWorld.html

I also have no idea how to use animationOf and the documentation provides no answers and examples I find on Google don't work no matter how I try to modify them or writing my own versions following the syntax they show.

Also does anyone know what version of Haskell this is they're making us learn and why it's different from other versions I see. And are there any better resources out there for learning this stuff because our documentation and examples are terrible.

Upvotes: 2

Views: 355

Answers (1)

K. A. Buhr
K. A. Buhr

Reputation: 50819

Here's the first problem. CodeWorld is an educational programming environment implemented in Haskell. It comes in two variants -- "CodeWorld" which allows you to program in a modified educational variant of the Haskell language that is similar to Haskell in some respects but has a different syntax; and "CodeWorld Haskell" which allows you to program in standard Haskell.

The version available at https://code.world/, and the one you appear to be using, is plain old "CodeWorld" instead of "CodeWorld Haskell". ("CodeWorld Haskell" can be accessed at https://code.world/haskell", if you want). The best source of documentation on this plain old "CodeWorld" language is the CodeWorld Guide, which you can access by clicking on the "Guide" button at the bottom of the CodeWorld IDE.

You use animationOf by defining a function that accepts a time value and renders a picture based on that time. You then call animationOf on that function, and animationOf takes care of showing a bunch of frames at selected times to create the animation.

So, if you really want to flip through some specific frames in a cycle, you need to calculate a frame number from a time. For example, the following function cycles through the same three frame numbers from "1" to "3" every two seconds:

framenum(t) = floor(remainder(t/secs, 1)*totalframes)+1
 where
  totalframes = 3
  secs = 2

You can then use it to write a function that selects from a list of frames like so, again based on a given time value:

showframe(t) = allframes # framenum(t)
  where
   allframes = [rectangle(4,1), circle(1), rectangle(1,4)]

and then define your program as an animation based on that showframe function:

program = animationOf(showframe)

This is a pretty awkward way of animating though. Instead of cycling through a bunch of frames, you're actually supposed to write a function that renders a scene as it should look at a particular time, not thinking about frames at all. For example, if you want a ball to bounce across the screen, you might define it's "x" and "y" positions as functions of time:

x(t) = t*2
y(t) | t < 1 = -10*(t-1)*(t+1)
     | t < 2 = -10*(t-1)*(t-2)
     | t < 2.5 = -10*(t-2)*(t-2.5)
     | otherwise = 0

Then you can write a function that displays a ball at the correct location based on that time value:

ball(t) = translated(circle(1),x(t),y(t))

and finally you can pass that function to animationOf and call it your program:

program = animationOf(ball)

The "Part 3: Change" section of the Guide contains many animation examples of this sort.

Here are the two complete programs which should work if cut and paste exactly into the IDE at https://code.world/

Program #1: Frames

framenum(t) = floor(remainder(t/secs, 1)*totalframes)+1
 where
  totalframes = 3
  secs = 2

showframe(t) = allframes # framenum(t)
  where
   allframes = [rectangle(4,1), circle(1), rectangle(1,4)]

program = animationOf(showframe)

Program #2: Ball

x(t) = t*2
y(t) | t < 1 = -10*(t-1)*(t+1)
     | t < 2 = -10*(t-1)*(t-2)
     | t < 2.5 = -10*(t-2)*(t-2.5)
     | otherwise = 0

ball(t) = translated(circle(1),x(t),y(t))

program = animationOf(ball)

Upvotes: 1

Related Questions