Images
Designing Images
Designing images for the games
The images that comprise the game scene are drawn on Canvas.
The programmer specifies the size of the Canvas
when the game starts. Every image that the programmer defines has a pinhole —
The color of the image can be specified in one of two ways. For the beginner, we supply the interface IColor and six classes that implement this interface: Black, White, Red, Blue, Green, and Yellow. To define the red color, the programmer just writes: new Red(). For more advanced programmers the library uses the java.awt.Color class with the predefined constants for some of the color shades (e.g. Color.red, Color.cyan, Color.orange, Color.magenta, Color.gray) as well as any constructors for the instances of the Color class (e.g. new Color(255, 0, 0, 155) that defines a semi-transparent red color).
All images extend the abstract class WorldImage. The following diagram describes the classes that represent the basic geometric shapes, and some additional ways of creating images:
+-------------+ |
| WorldImage | |
+-------------+ |
| int pinhole | |
| Color color | |
+-------------+ |
/ \ |
--- |
| |
------------------------------------------------------------------ |
| | | | | | | | | | |
| +----------------+ | | +------------+ | | +--------------+ | | |
| | RectangleImage | | | | DiskImage | | | | EllipseImage | | | |
| +----------------+ | | +------------+ | | +--------------+ | | |
| | int width | | | | int radius | | | | int width | | | |
| | int height | | | +------------+ | | | int height | | | |
| +----------------+ | | | | +--------------+ | | |
| | | | | | | |
| +-----------+ | +--------+ | +-----------+ | |
| | | | | | | |
| +------------+ | +--------------+ | +------------+ +-+ |
| | FrameImage | | | CircleImage | | | OvalImage | | |
| +------------+ | +--------------+ | +------------+ | |
| | int width | | | int radius | | | int width | | |
| |int height | | +--------------+ | | int height | | |
| +------------+ | | +------------+ | |
| +-----------------+ | +---------------+ |
+-----+ | LineImage | | | TriangleImage | |
| +-----------------+ | +---------------+ |
+----------------+ | Posn startPoint | | | Posn p1 | |
| OverlayXY | | Posn endPoint | | | Posn p2 | |
+----------------+ +-----------------+ | | Posn p3 | |
| WorldImage bot | | +---------------+ |
| WorldImage top | | |
| int dx | +-----------------+ |
| int dy | | FromFileImage | |
+----------------+ +-----------------+ |
/ \ | String filename | |
--- +-----------------+ |
| |
+----------------+ |
| Overlay | |
+----------------+ |
| WorldImage bot | |
| WorldImage top | |
+----------------+ |
Every class includes two full constructors, one that takes the color defined as an instance of the java.awt.Color class, the other that uses our simplified colors as defined in the javalib.color library.
Every class also defines the toString() and the toIndentedString(String indent) methods that produce a formatted String that represents this object (possibly indented as desired).
Every class implements the methods getWidth() and getHeight() methods.
Every image has a pinhole that represents its current location on the Canvas. The methods that change the location of the image are described in Managing the image location
Geometric shapes
Here is a simple description of each class that represents a basic geometric shape.
RectangleImage class represents a filled rectangle with the pinhole in the center, and the given width, height, and color.
FrameImage class represents a rectangular frame with the pinhole in the center, and the given width, height, and color.
OvalImage class represents a filled ellipse image with the pinhole in the center, and the given width, height, and color.
EllipseImage class represents an ellipse outline image with the pinhole in the center, and the given width, height, and color.
DiskImage class represents a filled disk image with the pinhole in the center, and the given radius and color.
CircleImage class represents a circle outline image with the pinhole in the center, and the given radius and color.
LineImage class represents a line image with the the given start and end points in the given color. The constructor places the pinhole in the middle of the line.
TriangleImage class represents a filled triangle image with the given three points in the given color. The constructor places the pinhole in the middle of the triangle.
Text, images, composites
The programmer may also display text, images from .png files, and combine several images into a composite as follows:
TextImage class represents a text shown in the given size and style and in the given color at the location of its pinhole. The size of the text by default is 13, the programmer can change it as desired. The style is specified as follows: regular style = 0, bold face = 1, italic = 2, bold and italic = 3.
FromFileImage class represents an image read from the given .png file. The pinhole is in the center of the image. The library reads the file only once and reuses it any time it is displayed.
OverlayImagesXY class represents a combination of two images, The bottom image is drawn first, the second (top) image is then drawn after its pinhole has been moved by the given distance (dx, dy). The pinhole for the resulting image is in the middle of the pinholes of the bottom and the top image.
OverlayImages class is a convenience class that overlays two images without any change in the pinhole for the top image.
Additionally, the abstract WorldImage class includes the method
WorldImage overlay(WorldImage ...)
that overlays an arbitrary number of images on top of the bottom image that invokes the method without moving any of the images. The pinhole is computed to be the average of the pinholes of all combined images.
Managing the image location
The abstract WorldImage class also includes the methods that allow the programmer to change the location of the pinhole of an image as follows:
When programming in the functional (mutation-free) style the following methods produce new images moved as specified:
// produce an image moved by the given distance
WorldImage getMovedImage(int dx, int dy)
// produce an image moved to the given location
WorldImage getMovedTo(Posn p)
When programming in the imperative style the following methods can be used to modify the location of the pinhole:
// EFFECT: move the pinhole of this image by (dx, dy)
void movePinhole(int dx, int dy)
// EFFECT: move the pinhole of this image to the given position
void moveTo(Posn p)
Image Samples
A sample of the image types:

and the code that generated the image:
package worldimagestests; |
|
import javalib.colors.*; |
import javalib.funworld.*; |
import javalib.worldcanvas.WorldCanvas; |
import javalib.worldimages.*; |
|
import java.awt.*; |
|
/** |
* Copyright 2012 Viera K. Proulx |
* This program is distributed under the terms of the |
* GNU Lesser General Public License (LGPL) |
*/ |
|
/** |
* A complete set of images displayed in the Canvas |
* |
* author Viera K. Proulx |
* since 5 February 2012 |
*/ |
public class ExamplesImageDrawings { |
|
public ExamplesImageDrawings() {} |
|
// support for the regression tests |
public static ExamplesImageDrawings examplesInstance = |
new ExamplesImageDrawings(); |
|
// a text inside a red rectangle with a yellow dot in its pinhole location |
public static WorldImage makeText(Posn pos, int size){ |
WorldImage hello = |
new TextImage(pos, "quickbrownfoxjumpedoveralazydog", size, 3, new Blue()); |
|
WorldImage helloRed = |
new OverlayImages( |
new RectangleImage(pos, |
hello.getWidth(), hello.getHeight(), |
new Red()), |
hello); |
return |
new OverlayImages(helloRed, |
new DiskImage(hello.pinhole, 2, new Yellow())); |
} |
|
WorldImage circleText = |
new TextImage(new Posn(200, 20), |
"CircleImage(new Posn(200, 60), 10, new Red())", Color.red); |
WorldImage circle = new CircleImage(new Posn(200, 60), 10, new Red()); |
|
|
WorldImage diskText = |
new TextImage(new Posn(200, 100), |
"DiskImage(new Posn(200, 140), 10, new Red())", Color.red); |
WorldImage disk = new DiskImage(new Posn(200, 140), 10, new Red()); |
|
|
WorldImage lineText = |
new TextImage(new Posn(220, 180), |
"LineImage(new Posn(200, 220), new Posn(280, 230), Color.green)", Color.green); |
WorldImage line = |
new LineImage(new Posn(200, 220), new Posn(280, 230), Color.green); |
|
|
WorldImage triangleText = |
new TextImage(new Posn(280, 260), |
"TriangleImage(new Posn(250, 300), new Posn(200, 340), new Posn(150, 310), Color.cyan)", |
Color.cyan); |
WorldImage triangle = |
new TriangleImage(new Posn(250, 300), new Posn(200, 340), new Posn(150, 310), Color.cyan); |
|
|
WorldImage ellipseText = |
new TextImage(new Posn(600, 20), |
"EllipseImage(new Posn(600, 60), 60, 20, new Blue())", new Blue()); |
WorldImage ellipse = new EllipseImage(new Posn(600, 60), 60, 20, new Blue()); |
|
WorldImage frameText = |
new TextImage(new Posn(600, 100), |
"FrameImage(new Posn(600, 120), 60, 20, new Black())", new Black()); |
WorldImage frame = new FrameImage(new Posn(600, 120), 60, 20, new Black()); |
|
WorldImage ovalText = |
new TextImage(new Posn(600, 180), |
"OvalImage(new Posn(600, 220), 60, 20, new Yellow())", new Yellow()); |
WorldImage oval = new OvalImage(new Posn(600, 220), 60, 20, new Yellow()); |
|
WorldImage rectangleText = |
new TextImage(new Posn(600, 300), |
"RectangleImage(new Posn(600, 330), 60, 20, Color.orange)", Color.orange); |
WorldImage rectangle = new RectangleImage(new Posn(600, 330), 60, 20, Color.orange); |
|
WorldImage fromFileText = |
new TextImage(new Posn(600, 420), |
"FromFileImage(new Posn(600, 480), fish.png)", Color.black); |
WorldImage fish = new FromFileImage(new Posn(600, 480), "fish.png"); |
|
WorldImage combined = |
this.circleText.overlayImages( |
this.circle, |
this.diskText, |
this.disk, |
this.lineText, |
this.line, |
this.triangleText, |
this.triangle, |
this.ellipseText, |
this.ellipse, |
this.frameText, |
this.frame, |
this.ovalText, |
this.oval, |
this.rectangleText, |
this.rectangle, |
this.fromFileText, |
this.fish); |
|
|
public static void main(String[] args) { |
|
WorldCanvas c = new WorldCanvas(800, 600); |
|
WorldImage pic = ExamplesImageDrawings.makeText(new Posn(300, 400), 15); |
|
ExamplesImageDrawings e = new ExamplesImageDrawings(); |
|
// show several images in the canvas |
boolean makeDrawing = |
c.show() && |
c.drawImage(e.combined) && |
c.drawImage(pic); |
} |
} |