Graphics Library (#include "library.h")
The following lists the most generally useful
things defined in the graphics library. If some essential function seems to be
missing, send a message and I'll look into the possibility of adding something.
Important Notes:
- The co-ordinate system is not exactly what you may be used to when
plotting mathematical graphs; the y axis is "upside-down" for compatibility
with most computer grahics functions. These library functions operate on a
rectangular window. Co-ordinates of the form (x,y) are measured in pixels. X
ranges from 0 at the left to a maximum at the right. Y ranges from 0 at the
TOP to a maximum at the bottom.
- Co-ordinates (x,y) passed to the drawing functions do not need to be
whole numbers (ints); floats and doubles are accepted.
- Attempting (accidentally or otherwise) to draw outside the graphics window
has no adverse effect. Everything behaves exactly as normal, but nothing is
drawn until the position comes back inside the window.
- The system always remembers the direction of the last movement made
(whether drawing a line, or just moving the pen). When you want to draw a line
or move the pen, you may either specify the co-ordinates of the end of the
line, or just the length of the line. If you just specify the length, it moves
in the previously established current direction.
- All functions that deal with directions or angles have two versions,
one with an unadorned name that measures angles in radians, and one with
"Degrees" in its name that measures angles in degrees. For example,
TurnLeftBy() and TurnLeftByDegrees().
- All functions that deal with degrees instead of radians round
angles to the nearest minute (1/60 degree) before and after all operations.
This means that specific (cardinal) directions will always be stored
accurately. For example, 180 degrees is equivalent to pi radians.
Turning by 1 degree 360,000,000 times and turning pi/180 radians 360,000,000 times
should result in no net change of direction, but due to the errors
inherent in floating point arithmetic, there is a net change of direction
when radians are used, but because of the special rounding scheme not when degrees are used.
- Headings are arranged so that 0 means "up" or "North", 90 degrees (or
pi/2 radians) means "right" or "east", 180 degrees (pi radians) means "down"
or "south", and 270 degrees means "left" or "west". Of course intermediate
values are allowed.
- When the system starts, the pen is at the exact centre of the window. Its
current direction is initially "up", or "north", or the direction of
decreasing y values.
- The width of the pen is initially one pixel, but may be set at any time to
any (int) width.
- The colour of the pen is initially black, but may be set at any time to
any colour that your monitor can handle. Changing the colour of the pen has no
effect on what has already been drawn, only on what you are about to draw.
- Pen colours are described by three numbers, being the components of the
colour in the standard human additive primary colours (red, green, blue).
There are two versions of the colour setting functions, one takes (float)
numbers in the range 0 to 1, and one that takes (int) numbers in the range 0
to 255. 0 represents the particular colour component being off, and the
maximum (1 or 255) represents maximum intensity. The following are just a few
examples of colour descriptions:
| black
|
| (0.0, 0.0, 0.0)
|
| (0, 0, 0)
|
| **LIKE THIS**
|
| white
|
| (1.0, 1.0, 1.0)
|
| (255, 255, 255)
|
| **LIKE THIS**
|
| red
|
| (1.0, 0.0, 0.0)
|
| (255, 0, 0)
|
| **LIKE THIS**
|
| green
|
| (0.0, 1.0, 0.0)
|
| (0, 255, 0)
|
| **LIKE THIS**
|
| blue
|
| (0.0, 0.0, 1.0)
|
| (0, 0, 255)
|
| **LIKE THIS**
|
| yellow
|
| (1.0, 1.0, 0.0)
|
| (255, 255, 0)
|
| **LIKE THIS**
|
| orange
|
| (1.0, 0.5, 0.0)
|
| (255, 127, 0)
|
| **LIKE THIS**
|
| light blue
|
| (0.7, 0.7, 1.0)
|
| (178, 178, 255)
|
| **LIKE THIS**
|
| gray
|
| (0.6, 0.6, 0.6)
|
| (153, 153, 153)
|
| **LIKE THIS**
|
| pale pink
|
| (1.0, 0.9, 0.9)
|
| (255, 230, 230)
|
| **LIKE THIS** |
Basic Drawing Functions
- int CheckSameVersions()
Checks that the .h and .cpp files have the same version
number. Returns 1 if same. Prints message and returns
0 if different.
- Exit(); Like the stdlib function
exit(1) but compatible with graphics. Stops
the program permanently, but does not destroy any
open windows.
- void MakeWindow(int w, int h); Create the window (only use
this once), width of usable surface is w pixels, height is h pixels. If
MakeWindow is not used, the first graphics function used will automatically
create a window occupying the whole screen area. (example)
- void MakeWindow(int w, int h, int x, int y); Create the
window as above, with top left corner at screen co-ordinates (x,y).
- CloseWindow(); Closes the graphics
window, as normally done by clicking the close button.
- SetCaption(string s) Sets the text in the
title bar of the window.
- void GetSize(int w, int h); Sets w to the width of the
window, and h to its height, both in Pixels. w and h must both be variables.
- SetSize(w, h); Changes the size of
the window, as though the user had dragged the bottom
right corner with the mouse. This function generates
a WINDOW_RESIZED event with the Cause set to 1.
- MoveTo(x, y); Move the pen to (x,y) without
drawing. (example)
- DrawLineTo(x, y); Draw a line from the current
position to position (x,y). (example)
-
void DrawLineBy(dx, dy); Relative line drawing: if the pen is currently at position (x,y),
this function draws a line from (x,y) to (x+dx,y+dy). The new pen position becomes (x+dx,y+dy) and
the current direction is set to the direction the line was drawn in.
-
void MoveBy(dx, dy); Relative pen movement: if the pen is currently at position (x,y),
this function moves the pen to (x+dx,y+dy) without drawing a line. The new pen position becomes (x+dx,y+dy) and
the current direction is set to the direction the movement was drawn in.
-
void DrawRectangleXYXY(x1,y1,x2,y2); Outline Rectangle:
draws the outline of a rectangle. Equivalent to drawing lines between (x1,y1) and (x2,y1),
(x2,y1) and (x2,y2), (x2,y2) and (x1,y2), and (x1,y2) and (x1,y1). Does not change the
pen position or direction.
-
void DrawRectangleXYWH(x1,y1,w,h); Outline Rectangle:
draws the outline of a rectangle. Equivalent to drawing lines between (x1,y1) and (x1+w-1,y1),
(x1+w-1,y1) and (x1+w-1,y1+h-1), (x1+w-1,y1+h-1) and (x1,y1+h-1), and (x1,y1+h-1) and (x1,y1). Does not change the
pen position or direction.
-
void FillRectangleXYXY(x1,y1,x2,y2); Solid Rectangle:
Eaxactly the same as DrawRectangleXYXY, except that the interior of the rectangle is filled
with the current pen colour.
Does not change the pen position or direction.
-
void FillRectangleXYWH(x1,y1,w,h); Solid Rectangle:
Eaxactly the same as DrawRectangleXYWH, except that the interior of the rectangle is filled
with the current pen colour.
Does not change the pen position or direction.
- DrawPointAt(x, y); Moves to position (x,y), then
draws a round dot determined by the current pen width and colour. (example).
- DrawPointHere(); Draws a round dot determined by the
current pen width and colour, at the current pen position.
- ColorPixel(int x, int y, double r, double g, double b);
Sets the single pixel (not determined by the pen width) at position (x,y) to
the colour described by (r,g,b). This function does NOT change the current
position or direction, NOR does it change the current pen colour. Components
r, g, and b are in the range 0-1. For the ColorPixel-like functions,
individual pixels are explicitly addressed, so x and y must be ints.
- ColorPixel0255(int x, int y, int r, int g, int b);
Identical to the above, except r, g, and b are ints in the range 0-255.
- ColorPixel(int x, int y, int c);
Identical to the above, except that the color is passed in encoded as a single
int. See EncodeColor below.
- DrawLineLength(s); Draw a line of length s pixels,
continuing in the current direction. (example)
- MoveByLength(s); The same as DrawByLength(s), except
that no line is drawn, the pen position just moves.
- TurnLeftBy(angle); and TurnLeftByDegrees(float angle);
Change the current direction
without moving or making a mark. (example)
- TurnRightBy(angle); and
TurnRightByDegrees(angle);
Change the current direction
without moving or making a mark.
(example)
- TurnToHeading(angle); and
TurnToHeadingDegrees(angle);
Change the current direction
without moving or making a mark.
(example)
- double DirectionTo(x, y); and
double DirectionToDegrees(x, y);
Calculates the direction
from the current pen position towards coordinates (x,y). This function does
not change the pen's direction or position, it simply returns a direction
suitable for use by TurnToHeading.
- double DistanceTo(x, y);
returns the distance between the current pen position and the point (x,y).
- double DistanceFromTo(x1, y1, x2, y2);
For those who have forgotten Pythagoras:
returns the distance between the two points (x1,y1) and (x2,y2).
- double DirectionFromTo(x1, y1, x2, y2); and
double DirectionFromToDegrees(x1, y1, x2, y2);
Returns the direction that a straight line would have if drawn
from point (x1,y1) to point (x2,y2).
- GetPosition(x, y);
The parameters must
be variables (int, float, or double), not expressions or constants. Calling this function sets x and y
to the current pen position.
- double GetHeading(); and
double GetHeadingDegrees();
Similar to GetPosition, but returns the current heading.
- Clear(); Clear the screen to all blank/white.
- Pause(double secs); Makes a delay in execution, so that
you can see complex graphics growing at a slower than normal pace. The
smallest possible pause is 1 milli-second, caused by Pause(0.001);
there is no maximum length of pause. The time parameter may be int, float or
double. (example).
- Hide(); Makes the window disappear. It is not closed, just invisible.
You can use Show() at any time to make it come back, with its content intact.
- Show(); Make the window appear on the screen. Only needed
if you have used Hide() to make it disappear.
- int GetPixelColor(int x, int y) returns the colour of the pixel at co-ordinates x,y
encoded as a single integer using the same encoding scheme as the EncodeColor functions.
- GetPixelColor0255(int x, int y, int r, int g, int b) reads the colour of pixel
at co-ordinates x,y and stores the red/green/blue values (in the range 0-255) in the parameters r, g, b which must be
int variables.
- GetPixelColor(int x, int y, r, g, b) The same as GetPixelColor0255, except
the r, g, and b may be float or double variables, and receive values in the range 0 to 1.
Shapes and Filling
The graphics system is capable of recording a complex shape
and drawing or filling that shape later. A shape is assumed to
be bounded by a number of connected straight lines (think of
a triangle or a star), and the only information needed to
completely define a shape is the positions of its corners
(vertices). A shape is made by moving the pen around the
vertices of the shape, recording each as it is reached.
- StartShape(); Must be called before any
of the other shape functions. All previous shape data is forgotten,
and anew one is allowed to start.
- AddHereToShape(); The co-ordinates of
the current pen position are recorded as the next corner/vertex
of the shape being defined.
- AddVertexToShape(x,y); The co-ordinates (x,y)
are recorded as the next corner/vertex of the shape being
defined; the current pen position is irrelevant.
- DrawShape(); The most recently defined shape
is drawn in outline.
- FillShape(); The most recently defined shape
is draw and filled with solid colour (the current pen colour
naturally). Outlined shapes may be drawn by first defining a shape,
then calling FillShape, then changing the pen colour and calling
DrawShape. After a shape has been recorded, it may be drawn
many times.
- DrawShapeScaled(double s); FillShapeScaled(double s);
are exactly the same as DrawShape and FillShape, except that the shape is
drawn at a different scale. It starts from the same position, and all
angles are preserved, but the lengths of all the edges are multiplied
by a factor of s (the parameter).
- DrawShapeHere(); FillShapeHere(); DrawShapeHereScaled(s);
FillShapeHereScaled(s); Functionally the same as the previous
four functions, but the shape is moved before it is drawn. The first
vertex/corner of the drawn shape is at the current pen position. All
other vertices keep the same relative position, so the shape is moved
to a new location without distortion.
Clipping and Regions
- RestrictDrawingTo(Region r); [A Region
is a rectangular sub-area of the screen; functions for making
Regions are described below] All drawing operations are clipped
to the specified region: any drawing outside this region has
no visible effect, but all operations behave as normal otherwise.
- UnrestrictedDrawing(); Cancels the effect
of RestrictDrawingTo.
- Region MakeRegionXYXY(int x1, int y1, int x2, int y2)
creates a Region object suitable for passing to RestrictDrawingTo;
the region is rectangular with (x1,y1) as the top-left corner, and
(x2,y2) as the bottom-right corner.
- Region MakeRegionXYWH(int x, int y, int w, int h)
creates a Region object suitable for passing to RestrictDrawingTo;
the region is rectangular with (x,y) as the top-left corner, and
(x+w,y+h) as the bottom-right corner.
Colours and Pen Widths
- PenWidth(int w) Set the width of the pen to w pixels. (example).
- PenColor(float r, float g, float b); Set the pen colour;
r, g, b in range 0-1. Parameters can be either floats or doubles. (example).
- PenColor0255(int r, int g, int b); Set the pen colour; r,
g, b in range 0-255. (example).
- PenColor(int c); Set the pen colour; c is
an encoded colour as created by EncodeColor.
- PenWidthColor(int w, float r, float g, float b); Special
combined function, sets pen width and colour in a single operation; more
efficient.
- PenWidthColor0255(int w, int r, int g, int b); Special
combined function, sets pen width and colour in a single operation; more
efficient. (example).
- PenWidthColor(int w, int c); Special
combined function, sets pen width and colour in a single operation; more
efficient..
- int EncodeColor(double r, double g, double b);
There are only about 16,000,000 possible different colours, which means
that each possible colour can be encoded as a single integer (for convnience:
programs have to handle one combined value instead of three (r,g,b) components).
All the color-using functions have a version that accepts encoded colours.
For this function (r,g,b) must all be in the range 0.0 to 1.0.
- int EncodeColor0255(int r, int g, int b);
The same as EncodeColor (above) except that the parameters are
ints in the range 0 to 255.
- DecodeColor0255(int c, int r, int g, int b);
The first parameter is an encoded colour as created by EncodeColor;
the next three parameters (r,g,b) (which must be variables) are set to the
components of that colour, in the range 0 to 255.
- DecodeColor(int c, double r, double g, double b);
The first parameter is an encoded colour as created by EncodeColor;
the next three parameters (r,g,b) (which must be variables) are set to the
components of that colour, in the range 0.0 to 1.0.
- HLStoRGB(double H, double L, double S, double R, double G, double
B); HLS and RGB are alternative ways of describing colours. With the
RGB system, you mix lights of the three primary colours, specifying the
relative brightnesses of each. With HLS (Hue, Lightness, and Saturation) the
controls are more like they were on an old colour television. Hue (0.0 to 1.0)
gives the basic colour, (0.0=pure red, 0.3333=pure blue, 0.6667=pure green,
and 1.0=pure red again, intermediate colours have intermediate values, so
purple is at about 0.16, yellow at 0.84, and orange at 0.9). Lightness (0.0 to
1.0) controls brightness (0.0=black, 0.5=normal for primary colours,
1.0=white). Saturation (0.0 to 1.0) controls the amount of colour present
(0.0=no colour, only grays; 1.0=full colour). The HLStoRGB function converts
from and HLS description to an RGB decription; the PenColor functions only
accept RGB descriptions. The last three parameters of HLStoRGB (R, G, B) must
be variables to receive the result. (example).
- RGBtoHLS(double R, double G, double B, double H, double L, double
S); The opposite of HLStoRGB, see description above.
Displaying Text
- WriteText(string s); Writes the string as normal text in
the current pen colour; current pen width is ignored. The current pen position
is on the baseline of the written text, and immediately to its left. The pen
position is not moved by this function. (example)
- WriteUnicode(int n); Writes single character whose unicode
encoding is n.
- WriteTextf(string format, ...); Similar to WriteText
except that it doesn't just take a fixed string to print, it takes the
same parameters as the stdio function printf.
-
SetFontSize(int sz); Sets the font for all subsequent calls to WriteText().
The "point size" of the font is changed to sz; all other attributes remain unchanged. If the
required size is not available, the system finds the closest matching font.
-
SetFontAttributes(int at); Sets the font for all subsequent calls to WriteText().
The parameter is constructed by adding together any of the following predefined constants:
FONT_NORMAL, FONT_BOLD, FONT_ITALIC, FONT_UNDERLINE, FONT_STRIKEOUT.
The point size and font name remain unchanged. If the required attributes are not available for
the selcted font, the system finds the closest match.
-
SetFontFace(int f) Sets the font style to one of the predefined standard fonts.
That parameter may be one of FONT_ROMAN, FONT_FIXED, or FONT_SANS_SERIF. (FONT_ROMAN may also
be called FONT_SERIF; FONT_SANS_SERIF may also be called FONT_SANS). Point size and attributes
of the font are not modified.
-
SetFontFace(string fontname)
Selects the font with the given name. The name may specify any installed font; if the font is
not available, the system will pick a different one. Example names: "Times New Roman",
"Comic Sans MS", "Symbol".
Point size and attributes of the font are not modified.
-
SetFontFace(char *fontname) Same as SetFontFace(string).
-
SetFontFaceAttributesSize(string fontname, int fa, int sz) Same as the sequence of
calls SetFontFace(fontname); SetFontAttributes(fa); SetFontSize(sz); but more efficient.
-
SetFontFaceAttributesSize(char *fontname, int fa, int sz) Same as the sequence of
calls SetFontFace(fontname); SetFontAttributes(fa); SetFontSize(sz); but more efficient.
- UseDefaultFont() Reverts to using the default windows font.
- int GetNumberOfFonts() returns the number of different fonts currently available for
use.
- string GetFontName(int i) returns the name of one of the available fonts; i must be
positive, and less than the number of fonts. The string returned is suitable for use in the SetFontFace
function.
-
MeasureText(String s, int w, int h) (the second and third parameters must be variables).
This function calculated the space required to write the given text in the current font; the parameters
w and h are set to the width and height of that space. Thus, the following sequence of calls:
MoveTo(x,y); WriteText("Hello"); MeasureText("Hello", w, h); DrawRectangleXYWH(x,y,w,h);
draws the string "Hello" with a box around it.
-
MeasureUnicode(int n, int w, int h) same as above, except that it provides the display
size of the single character whose unicode encoding is n.
-
MeasureText(char *s, int w, int h) same as above.
Events: mouse, keyboard, window, timer
- CaptureEvents(e); Used to notify
the system which kinds of events you want your program
to be given. Programs are only notified of events
that are explicitly requested with CaptureEvents.
These are the following kinds of events:
- MOUSE_PRESS_L
The left mouse button being pressed
- MOUSE_PRESS_M
The middle mouse button being pressed
- MOUSE_PRESS_R
the right mouse button being pressed
- MOUSE_RELEASE_L
The left mouse button being released
- MOUSE_RELEASE_M
The middle mouse button being released
- MOUSE_RELEASE_R
The right mouse button being released
- MOUSE_CLICK_L
The left mouse button being clicked
- MOUSE_CLICK_M
The middle mouse button being clicked
- MOUSE_CLICK_R
The right mouse button being clicked
- MOUSE_CLICKS
Any mouse button being clicked
- MOUSE_MOVEMENT
The mouse being moved, regardless of buttons being pressed or not
- KEY_TYPED
A chanracter (except control-C) being typed on the keyboard
- CONTROL_C_TYPED
Control-C being typed on the keyboard
- WINDOW_RESIZED
The window changing size dut to user action.
- WINDOW_MINIMIZED
The window being minimised (reduced to an icon on the task bar)
- WINDOW_RESTORED
The window being restored from minimized state
- WINDOW_CLOSED
The window being closed
- WINDOW_EVENTS
Any of the window events except WINDOW_CLOSED
- TIMER_SIGNAL
A timer "going off"
- MENU_SELECTED
A Menu item being selected by the user.
Notes about events
- Programs receive notification of these events happening
by using the GetNextEvent function described below.
- The effect of CaptureEvents() can be reversed by
using the IgnoreEvents() function described later.
- A group of events may be requested either by using multiple
calls to CaptureEvents or by using the | operator to
combine multiple event names in one call: This
CaptureEvents(BUTTON_PRESS_L);
CaptureEvents(BUTTON_PRESS_R);
is equivalent to this:
CaptureEvents(BUTTON_PRESS_L | BUTTON_PRESS_R);
- As events occur they are put into a queue, so that they
can be received later. There is room for 1000 unreceived events to be
waiting in the queue. Events will always be received in the
correct order, even if there is a long delay between the
event happening and the program getting around to seeing it.
- A mouse click is a mouse press followed by a mouse release
at almost exactly the same position. If all three of
BUTTON_PRESS_L, BUTTON_RELEASE_L, and BUTTON_CLICK_L are
selected, then a proper click with the left mouse button
will generate all three events in turn.
- MOUSE_CLICKS is equivalent to
MOUSE_CLICK_L | MOUSE_CLICK_M | MOUSE_CLICK_R.
- If you capture KEY_TYPED events, then keyboard input will
no longer be received in the normal way: read_char() etc will not
work. Instead, any key except control-c will generate a KEY_TYPED event
message containing the ascii code of the key pressed..
- If CONTROL_C_TYPED events are captured, then control-c
will no longer stop the running program, it will be treated
as a perfectly normal character producing a KEY_TYPED event.
Its ascii code is 3.
- When the window is resized (by the user dragging an edge or corner,
or pressing the maximise button), it is not necessary for the
program to do anything; the graphics system automatically notes the
new window size. However, if you want to redraw the window contents
to fit the new size, WINDOW_RESIZED is the event to capture.
- There is no need to take any notice of WINDOW_MINIMIZED events.
Except that if a program does a lot of work continually drawing things,
it can save the effort when the window is minimised and therefore
invisible. The WINDOW_RESTORED only (and always) happens when
a previously minimised window becomes visible again.
Maximising a window is nothing special, it simply produces a
produces a WINDOW_RESIZED event.
- When the close button (with a X in it, top right of any
normal window) is pressed, the normal effect is to close the
window, and if that is the last window to close, the program
is stopped. If WINDOW_CLOSED events are captured, this no longer
happens, the only effect of clicking the close button is
to generate a WINDOW_CLOSED event. The program may choose
to close the window itself using the CloseWindow() function.
- Programs may request automatic timers that expire, or
"go off" at some pre-set time in the future, using the
StartRegularTimer or StartSingleTimer functions described
below. When a timer goes off, it generates a TIMER_SIGNAL
event.
- It is no possible to add normal menus to the graphics
window. When a menu is selected and clicked by the user,
it generates a MENU_SELECTED event.
- IgnoreEvents(e) takes exactly the
same parameters as CaptureEvents(), but it cancels
the request to receive a particular kind or group of
kinds of events.
- GetEventName(e) takes exactly the
same parameters as CaptureEvents(), returns a string
giving the name of the indicated event.
- int GetNextEvent(e, x, y, t, c) the
five parameters must be int variables. The next event
from the queue is removed, and its details are put
into the five variables e, x, y, t, and c, and the
result of the function is 1.
The value of e is one of the event names listed above;
the values of x and y depend on what kind of event
has occured, and are described below. The value of
c is the Cause of the event: 0 means it was caused
by the user, 1 means it was caused by the program.
The value of t
is always a 'timestamp' for when the event occured:
the number of milliseconds since the program started.
(If the program has been running without interruption
for 25 days, the timestamp will become too big for
an integer variable, and won't be totally reliable).
If there were no events
in the queue, e is set to the constant NOTHING_HAPPENED,
and the returned value is 0.
- All Mouse Events: the values of x and y are
the pixel coordinates of where (within the window)
the event occured.
- WINDOW_RESIZED events: x is the new width
of the window, and h the new height. c is 1 if this
was caused by a call to the SetSize function, or 0
if caused by user action.
- KEY_TYPED events: x is the ascii code of
the key typed, or for non-ascii keys, one of the
following constants:
- If KEY_TYPED events are captured, all
catchable keypresses are now reported to the program.
Keys such as "DELETE", "LEFT-ARROW", and "PAGE-UP" have
been assigned codes just outside the normal ASCII range,
but still wihtin the bounds of a char variable. The
following defined constants give the codes for these
keys:
-
KEY_ESC
-
KEY_BACKSPACE
-
KEY_TAB
-
KEY_F1
-
KEY_F2
-
KEY_F3
-
KEY_F4
-
KEY_F5
-
KEY_F6
-
KEY_F7
-
KEY_F8
-
KEY_F9
-
KEY_F10
-
KEY_F11
-
KEY_F12
-
KEY_INSERT
-
KEY_DELETE
-
KEY_HOME
-
KEY_END
-
KEY_PAGE_UP
-
KEY_PAGE_DOWN
-
KEY_UP_ARROW
-
KEY_DOWN_ARROW
-
KEY_LEFT_ARROW
-
KEY_RIGHT_ARROW
-
KEY_ENTER
-
KEY_MENU
-
KEY_PAD_5
Note that all keys on the numeric keypad are just repeats
of other keys, except the "5" when "num-lock" is off.
- string GetCharacterName(int c) converts
any character code into a fully human-readable string
describing it exactly.
- There is no such thing as a CONTROL_C_TYPED
event. CONTROL_C_TYPED is how you ask to be notified
of control-c being typed, but the corresponding event
is a KEY_TYPED event with x set to 3, the ascii code
for control-c.
- TIMER_SIGNAL events: x is set to the
identification number of the timer that went off.
c will always be 1.
- MENU_SELECTED events: x is set to the
identification number of the menu item that was
selcted.
- All others: x and y have no meaningful
value.
- WaitAndGetNextEvent(e, x, y, t, c)
is exactly the same as GetNextEvent except that whereas
GetNextEvent always returns immediately even if no
events have occured yet, WaitAndGetNextEvent will
never return until a real event has happened.
- LimitedWaitAndGetNextEvent(timeout, e, x, y, t, c)
The same as WaitAndGetNextEvent, except that there is a
limit to how long it will wait for an event. the 'timeout'
parameter is a floating point number, and specifies
the maximum time (in seconds) that it will wait. If
that time expires, it behaves like GetNextEvent, returning
0 and setting e to NOTHING_HAPPENED.
- SendEvent(e, x, y); or
- SendEvent(e, x, y, c); Artificially
generates the event of kind e, with parameters x and y,
and sets the cause to c (if c is not supplied, it is
set to 1, the signal for an artificial event).
All parameters must be ints.
If events of type e have not been enabled for capturing,
this has no effect.
- int StartSingleTimer(t) starts a timer,
which will wait t seconds (t is floating point), then
cause a TIMER_SIGNAL event, and never do anything again.
Rememeber to enable capturing of TIMER_SIGNAL events.
The result returned by StartSingleTimer is the identification
number for the timer just created. It is possible to have
many timers all ticking at the same time. When any timer
goes off, the event it causes contains its own identification
number so that the program can tell which timer it was if
necessary. Timer events always ahve a cause equal to 1
because they are caused by the program, not by the user.
- int StartRegularTimer(t) exactly the
same as StartSingleTimer, except this is a repeating timer:
it generates an event every t seconds instead of just once.
Keyboard, Mouse, Input and Output functions
- log("some message"); Debugging graphics programs can be
tricky. The log function prints a message in a permanent file which you can
look at after the program has finished or crashed, so you can build up a trace
of what it did. The message should not have any percent signs (%) in
it; you will learn why later. The file created is called "log.log",
and is usually stored in one of the project's sub-folders.
True Explanation: This function can take a lot of parameters; it works like
printf in that the first parameter must be a string specifying
the format for the entire output. That is why percent signs must be
handled with care.
- int CheckKeyPressed(void); This function returns 1 if
a keyboard key has been pressed and is ready to be read, or zero if no
key is ready. It does not guarantee that a whole line of input is ready,
nor does it read the key. To see which key was pressed, use
read_char_no_wait(). This is not the normal way to see
if keyboard input is ready: see CheckInputReady, below.
- int CheckInputReady(void); This function returns 1 if
a keyboard input is ready to be read, or zero if there is no available input.
This function checks that a whole line of input is available
before returning 1; that is because all the normal input functions wait
for a whole line before taking any characters (otherwise the backspace key
would be useless). This function does not consume any input, it just
sees if its ready. To get the input, use one of the normal read_...()
functions.
(example).
- int read_char_no_wait(void); This is the only keboard
input function that does not wait for a whole line of input before
proceeding. If any key has been typed, its ASCII code is returned.
If no keys have been typed, it returns zero.
- int read_char(void); This function waits until a
whole line of input (terminated by ENTER) has been typed, then takes
the first character and returns its ASCII code.
- void read_char_no_echo(char c);
char read_char_no_echo(void);
char read_char_no_wait_no_echo(void);
These three functions are exactly the same as the similarly named
functions (same name without the "_no_echo" part), except that the character
typed does not appear in the main text window after it has been read.
It does still appear in the input buffer until it has been read.
- SetKeyboardMode(m);, where m may be either
NORMAL_MODE or DIRECT_MODE, modifies how
keypresses are processed. Under NORMAL_MODE (the default
when a program first starts), the backspace key is used to
"un-type" a character, and is never received by a running
program as the result of read_char(); Control-C
terminates the program, and is similarly never received.
Under DIRECT_MODE, all keypresses, no matter what
they normally represent, become input to the running program;
backspace and control-C (amongst others) have no special
effect. While in DIRECT_MODE the one-line input buffer
at the bottom of the console window disappears, to emphasize the
fact that no input buffer processing happens. "Exit", under the
File menu in the console window, may still be used to stop
a program.
- string read_string(void); This function waits until a
whole line of input (terminated by ENTER) has been typed, then takes
the first word and returns it as a string (a word is any sequence of
visible characters).
- string read_line(void); This function waits until a
whole line of input (terminated by ENTER) has been typed, then returns that whole line
as a string.
- int read_int(void); This function waits until a
whole line of input (terminated by ENTER) has been typed, then takes
the first word converts it to an integer, and returns that value.
Note that numbers read this way must be followed by a space or newline
character.
- float read_float(void); This function waits until a
whole line of input (terminated by ENTER) has been typed, then takes
the first word converts it to a float, and returns that value.
Note that numbers read this way must be followed by a space or newline
character.
- double read_double(void); This function waits until a
whole line of input (terminated by ENTER) has been typed, then takes
the first word converts it to a double, and returns that value.
Note that numbers read this way must be followed by a space or newline
character.
- print(...); and newline(); The print
functions take a single parameter that may be an int, double, float, char,
char *, or string, and print it as text in a standard format. newline()
starts a new line of output, and is the same as print("\n");
- printf("format", ...); works
exactly as in the stdio.h library.
- WaitForMouse(int x0, int y0, int x1, int y1, int
b); All five parameters must be variables, they receive results from
this function. This function waits until the user presses and releases the
mouse, either as a click or as a drag operation, entirely within the graphics
window. the varibles (x0,y0) are set to the co-ordinates of the point where
the mouse was pressed, and (x1,y1) are set to the point where the mouse was
released. If those two points are very close it was a click, otherewise it was
a drag. The fifth parameter, b, is set to show which button was pressed:
1=left, 2=right, other buttons are numbered from 3 up. (example).
- WaitForMouseOrInput(int x0, int y0, int x1, int y1, int
b); Exactly the same as WaitForMouse, except that it can be used when
keyboard input may also be expected. If any normal keyboard input is available,
the function returns immediately without waiting any longer for a mouse
operation. To indicate that keyboard input was ready, the fifth parameter (b)
is set to zero instead of a valid button number. Nothing is read from the
keyboard; the standard read_... functions may be used to actually get the
input. This function does not consider input to be ready unless a whole
line (with ENTER at the end) has been typed. This is to allow typing errors
to be corrected using the backspace key.
- WaitForMouseOrKeyPress(int x0, int y0, int x1, int y1, int
b); Exactly the same as WaitForMouse, except that it can be used when
keyboard input may also be expected. If any normal keyboard key is pressed,
the function returns immediately without waiting any longer for a mouse
operation. To indicate that a key press was detected, the fifth parameter (b)
is set to zero instead of a valid button number. Nothing is read from the
keyboard; the standard read_... functions may be used to actually get the
input.
- WaitForMouseEventOrKeyPress(int x, int y, int
b); Almost the same as WaitForMouseOrKeyPress, except that it
does not wait for a complete click (mouse press followed by mouse release)
either event, press or release, is enough to satisfy this function. Hence
only one set of variables (x,y) wich receive the coordinates of the mouse
press/release. The third parameter again indicates which mouse button
was used, but is positive for a press, and negative for a release.
- StartMonitoringMouse(); If you want to be able to see
if the mouse has been clicked, but do not want the program to wait for such
an event (perhaps so that it can continue normal processing, but accept
mouse commands if they happen to be given), use this function together with
CheckMouseAction (below). The StartMonitoringMouse function
effectively turns the mouse on; any mouse actions before this function is called
are ignored. To clear any memory of old mouse clicks, simply call
StartMonitoringMouse again.
(example).
- int CheckMouseAction(void);. Used only in conjunction with
StartMonitoringMouse. Once mouse monitoring has been turned on,
the system will record the next mouse action (any proper click or drag within
the window). CheckMouseAction does not wait for a mouse action, it simply returns
1 if there has been an action and 0 if there has not.
(example).
- void GetMouseAction(int x0, int y0, int x1, int y1, int
b); (All parameters must be variables). Used only in conjunction with
StartMonitoringMouse. Once mouse monitoring has been turned on,
the system will record the next mouse action (any proper click or drag within
the window). GetMouseAction does not wait for a mouse action, it is normally
only used after CheckMouseAction has returned 1. Apart from not waiting for
mouse action to occur, this function is exactly the same as WaitForMouse (above).
If there has been no mouse action, the fifth parameter (b) is set to zero.
(example).
- void GetMouseEvent(int x, int y, int b);
A combination of WaitForMouseEventOrKeyPress and GetMouseAction. It delivers
the last mouse even (press or release) if there is one, but does not wait if
there is not. Also does not wait for a complete click: delivers presses and
releases of the mouse separately. b negative for release.
- Region GetDrag(void);
Waits for the user to select a rectangular region by dragging the pressed mouse
from top-left to bottom-right, then releasing the mouse. While the mouse is being
dragged, a white rectangle is shown around the area currently selected; this
rectangle disappears as soon as the mouse is released. The value returned is a
struct object with four int components: top, left, bottom, and right, giving
the pixel positions of the edges of the selected region.
Dialogues (temporary pop-up windows)
- InformationDialog(string message, string title); Makes a small message box
appear on the screen. The program does not continue until the user presses OK. message is the
message that appears inside the box. If the message should occupy more than one line of text,
the special character \n may be used. Title is optional; if supplied, it appears in the
title/drag bar of the dialog window.
- ErrorDialog(string message, string title); The same as InformationDialog
except that the dialogue window is less friendly-looking, and more visually suggestive of trouble.
- TerminalErrorDialog(string message, string title); The same as ErrorDialog
except that once the user clicks OK after seeing the error message, the program is terminated.
TerminalErrorDialog is a way to completely stop a program after giving the user an
unmissable message.
(example).
- int YesNoDialog(string message, string title); The same as InformationDialog
except that the window is suggestive of a question being asked, and has two buttons, one marked YES
and one marked NO. The result returned is 1 is the user clicks YES, or 0 for NO.
- string SaveAsFileDialog(suggestedname, directory, extension, title)
Starts up the standard dialog for selecting a file that is to be created/written. All parameters are
optional. The result returned is the empty string "" if the user selects CANCEL, otherwise the full
name (including path) of the selected file. suggestedname is the name that will be used
(no path should be provided) if the user just clicks OK without actively choosing a filename.
directory is the folder that the dialog starts in, but the user can navigate out of it;
if not provided, or "", the current working directory is used. extension is the extension
(e.g. "TXT", "DAT") that will be added to the end of the name the user type if the user does not
add an extension. title appears in the title/drag bar of the dialog window.
- string OpenFileDialog(suggestedname, directory, title) is the same as
SaveAsFileDialog except that it is intended to be used for selecting a file that
already exists.
(example).
- string GetWorkingDirectory() returns the full path and name of the
current working directory.
Menus
- AddMenuBar(); Adds an empty menu
bar to the graphics window. This function is not necessary,
as AddMenu() will automatically create the
menu bar if it doesn't already exist.
- AddMenu(string name); Adds a pull-down
menu to the menu bar. There are initially no selectable items
in this menu. This function is also not needed because the
AddMenuItem function automatically creates the
necessary menu if it isn't already there.
- int AddMenuItem(string menuname, string itemname);
For example, if you want to add an "Exit" item to the "File"
menu, which is the normal setup for windows programs, use
m=AddMenuItem("File","Exit"); The value returned
is the identification number for this menu item. When the
user clicks on this menu item, a MENU_SELECTED event
is sent, containing this identification number.
Rememeber to enable capturing of MENU_SELECTED events.
Support for .BMP files
- These functions should be able to read any .BMP (windows bitmap) files, but it is possible
that some new formats exist. Please report any failures. No other graphics file types (e.g. GIF, JPG)
are supported yet, but most drawing programs (e.h. Photoshop) make it easy to convert.
- ImageFromFile(filename) filename must be a string. Reads a graphical image from
a file, returns an object of type Image *, or NULL on failure. An
Image * object may be drawn in the grapics window using the DrawImage
functions.
(another example).
- DrawImage(Image *img, x, y) or DrawImage(Image *img)
Draws an image (as read by ImageFromFile) in the graphics window at position x,y. If
x and y are not given, the current pen position is used. Pen position, colour, and direction
are left unchanged.
- Example, draws a picture from a file 3 times:
Image *im=ImageFromFile("c:\\programs\\example36\\porkpie.bmp");
if (im==NULL)
{ print("Error reading graphics file: ");
print(GetReasonForFailure());
newline();
return; }
DrawImage(im, 100, 100);
DrawImage(im, 200, 100);
DrawImage(im, 300, 100);
- string GetReasonForFailure() If ImageFromFile fails for any reason, it returns NULL
as its result, and this function returns a string explaining what caused the failure.
- im->GetSize(w,h); w and h must be int variables. After successfully
reading an Image *im from a file, this function determines its size in pixels.
(example).
- SaveAsBMP(string filename) The entire contents of the graphics window is saved
as a "true-colour" .BMP file with the given name. Warning: BMP files can be big. Width w and Height h
pixels produces a file just over 3*w*h bytes.
- SaveAsBMP(string filename, int x, int y, int w, int h) Same as the one-argument
SaveAsBMP, except only the portion of the screen starting at co-ordinates (x,y) and with given width an
height are saved.
Consolidating Operations
- StartBatching(); Before each drawing
operation, the graphics system has to gain control of the
screen, and then release control immediately afterwards.
This is Always Automatic, you do not need
to use StartBathcing() ever. However, if you are performing
a reasonably large number of tiny operations all at once
(perhaps drawing a whole row of an image one pixel at a time)
the time taken to gain control before each single operation
can slow things down noticably. Under these circumstances,
and no others, StartBatching() gains control of the
whole screen and keeps it. Any normal drawing operations
subsequently performed don't have to bother. After performing
a reasonable number of operations, StopBatching() must
be used to release control. Until control is released,
none of the automatic refresh operations that are absolutely
necessary for maintaining the correct appearance of the screen
will be performed. Control must not be kept for a long
perios, not even a large fraction of a second.
- StopBatching(); Reverses the effect
of StartBatching().
- int IsBatching() returns 1 is
batching is on (StartBatching has been called, but
StopBatching hasn't yet), or 0 otherwise.
Threads
- A Thread is a separate stream of execution within a program. It is actually a perfectly
normal function, except that (once started) the thread and the main program both run at
the same time (unlike non-thread function, which stops the main program from running until
it is finished). There may be a large number of threads all running at the same time. Threads
are useful for background or monitoring tasks, such as listening for mouse activity while
the main program continues with its normal tasks.
- Thread name(function); creates (but does not start the execution of)
a new thread. The thread is represented by a new C++ variable called name, and the function
provided as a parameter is what the thread will do once it is started. The function should
return no result (void) and take either no parameters or a single int parameter.
- name.Start(); If "name" is the variable representing a thread, as
described above, this starts execution of that thread. This form should be used when the
thread function takes no parameters.
- name.Start(int x); If "name" is the variable representing a thread, as
described above, this starts execution of that thread. This form should be used when the
thread function takes one int parameter; the value of x is passed to the thread function
when it is started.
- Example of threads being used:
void background(int init)
{ for (int val=init; val<init+10; val+=1)
{ Delay(random_in_range(0.1, 2.0));
printf("%d ", val); }
printf("done "); }
void main(void)
{ Thread one(background);
Thread two(background);
printf("go! ");
one.Start(10);
two.Start(20);
Delay(10.0);
printf("end "); }
- Explanation of example: Note that a normal call to the function background(100) would
print out the number 100, 101, 102, 103, ..., 109 then "done", but with a randomly
selected delay of between 0.1 and 2 seconds before each number is printed. If background(10)
and background(20) were both running at the same time, we would see the numbers 10, 11, 12, ..., 19, "done"
and the numbers 20, 21, 22, ..., 29, "done" all printed out, but randomly interleaved.
That is exactly what this program prints, plus the word "go!" before any numbers appear, and the
word "end" appears after 10 seconds of printing. This is what the program produced when I just
ran it: "go! 2010 21 22 11 23 12 24 13 25 14 15 26 27 28 16 29 done 17 end 18 19 done", but
the output could be different for each run.
Semaphores
Example 1
This program draws a simple square on the screen using
calculated coordinates for the corners. void main(void)
{ MakeWindow(400,400);
MoveTo(100,100);
DrawLineTo(300,100);
DrawLineTo(300,300);
DrawLineTo(100,300);
DrawLineTo(100,100); }
Example 2
This program draws a simple square on the screen by drawing a
straight line, turning right through 90 degrees, and repeating four times. void main(void)
{ MakeWindow(400,400);
DrawLineLength(100);
TurnRightByDegrees(90);
DrawLineLength(100);
TurnRightByDegrees(90);
DrawLineLength(100);
TurnRightByDegrees(90);
DrawLineLength(100);
TurnRightByDegrees(90); }
Example 3
This program draws a simple square on the screen by turning
towards each of the four cardinal directions in turn, and drawing a straight
line. void main(void)
{ MakeWindow(400,400);
MoveTo(50,50);
TurnToHeadingDegrees(90);
DrawLineLength(200);
TurnToHeadingDegrees(180);
DrawLineLength(200);
TurnToHeadingDegrees(270);
DrawLineLength(200);
TurnToHeadingDegrees(0);
DrawLineLength(200); }
Example 4
This program draws a smooth parabola out of the word "Bah!" by
varying x from 0 to the width of the window, calculating y as a quadratic
function of x, and writing "Bah!" at position (x,y). void main(void)
{ MakeWindow(430,400);
for (int x=0; x<=400; x+=5)
{ int y=(x-200)*(x-200)/100;
MoveTo(x,y);
WriteText("Bah!"); } }
Example 5
This program follows the form of example 1, but draws a normal
thin-sided square with a fat-sided square inside it. void main(void)
{ MakeWindow(400,400);
MoveTo(100,100);
DrawLineTo(300,100);
DrawLineTo(300,300);
DrawLineTo(100,300);
DrawLineTo(100,100);
PenWidth(4);
MoveTo(150,150);
DrawLineTo(250,150);
DrawLineTo(250,250);
DrawLineTo(150,250);
DrawLineTo(150,150); }
Example 6
This program follows the form of example 2, but draws a
multi-coloured hexagon with the aid of PenColor. void main(void)
{ MakeWindow(400,400);
MoveTo(200,100);
PenWidth(6);
TurnToHeadingDegrees(120);
PenColor(1.0, 0.0, 0.0); // red
DrawLineLength(70);
TurnRightByDegrees(60);
PenColor(1.0, 1.0, 0.0); // yellow
DrawLineLength(70);
TurnRightByDegrees(60);
PenColor(0.0, 1.0, 1.0); // prussian blue
DrawLineLength(70);
TurnRightByDegrees(60);
PenColor(1.0, 0.5, 0.0); // orange
DrawLineLength(70);
TurnRightByDegrees(60);
PenColor(1.0, 0.8, 0.8); // pink
DrawLineLength(70);
TurnRightByDegrees(60);
PenColor(0.7, 0.7, 0.7); // gray
DrawLineLength(70); }
Example 7
This program is the same as example 6, but uses the
integer-based colour descriptions instead. void main(void)
{ MakeWindow(400,400);
MoveTo(200,100);
PenWidth(6);
TurnToHeadingDegrees(120);
PenColor0255(255, 0, 0); // red
DrawLineLength(70);
TurnRightByDegrees(60);
PenColor0255(255, 255, 0); // yellow
DrawLineLength(70);
TurnRightByDegrees(60);
PenColor0255(0, 255, 255); // prussian blue
DrawLineLength(70);
TurnRightByDegrees(60);
PenColor0255(255, 127, 0); // orange
DrawLineLength(70);
TurnRightByDegrees(60);
PenColor0255(255, 200, 200); // pink
DrawLineLength(70);
TurnRightByDegrees(60);
PenColor0255(170, 170, 170); // gray
DrawLineLength(70); }
Example 8
This program draws four big dots at the vertices of a square. void main(void)
{ MakeWindow(400,400);
MoveTo(200,100);
PenWidth(10);
DrawPointAt(100,100);
DrawPointAt(300,100);
DrawPointAt(100,300);
DrawPointAt(300,300); }
Example 9
This program uses HLStoRGB to generate a rainbow. By varying
Hue continuously from 0 to 1, while keeping Lightness at 0.5 and Saturation at
1.0, it goes through all the colours of the virtual rainbow, keeping constant
brightness. void main(void)
{ MakeWindow(800,200);
for (int i=0; i<600; i+=1)
{ double R, G, B;
HLStoRGB(i/600.0, 0.5, 1.0, R, G, B);
PenColor(R, G, B);
MoveTo(100+i, 50);
DrawLineTo(100+i, 150); } }
Example 10
This program draws blobs of random size at random points in
the window; the colours are of random shades of blue to purple. It never
terminates naturally, so use control-C on it. void main(void)
{ MakeWindow(500,500);
while (1)
{ int red=random_in_range(0,255), green=0, blue=255;
int size=random_in_range(5,100);
PenWidthColor0255(size, red, green, blue);
int x=random_in_range(0,500);
int y=random_in_range(0,500);
DrawPointAt(x,y);
Pause(0.05); } }
Example 11
This program repeatedly waits for the user to drag the mouse
(i.e. press the mouse, move it while pressed, then release the mouse in a new
position), when it draws a rectangle connecting the begin and end points of the
mouse drag.
The program has no natural end, so will need a control-C to
stop it. Mouse drags should be entirely within the graphics window to work
properly. void main(void)
{ MakeWindow(500,500);
while (1)
{ int x0, y0, x1, y1, b;
WaitForMouse(x0, y0, x1, y1, b);
MoveTo(x0, y0);
DrawLineTo(x0, y1);
DrawLineTo(x1, y1);
DrawLineTo(x1, y0);
DrawLineTo(x0, y0); } }
Example 12
This program slowly draws a line in a fixed direction.
At any time, the user may type one of the words "red", "green", or "blue",
in which case the pen will change colour, or "stop". Additionally, the
user may click the mouse anywhere within the window, in which case
the pen will change direction and start moving towards the mouse click
position.void main(void)
{ MakeWindow(500,500);
StartMonitoringMouse();
while (1)
{ DrawLineLength(2);
Pause(0.1);
int inputrdy = CheckInputReady();
int mouserdy = CheckMouseAction();
if (inputrdy)
{ string command=read_string();
if (command=="red")
PenColor0255(255, 0, 0);
else if (command=="green")
PenColor0255(0, 180, 0);
else if (command=="blue")
PenColor(0, 0, 255);
else if (command=="stop")
break;
else
{ print("Bad command '"); print(command); print("'"); newline(); } }
if (mouserdy)
{ int x0, y0, x1, y1, b;
GetMouseAction(x0, y0, x1, y1, b);
double dir=DirectionTo(x1, y1);
TurnToHeading(dir); } } }
Example 13
This program uses a dialog to select a .BMP (windows
bitmap) graphic file, then displays the graphic from that file in a
sutiably sized window.
void main(void)
{ string fname=OpenFileDialog("*.bmp", GetWorkingDirectory(), "Select a BMP");
if (fname=="") return;
Image *im=ImageFromFile(fname);
if (im==NULL)
TerminalErrorDialog("Can't read selected file");
int w, h;
im->GetSize(w,h);
MakeWindow(w+10, h+10);
DrawImage(im, 5, 5); }