The Universe Package#
To import this package, use the following import statements:
import comp1110.universe.*;
import static comp1110.universe.Colour.*;
import static comp1110.universe.Image.*;
import static comp1110.universe.Universe.*;
Images#
Opaque Data Types#
Colour#
/**
* This type represents colours.
* There are a number of colour constants you can use:
* RED, GREEN, BLUE, WHITE, BLACK, CYAN, YELLOW, MAGENTA,
* GRAY, DARK_GRAY, LIGHT_GRAY, ORANGE, PINK
* You can also use the MakeColour() function.
*/
// This is an opaque type whose definition does not matter to you
Image#
/**
* This type represents various images.
* Each image has a width and height, and a "pin"
* position, which is used by default to position
* the image relative to others. Pins are initialized
* to be in the middle of a shape (rounded down).
* These values can be retrieved using the functions:
* GetImageWidth, GetImageHeight, GetImagePinX, and
* GetImagePinY, respectively.
*/
// This is an opaque type whose definition does not matter to you
Enumerations#
FontStyle#
/**
* Represents a font style for text rendering
*/
enum FontStyle {
/** Normal text style
*/
PLAIN,
/** Italic text
*/
ITALIC,
/** Bold text
*/
BOLD,
/** Bold italic text
*/
ITALICBOLD
}
// TEMPLATE:
// {
// return ... switch(fontstyle) {
// case PLAIN -> ...;
// case ITALIC -> ...;
// case BOLD -> ...;
// case ITALICBOLD -> ...;
// } ...;
// }
Mode#
/**
* Represents a mode of drawing a geometrical shape
*/
enum Mode {
/** Indicates that a geometrical shape should be filled
*/
SOLID,
/** Indicates that only the outline of the shape should be drawn
*/
OUTLINE
}
// TEMPLATE:
// {
// return ... switch(mode) {
// case SOLID -> ...;
// case OUTLINE -> ...;
// } ...;
// }
TextAlign#
/**
* Describes a desired text alignment
*/
enum TextAlign {
/** LEFT alignment for left-to-right languages
* RIGHT alighnment for right-to-left languages
*/
DEFAULT,
/** Align text on the left-hand side of the text field
*/
LEFT,
/** Align text on the right-hand side of the text field
*/
RIGHT,
/** Align text on the center of the text field
*/
CENTER,
/** Justify the text within the given maxWidth parameter
*/
JUSTIFY
}
// TEMPLATE:
// {
// return ... switch(textalign) {
// case DEFAULT -> ...;
// case LEFT -> ...;
// case RIGHT -> ...;
// case CENTER -> ...;
// case JUSTIFY -> ...;
// } ...;
// }
Functions#
GetImageWidth ; GetImageHeight ; GetImagePinX ; GetImagePinY ; Intersects ; MovePinBy ; MovePinTo ; Rectangle ; Circle ; Ellipse ; Polygon ; Text ; DrawLine ; FromFile ; SavePNG ; SaveJPEG ; Overlay ; OverlayXY ; Place ; PlaceXY ; Rotate ; Scale ; ScaleX ; ScaleY ; Mask ; ShowImage
GetImageWidth#
/**
* Returns the width of an image, in pixels.
*
* Examples:
* given: Circle(5, RED)
* expect: 10
* given: Rectangle(25, 50, BLUE)
* expect: 25
*
* @param image the image whose width should be returned
* @return The width of the given image, in pixels
* @implSpec
* Postcondition: Image widths are always nonnegative
*/
int GetImageWidth(Image image);
GetImageHeight#
/**
* Returns the height of an image, in pixels.
*
* Examples:
* given: Circle(5, RED)
* expect: 10
* given: Rectangle(25, 50, BLUE)
* expect: 50
*
* @param image the image whose height should be returned
* @return The height of the given image, in pixels
* @implSpec
* Postcondition: Image heights are always nonnegative
*/
int GetImageHeight(Image image);
GetImagePinX#
/**
* Returns the x position of an image's pin,
* relative to its top left corner
*
* Examples:
* given: Circle(5, RED)
* expect: 5
* given: Rectangle(25, 50, BLUE)
* expect: 12
*
* @param image the image whose pin's x-coordinate should be returned
* @return The x-coordinate of the given image's pin
*/
int GetImagePinX(Image image);
GetImagePinY#
/**
* Returns the y position of an image's pin,
* relative to its top left corner
*
* Examples:
* given: Circle(5, RED)
* expect: 5
* given: Rectangle(25, 50, BLUE)
* expect: 25
*
* @param image the image whose pin's y-coordinate should be returned
* @return The y-coordinate of the given image's pin
*/
int GetImagePinY(Image image);
Intersects#
/**
* Tests whether two images placed at certain coordinates
* would intersect. This is reasonably precise for basic shapes,
* but for images and text a rectangular bounding box is assumed.
*
* Examples:
* given: Circle(5, RED), 10, 10, Circle(5, BLUE), 18, 18
* expect: false
* given: Rectangle(10, 10, RED), 10, 10,
* Rectangle(10, 10, BLUE), 18, 18
* expect: true
*
* @param image1 The first image
* @param x1 the x-coordinate of the first image (at its pin)
* @param x1 the y-coordinate of the first image (at its pin)
* @param image2 The second image
* @param x2 the x-coordinate of the second image (at its pin)
* @param x2 the y-coordinate of the second image (at its pin)
* @return True if the two images would intersect if placed
* as given, false if not
*/
boolean Intersects(Image image1, int x1, int x1, Image image2, int x2, int x2);
MovePinBy#
/**
* Adjusts the position of an image's pin
*
* Examples:
* given: An image whose pin is at (10,-2), x=5, y=3
* expect: An image like the given one with a pin at (15, 1)
*
* @param image The image whose pin should be moved
* @param x The amount by which the x-coordinate should move
* @param y The amount by which the y-coordinate should move
* @return A new image that is like the given one, except that
* the position of the pin was adjusted
*/
Image MovePinBy(Image image, int x, int y);
MovePinTo#
/**
* Adjusts the position of an image's pin
*
* Examples:
* given: An image whose pin is at (10,-2), x=5, y=3
* expect: An image like the given one with a pin at (5, 3)
*
* @param image The image whose pin should be moved
* @param x The new x-coordinate of the pin
* @param y The new y-coordinate of the pin
* @return A new image that is like the given one, except that
* the position of the pin was adjusted
*/
Image MovePinTo(Image image, int x, int y);
Rectangle#
/**
* Creates an image of a rectangle
*
* Examples:
* given: 10, 10, RED
* expect: An image of a 10x10 square filled red
* given: 20, 25, BLUE, OUTLINE
* expect: An image of a 20x25 rectangular blue outline
*
* @param width The width of the rectangle, in pixels
* @param height The height of the rectangle, in pixels
* @param colour The colour of the rectangle
* @param mode The fill mode of the rectangle
* OPTIONAL, default = SOLID
* @return An image of a rectangle based on the given parameters
*/
Image Rectangle(int width, int height, Colour colour, Mode mode);
Circle#
/**
* Creates an image of a circle
*
* Examples:
* given: 10, RED
* expect: An image of a circle of radius 10 filled red
* given: 20, BLUE, OUTLINE
* expect: An image of a circular blue outline with radius 20
*
* @param radius The radius of the circle, in pixels
* @param colour The colour of the circle
* @param mode The fill mode of the circle
* OPTIONAL, default = SOLID
* @return An image of a circle based on the given parameters
*/
Image Circle(int radius, Colour colour, Mode mode);
Ellipse#
/**
* Creates an image of an ellipse
*
* Examples:
* given: 10, 10, RED
* expect: An image of a circle of radius 5 filled red
* given: 20, 25, BLUE, OUTLINE
* expect: An image of a elliptical 20x25 blue outline
*
* @param width The width of the ellipse, in pixels
* @param height The height of the ellipse, in pixels
* @param colour The colour of the ellipse
* @param mode The fill mode of the ellipse
* OPTIONAL, default = SOLID
* @return An image of a ellipse based on the given parameters
*/
Image Ellipse(int width, int height, Colour colour, Mode mode);
Polygon#
/**
* Creates an image of a polygon.
* In contrast to the other image functions, which put
* the pin at the center of the image, a polygon is
* constructed by coordinates relative to the pin.
*
* Examples:
* given: RED, Pair(5,5), Pair(5,9), Pair(8,5)
* expect: An image of a right triangle filled red
* given: BLUE, OUTLINE, Pair(-3, -3), Pair(-3, 3),
* Pair(3, 3), Pair(3, -3)
* expect: An image of a 6x6 square blue outline
*
* @param colour The colour of the polygon
* @param mode The fill mode of the polygon
* OPTIONAL, default = SOLID
* @param points Coordinates for the corners of the polygon,
* as many as you like (at least three), separated
* by commas
* @return An image of a polygon based on the given parameters
*/
Image Polygon(Colour colour, Mode mode, Pair<Integer, Integer>... points);
Text#
/**
* Creates an image of text. Most parameters are
* optional, but need to be specified in order up
* to the last parameter that is needed, except for
* maxWidth, which can always be omitted.
*
* Examples:
* given: "Hello World!", 15
* expect: An image of the text "Hello World!", rendered
* in 15pt Arial
*
* @param text The text that should be rendered.
* May include line breaks ('\n').
* @param fontSize The size of the text, in points
* @param maxWidth A non-negative integer if the text should include
* line-breaks to avoid exceeding maxWidth, or -1 if
* the text may get arbitrarily wide
* OPTIONAL, default = -1
* @param colour The colour with which the text should be rendered
* OPTIONAL, default = BLACK
* @param fontName The name of the font that should be used
* OPTIONAL, default = Arial
* @param style The style of the font that should be used
* OPTIONAL, default = FontStyle.PLAIN
* @param align The alignment of the text, relevant if multi-line
* OPTIONAL, default = TextAlign.DEFAULT
* @return The text rendered as an Image according to the parameters
*/
Image Text(String text, int fontSize, int maxWidth, Colour colour, String fontName, FontStyle style, TextAlign align);
DrawLine#
/**
* Draws a line onto an existing image.
*
* Examples:
* given: Rectangle(50, 50, WHITE), 50, 0, 0, 50, BLACK, 5
* expect: A white 50x50 rectangle with a black diagonal line
*
* @param base The base image on which the line should be drawn
* @param x1 The x-coordinate of the first end of the line
* @param y1 The y-coordinate of the first end of the line
* @param x1 The x-coordinate of the second end of the line
* @param y1 The y-coordinate of the second end of the line
* @param colour The colour of the line
* @param thickness The thickness of the line
* OPTIONAL, default = 1
* @return A new image that is like the given image, but
* with a line drawn on top according to parameters
*/
Image DrawLine(Image base, int x1, int y1, int x1, int y1, Colour colour, int thickness);
FromFile#
/**
* Loads an image from a file.
*
* Examples:
* given: car.png
* expect: Assuming car.png exists where the application was run,
* an Image that when drawn draws the contents of car.png
*
* @param path A path to an image file (PNG or JPEG)
* @return An Image representing the imgage contained in the file
*/
Image FromFile(String path);
SavePNG#
/**
* Saves an image to a PNG file. If the given
* file already exists, it is overwritten.
*
* Examples:
* given: Rectangle(400, 400, GREEN), "box.png"
* expect: "box.png" in the application's working
* directory now contains a 400x400 green square
*
* @param image The Image to be saved to a file
* @param path The path of the file
*/
void SavePNG(Image image, String path);
SaveJPEG#
/**
* Saves an image to a JPEG file. If the given
* file already exists, it is overwritten.
*
* Examples:
* given: Rectangle(400, 400, GREEN), "box.jpg"
* expect: "box.jpg" in the application's working
* directory now contains a 400x400 green square
*
* @param image The Image to be saved to a file
* @param path The path of the file
*/
void SaveJPEG(Image image, String path);
Overlay#
/**
* Overlays two images on top of each other, using
* pin positions to position the images relative to
* each other. The resulting image is sized to
* have space for both images as they are layed out.
*
* Examples:
* given: Rectangle(10, 500, GREEN), Rectangle(500, 10, GREEN)
* expect: A green cross in a 500x500 image
*
* @param base The base image. Parts of it may be covered by the
* other image.
* @param top The top image. Parts of it may cover the other
* image.
* @return A combination of both images.
*/
Image Overlay(Image base, Image top);
OverlayXY#
/**
* Overlays two images on top of each other, using
* the pin position of the top image and x/y coordinates
* relative to the bottom image's top left corner to
* position the two relative to each other. The
* resulting image is sized to have space for both
* images as they are layed out.
*
* Examples:
* given: Rectangle(10, 500, GREEN), Rectangle(500, 10, GREEN), 250, 250
* expect: A sideways green T in a 500x500 image
*
* @param base The base image. Parts of it may be covered by the
* other image.
* @param top The top image. Parts of it may cover the other
* image.
* @param x The x-coordinate from the top-left corner of base
* at which to place the pin of the top image
* @param y The y-coordinate from the top-left corner of base
* at which to place the pin of the top image
* @return A combination of both images.
*/
Image OverlayXY(Image base, Image top, int x, int y);
Place#
/**
* Places an image on top of another, using
* pin positions to position the images relative to
* each other. The resulting image has the same size
* as the base image, with parts of the placed image
* potentially cut off.
*
* Examples:
* given: Rectangle(10, 500, GREEN), Rectangle(500, 10, RED)
* expect: A green 10x500 rectangle, with a 10x10 red
* square in the middle.
*
* @param base The base image. Parts of it may be covered by the
* other image.
* @param top The top image. Parts of it may cover the other
* image, and parts of it may be cut off.
* @return A combination of both images.
*/
Image Place(Image base, Image top);
PlaceXY#
/**
* Places an image on top of another, using the pin
* position of the top image and x/y coordinates
* relative to the bottom image's top left corner to
* position the two relative to each other. The
* resulting image has the same size as the base
* image, with parts of the placed image
* potentially cut off.
*
* Examples:
* given: Rectangle(10, 500, GREEN), Rectangle(500, 10, RED), 5, 495
* expect: A green 10x500 rectangle, with a 10x10 red
* square at the bottom.
*
* @param base The base image. Parts of it may be covered by the
* other image.
* @param top The top image. Parts of it may cover the other
* image, and parts of it may be cut off.
* @param x The x-coordinate from the top-left corner of base
* at which to place the pin of the top image
* @param y The y-coordinate from the top-left corner of base
* at which to place the pin of the top image
* @return A combination of both images.
*/
Image PlaceXY(Image base, Image top, int x, int y);
Rotate#
/**
* Returns a rotated version of an image.
* Rotation is measured in radians.
* A full circle = 2*PI.
*
* Examples:
* given: Rectangle(50,50, RED), PI/4
* expect: An image of a red diamond
*
* @param image The image to be rotated.
* @param radians The radians by which the image should be rotated
* @return An image like the given one, rotated by given radians
*/
Image Rotate(Image image, double radians);
Scale#
/**
* Returns a scaled version of an image.
*
* Examples:
* given: Rectangle(50,50, RED), 2.0
* expect: An image of a 100x100 red rectangle
*
* @param image The image to be scaled.
* @param scale The scaling factor
* @return An image like the given one, scaled by the given factor
*/
Image Scale(Image image, double scale);
ScaleX#
/**
* Returns a version of an image that is scaled along the x-axis.
*
* Examples:
* given: Rectangle(50,50, RED), 2.0
* expect: An image of a 100x50 red rectangle
*
* @param image The image to be scaled.
* @param scale The x-scaling factor
* @return An image like the given one, scaled on
* the x-axis by the given factor
*/
Image ScaleX(Image image, double scale);
ScaleY#
/**
* Returns a version of an image that is scaled along the y-axis.
*
* Examples:
* given: Rectangle(50,50, RED), 2.0
* expect: An image of a 50x100 red rectangle
*
* @param image The image to be scaled.
* @param scale The y-scaling factor
* @return An image like the given one, scaled on
* the y-axis by the given factor
*/
Image ScaleY(Image image, double scale);
Mask#
/**
* Masks a given image to the shape of another one.
* This may cut off parts by the image and affects
* its intersection behavior.
*
* Examples:
* given: Rectangle(50, 50, RED), Circle(27, BLUE)
* expect: A red rectangle with some part of its edges cut off.
*
* @param image The image to be masked
* @param mask The image to use as the mask
* @return A masked version of the given image
*/
Image Mask(Image image, Image mask);
ShowImage#
/**
* Shows an image in a new window.
*
* Examples:
* given: Rectangle(50, 50, GRAY)
* expect: A window filled with a 50x50 gray rectangle
*
* @param image The image to be shown
* @param title A title for the window
* OPTIONAL, default = "Image"
*/
void ShowImage(Image image, String title);
World#
Enumerations#
KeyEventKind#
/**
* Represents a kind of keyboard event
*/
enum KeyEventKind {
/** A key has been pressed down, but not yet released
*/
KEY_PRESSED,
/** A key that had been pressed down has been released
*/
KEY_RELEASED,
/** For keys that result in text, this represents the direct
* result of having entered that text. That is, the
* corresponding KeyEvent will distinguish "A" from "a",
* depending on whether the SHIFT key has also been pressed.
*/
KEY_TYPED
}
// TEMPLATE:
// {
// return ... switch(keyeventkind) {
// case KEY_PRESSED -> ...;
// case KEY_RELEASED -> ...;
// case KEY_TYPED -> ...;
// } ...;
// }
MouseEventKind#
/**
* Represents a kind of mouse event
*/
enum MouseEventKind {
/** The left mouse button has been clicked (down+up)
*/
LEFT_CLICK,
/** The right mouse button has been clicked (down+up)
*/
RIGHT_CLICK,
/** The middle mouse button has been clicked (down+up)
*/
MIDDLE_CLICK,
/** The left mouse button has been pressed down
*/
LEFT_BUTTON_DOWN,
/** The right mouse button has been pressed down
*/
RIGHT_BUTTON_DOWN,
/** The middle mouse button has been pressed down
*/
MIDDLE_BUTTON_DOWN,
/** The left mouse button has been released
*/
LEFT_BUTTON_UP,
/** The right mouse button has been released
*/
RIGHT_BUTTON_UP,
/** The middle mouse button has been released
*/
MIDDLE_BUTTON_UP,
/** The mouse has been moved
*/
MOUSE_MOVE,
/** The mouse has entered the window
*/
MOUSE_ENTER,
/** The mouse has left the window
*/
MOUSE_LEAVE
}
// TEMPLATE:
// {
// return ... switch(mouseeventkind) {
// case LEFT_CLICK -> ...;
// case RIGHT_CLICK -> ...;
// case MIDDLE_CLICK -> ...;
// case LEFT_BUTTON_DOWN -> ...;
// case RIGHT_BUTTON_DOWN -> ...;
// case MIDDLE_BUTTON_DOWN -> ...;
// case LEFT_BUTTON_UP -> ...;
// case RIGHT_BUTTON_UP -> ...;
// case MIDDLE_BUTTON_UP -> ...;
// case MOUSE_MOVE -> ...;
// case MOUSE_ENTER -> ...;
// case MOUSE_LEAVE -> ...;
// } ...;
// }
Records#
KeyEvent#
/**
* A KeyEvent records a concrete keyboard event,
* e.g. a key press or release of a specific key
* Examples:
* - KeyEvent(KEY_TYPED, "A")
* - KeyEvent(KEY_TYPED, "a")
* - KeyEvent(KEY_PRESSED, "Space")
* - KeyEvent(KEY_RELEASED, "F10")
* @param kind The kind of event. See the KeyEventKind enumeration.
* @param key The key that was pressed. Depending on the event kind,
* this may be the name of a key, e.g. "Space" (for
* press/release events), or a string representation of
* what was typed.
*/
record KeyEvent(
KeyEventKind kind,
String key) {}
// TEMPLATE:
// { ... keyevent.kind() ... keyevent.key() ... }
MouseEvent#
/**
* A MouseEvent records a concrete mouse event,
* e.g. a button click/press/release or mouse move
* Examples:
* - MouseEvent(LEFT_CLICK, 15, 237)
* - MouseEvent(RIGHT_BUTTON_DOWN, 211, 853)
* - MouseEvent(MOUSE_MOVE, 500, 12)
* - MouseEvent(MOUSE_LEAVE, 0, 63)
* @param kind The kind of event. See the MouseEventKind enumeration.
* @param x The x-coordinate of the mouse at the time of the event.
* @param y The y-coordinate of the mouse at the time of the event.
*/
record MouseEvent(
MouseEventKind kind,
int x,
int y) {}
// TEMPLATE:
// { ... mouseevent.kind() ... mouseevent.x() ... mouseevent.y() ... }
Functions#
BigBang#
/**
* Examples: see below
*
* @param name the name of the window
* @param startState the initial value for the world state
* @param drawFunction a function that represents the current world state as an Image
* @param stepFunction a function that returns a new world state after a clock tick
* @param keyFunction a function that returns a new world state after a key event
* @param mouseFunction a function that returns a new world state after a mouse event
* @param endPredicate returns whether the world state indicates that the program has ended
*/
<State> void BigBang(String name, State startState, Function<State, Image> drawFunction, Function<State, State> stepFunction, BiFunction<State, KeyEvent, State> keyFunction, BiFunction<State, MouseEvent, State> mouseFunction, Predicate<State> endPredicate);
BigBang is used to start a World program, which is an interactive gui program that draws images on the screen based on world states, which themselves can evolve via clock ticks, keyboard events, and mouse events. The clock tick frequency is 30 clock ticks/second. This function is modeled after the Universe teachpack in HtDP (that is, if you are reading the book, this library works in very similar ways to what is described there).
The arguments keyFunction
, mouseFunction
, and endPredicate
are optional - you do not have to specify them, but when you do, you need to keep them in the same order. stepFunction
is also optional, but needs to be present if either keyFunction
or mouseFunction
are present.
The world state can be any data type you like, but it needs to be the same data type throughout the program. You need to write functions that provide the necessary functionality for each argument that you are using - at the very minimum, a drawing function, but in most cases at least also a stepping function.
Below is an example program that simply uses an integer as a state. Each clock tick increases the integer by one, and the program draws the integer as blue text on a gray background as shown in the following image:
import comp1110.universe.*;
import comp1110.lib.*;
import static comp1110.lib.Functions.*;
import static comp1110.universe.Colour.*;
import static comp1110.universe.Image.*;
import static comp1110.universe.Universe.*;
/**
* Draws the world state as blue text on gray background
* Examples:
* given: 0 expect: an image of a blue "0" centered on a gray background
* given: 15 expect: an image of a blue "15" centered on a gray background
* Strategy: Combining Simpler Functions
* @param state the current world state (a counter value)
* @return an image representing the world state (the counter value in blue on gray background)
*/
Image draw(int state) {
Image text = Text(ToString(state), 40, -1, BLUE, "Consolas", FontStyle.BOLD, TextAlign.CENTER);
return Place(Rectangle(200, 50, GRAY), text);
}
/**
* Increases the counter representing the world state by one.
* Examples:
* given: 0 expect: 1
* given: 15 expect: 16
* Strategy: Simple Expression
* @param state the world state at the start of the tick
* @return the world state after the tick
*/
int step(int state) {
return state+1;
}
void main() {
BigBang("Example", 0, this::draw, this::step);
}
void test() {
}