py-fizz
1 Basic vocabulary
2 py-fizz High Level
2.1 Basic Gadgets
3 py-fizz Low Level
3.1 Top Level
3.2 Basic Constructors
3.3 Setting Physical Properties of Objects
3.4 Making composite objects
3.4.1 Spatial Relations for Composite Objects
3.4.2 Physical Relations for Composite Objects
3.5 Runtime Behaviours
3.6 Misc
8.12

py-fizz🔗ℹ

Fun with fizzics!

Py-fizz is a language for creating physics simulations and games. Compiles to Python and runs in the context of Pygame and Pymunk. But Racket is the compile-time language, and provides a purely functional API for doing awesome physics stuff.

Py-fizz is divided into two languages. The first is a higher-level one, used for creating levels and simulations out of pre-built gadgets: e.g. Bowling balls, balloons, motors, etc. Eg.:

(simulate
   (wooden-level
     (bowling-ball)))

image

There is also a lower-level language for defining your own such gadgets. For example, the bowling-ball gadget might be defined as:

(define (bowling-ball)
  (mass 100000
        (make-dynamic (h:bitmap "./imgs/bowling-ball.png"))))

These docs describe both the high and low level languages.

1 Basic vocabulary🔗ℹ

Before we start, there are a few basic concepts.

First of all, everything in py-fizz is some kind of physical object. There are three basic kinds: cosmetic, dynamic, and static.

Cosmetic objects do not collide with anything. They are just for show.

Dynamic objects do collide. Also, they can move around.

Static objects also collide, but they do not move around.

There is one other kind of object, which is a "composite" object. This just means that the object is composed of more basic objects.

For example, the car object is composed of three wheels and a crate. The wheels and crate are all dynamic objects. The car is a composite object.

(simulate
   (wooden-level
     (car)))

image

One last critical concept! Objects can be parameterized. For example, the car is a function that takes a speed and/or ANOTHER OBJECT.

(simulate
   (wooden-level
     (car 1 (bowling-ball))))

image

Or...

(simulate
   (wooden-level
     (car 1 (balloon))))

image

Or...

(simulate
   (wooden-level
     (car 1 (enemy))))

image

And so on. You can pass in any basic object to the car function, and you’ll get a new composite object back. You could then pass this new car into any other function that takes a composite object.

For example, maybe you want to be able to shoot a balloon-car out of a cannon...

(simulate
   (wooden-level
     (cannon (car 1 (balloon)))))

image

The image above probably doesn’t communicate exactly how cool this is. Let’s check out a gif...

So that’s the basic idea. You create objects. You make those into composite objects. And you can combine composite objects to get even cooler composite objects.

And so on.

Exercise: Can you figure out how to make a car with a cannon on top that shoots out other cars?

2 py-fizz High Level🔗ℹ

The High Level library consists of various gadgets (composite and basic) that all tend to have a consistent look and feel, as well as physical properties that work well together. Many of the gadgets are parameterized, so you can make your own new gadgets with them (like that balloon car shooter seen above).

This part of the documentation lists the provided gadgets and shows you how to compose them to make new ones.

2.1 Basic Gadgets🔗ℹ

procedure

(wooden-level object)  composite?

  object : (or/c static? dynamic? cosmetic? composite?)
image

This is just a pretty-looking space for running simulations. There are static walls on all sides, and a cosmetic (wooden) background in the middle. It will dynamically resize if what’s inside doesn’t fit in the default 600x600 space.

procedure

(bowling-ball)  dynamic?

image

Simple bowling ball. High mass.

No parameters on this one. But you can alter its properties with functions like toggle-static, mass, initial-velocity, etc.

procedure

(crate)  dynamic?

image

Dynamic crate. Falls by default. If you want to use it as a platform, call toggle-static on it to convert it to a static object.

procedure

(wheel)  dynamic?

image

Low mass, circular object.

procedure

(balloon)  dynamic?

image

Floats. (Obeys opposite gravity.)

If it is attached to other objects, it will pull them upward.

procedure

(breakable-balloon)  dynamic?

image

Like a regular balloon, but it can be destroyed by clicking on it.

It can also be destroyed if it collides strongly with other objects.

procedure

(friend)  dynamic?

image

A dynamic object that causes you to lose the game if any of them are destroyed. Useful when building puzzles.

procedure

(enemy)  dynamic?

image

A dynamic object that causes you to win the game if all of them are destroyed. Useful when building puzzles.

procedure

(motor color speed)  dynamic?

  color : string?
  speed : number?

(motor "red" 1)

image

(motor "green" 1)

image

(motor "blue" 1)

image

A dynamic object that rotates continually. Good for vehicles.

Use negative numbers to make it rotate the other direction.

procedure

(pinned-motor color speed)  dynamic?

  color : string?
  speed : number?

(pinned-motor "red" 1)

image

(pinned-motor "green" 1)

image

(pinned-motor "blue" 1)

image

A dynamic object that rotates continually. It’s pinned to one spot. Good for conveyor belts.

Use negative numbers to make it rotate the other direction.

procedure

(catpult object)  composite?

  object : (or/c static? dynamic? cosmetic? composite?)

(catapult (crate))

image

(catapult (car))

image

(catapult (above (bowling-ball) (bowling-ball)))

image

Makes a see-saw contraption, on one side is a bowling ball with a strong downward starting velocity. On the other side is whatever object you supply.

Note that although this function accepts static, dynamic, cosmetic, or composite objects, it is most exciting when you pass in a dynamic object (or a composite object that contains dynamic objects).

procedure

(car [speed object] join-object)  composite?

  speed : number? = 1
  object : (or/c static? dynamic? composite?) = (crate)
  join-object : (or/c static? dynamic? composite?)

(car)

image

Makes a car. You can control speed and direction with the speed parameter (negative numbers go counter clockwise).

The second parameter controls what object is on top of the car. Passing in a dynamic object is the simplest thing.

(car 1 (bowling-ball))

image

If you pass in a static object, the car will be stuck in the air, "pinned" by the static object. Usually not what you want. (Use toggle-static to switch your static object to a dynamic one before passing it into the car function.)

(car 1 (toggle-static (cannon)))

image

ADVANCED USAGE: If you pass in a composite object, you pust also pass in a join-object as the third parameter. This determines which part of the composite object to connect the wheels to.

(let ([c (crate)])
  (car 1
       (balloons-pulling 10 c)
       c))
image

(let ([c (crate)])
  (car 1
       (car 1 c)
       c))
image

Let’s take a moment to see how cool it is to be able to make flying cars...

procedure

(pipe width height)  dynamic?

  width : number?
  height : number?

(pipe 100 10)

image

Makes a dynamic rectangle that looks like a pipe. Good for platforms, walls, falling pipes, etc.

procedure

(balloons-pulling num object [string-length])  composite?

  num : number?
  object : (or/c dynamic? static?)
  string-length : number? = 100
(balloons-pulling 4
                  (pipe 100 10)
                  50)
image

Attaches the given number of balloons to the given object. The length of the balloon string can also be configured.

procedure

(conveyor-belt num [speed])  composite?

  num : number?
  speed : number? = 10

(conveyor-belt 5 -10)

image

(conveyor-belt 5 10)

image

Creates the given number of motors in a horizontal row. The speed determines three things: the speed (obviously), the direction (negative is counter-clockwise), and the color (blue for counter-clockwise, red for clockwise).

procedure

(v-space num)  cosmetic?

  num : number?
Creates transparent vertical space. Good for positioning things.

(above (bowling-ball)
       (v-space 10)
       (bowling-ball))
image

procedure

(h-space num)  cosmetic?

  num : number?
Creates transparent vertical space. Good for positioning things.

(beside (bowling-ball)
        (h-space 10)
        (bowling-ball))
image

procedure

(fragments object    
  resolution    
  [energy    
  destroy-after])  composite?
  object : (or/c dynamic? static? cosmetic? composite?)
  resolution : number?
  energy : number? = 100000
  destroy-after : number? = 50

(fragments (car) 4)

image

Takes the object and returns a composite object that looks like the original, but is really a bunch of dynamic objects constructed from a sliced up image of the original.

This is how breakable-balloons explode when destroyed.

Note that fragments are computationally expensive. Keep the resolution and the destroy-after parameters low.

procedure

(cannon object [energy angle])  static?

  object : (or/c dynamic? static? cosmetic? composite?)
  energy : number? = 10000
  angle : number? = 0

(cannon (car))

image

Returns a static cannon that shoots the provided object when clicked.

The angle and the power of the shot can be adjusted.

procedure

(builder object [destroy-self?])  static?

  object : (or/c dynamic? static? cosmetic? composite?)
  destroy-self? : boolean? = #t

(builder (car))

image

Returns a static treasure chest that turns into the provided object when clicked. Good for puzzles.

An icon of the provided object is displayed above the chest, so the user knows what to anticipate.

3 py-fizz Low Level🔗ℹ

3.1 Top Level🔗ℹ

procedure

(preview object)  image?

  object : (or/c dynamic? static? cosmetic? composite?)
Any object or composite you make can be passed into the preview function to get an image of what it will look like.

procedure

(simulate object)  void?

  object : (or/c dynamic? static? cosmetic? composite?)
This triggers the actual compilation to Python and runs the game/simulation.

3.2 Basic Constructors🔗ℹ

procedure

(make-static object [#:collider collider])  static?

  object : (or/c h:image? cosmetic? layout? physical?)
  collider : collider? = circle-collider

procedure

(make-dynamic object [#:collider collider])  dynamic?

  object : (or/c h:image? cosmetic? layout? physical?)
  collider : collider? = circle-collider

procedure

(make-cosmetic object)  cosmetic?

  object : (or/c h:image? cosmetic? layout?)

procedure

(make-pivot object)  pivot?

  object : (or/c h:image? cosmetic?)

procedure

(circle radius fill-mode color)  cosmetic?

  radius : number?
  fill-mode : mode?
  color : color?
A lifted version of the 2htdp/image function (see those docs for details). Returns a cosmetic.

procedure

(rectangle width height fill-mode color)  cosmetic?

  width : number?
  height : number?
  fill-mode : mode?
  color : color?
A lifted version of the 2htdp/image function (see those docs for details). Returns a cosmetic.

procedure

(square size fill-mode color)  cosmetic?

  size : number?
  fill-mode : mode?
  color : color?
A lifted version of the 2htdp/image function (see those docs for details). Returns a cosmetic.

3.3 Setting Physical Properties of Objects🔗ℹ

procedure

(motorize speed object)  dynamic?

  speed : number?
  object : dynamic?

procedure

(gravity direction object)  dynamic?

  direction : (list/c number? number?)
  object : dynamic?

procedure

(elasticity amount object)  dynamic?

  amount : number?
  object : dynamic?

procedure

(angle amount object)  dynamic?

  amount : number?
  object : (or/c dynamic? static?)

procedure

(friction object [energy angle])  static?

  object : (or/c dynamic? static?)
  energy : number? = 10000
  angle : number? = 0

procedure

(ttl time object)  dynamic?

  time : number?
  object : (or/c dynamic? static? cosmetic?)

procedure

(mass amount object)  dynamic?

  amount : number?
  object : dynamic?

procedure

(initial-velocity direction object)  dynamic?

  direction : (list/c number? number?)
  object : dynamic?

procedure

(toggle-static object)  (or/c dynamic? static?)

  object : (or/c dynamic? static?)

procedure

(width object)  number?

  object : (or/c dynamic? static? cosmetic? composite?)

procedure

(height object)  number?

  object : (or/c dynamic? static? cosmetic? composite?)

3.4 Making composite objects🔗ℹ

The easiest way to make a composite object is to use a spatial layout function: above, beside, or overlay.

These place two objects in a spatial relation to each other.

Additionally, objects can be associated with physical properties: e.g. they might have a joint connecting them. If this is the case, you’ll create the composite object with a two-step process – 1) establish the physical relation ship (e.g. with the spring-joint function), and then place the two objects into a spatial relationship (e.g. with the above function).

(let* ([b1 (bowling-ball)]
       [b2 (bowling-ball)]
       [b1-with-connection
        (pin b1 b2)])
  (simulate
   (above b1-with-connection b2)))

Note that the pin function takes b1 and returns a new version of b1 that has a pin joint relationship to b2. But you still need to place both b1-with-connection and b2 into a relation with each other.

(You’ll get a runtime error if you don’t.)

3.4.1 Spatial Relations for Composite Objects🔗ℹ

Spatial relations may be established between any two objects. They do not need to be related to each other physically.

procedure

(above object ...)  composite?

  object : (or/c dynamic? static? cosmetic? composite?)

procedure

(beside object ...)  composite?

  object : (or/c dynamic? static? cosmetic? composite?)

procedure

(overlay object ...)  composite?

  object : (or/c dynamic? static? cosmetic? composite?)
3.4.2 Physical Relations for Composite Objects🔗ℹ

As stated above, spatial relations may be established between any two objects. They do not need to be related to each other physically.

The opposite, however, is not true. If you create a physical relationship between two objects, you must ALSO relate them spatially.

Think of it this way: If you say that two objects are physically related (e.g. they have a connecting joint), you also need to say where those objects are in the universe. The only way to place things into the universe is to relate them spatially to each other.

Keep that in mind with all of the functions in this subsection.

procedure

(gear object1 object2)  dynamic?

  object1 : dynamic?
  object2 : dynamic?
The two objects will rotate together.

Returns a new version of the first object.

procedure

(connect-pivot pivot object)  pivot?

  pivot : pivot?
  object : (or/c dynamic? static?)
Causes the object to swing around the pivot point.

Returns a new version of the pivot.

procedure

(pin object1 object2)  dynamic?

  object1 : (or/c dynamic? static?)
  object2 : (or/c dynamic? static?)
Establishes a rigid "rod" between the two objects.

Returns a new version of the first object.

procedure

(spring object1 object2 distance)  dynamic?

  object1 : (or/c dynamic? static?)
  object2 : (or/c dynamic? static?)
  distance : number?
Establishes a springy connection between two objects. (Used for balloon strings.)

Returns a new version of the first object.

procedure

(angle-spring object1    
  object2    
  [angle    
  stiffness    
  damping])  dynamic?
  object1 : (or/c dynamic? static?)
  object2 : (or/c dynamic? static?)
  angle : number? = 0
  stiffness : number? = 0
  damping : number? = 0
The two objects will prefer to be at the same angle. They will spring back to that angle if forces do not prevent it.

3.5 Runtime Behaviours🔗ℹ

procedure

(on-collide object 
  callback 
  #:friction friction-thresh 
  #:energy-loss energy-loss-thresh) 
  (or/c dynamic? static? cosmetic? composite?)
  object : (or/c dynamic? static? cosmetic? composite?)
  callback : callback?
  friction-thresh : 0
  energy-loss-thresh : 0
If the object suffers a collision, the callback is triggered.

Collisions can be filtered out based on friction and kinetic energy loss.

procedure

(on-click object callback)

  (or/c dynamic? static? cosmetic? composite?)
  object : (or/c dynamic? static? cosmetic? composite?)
  callback : callback?
If the object is clicked, the callback is triggered.

procedure

(spawn object [destroy-self?])  callback?

  object : (or/c dynamic? static? cosmetic? composite?)
  destroy-self? : boolean? = #f
Spawns a new object. Only useful in the context of on-click or on-collide.

procedure

(must-survive object)  (or/c dynamic? static?)

  object : (or/c dynamic? static?)
The given object triggers a lose screen if it is destroyed.

procedure

(must-die object)  (or/c dynamic? static?)

  object : (or/c dynamic? static?)
The given object triggers a win screen if all such objects are destroyed.

3.6 Misc🔗ℹ

procedure

(set-package-path! path)  void?

  path : string?
If you have the py-fizz package installed in a weird place (like I do when I’m developing it).