Words and fonts
A game talks: a score in the corner, a name over a door, a friend with
something to tell you. You’ve met PRINT and LOCATE already. This lesson is
about making words look the way you want and putting them exactly where you
want them.
A font of your own
My own letters are chunky and plain. LOADFONT loads a TrueType or OpenType
font from the game’s folder under a name, and SETFONT says how big to write
and in which font. FONT RESET goes back to mine.
SCREEN 320, 240
LOADFONT "font.ttf", "story"
SETFONT 24, "story"
PRINT "Once upon a time"
SETFONT 12
PRINT "...in a city far, far away"
FONT RESET
PRINT "back to my letters"
Once upon a time
...in a city far, far away
back to my letters
SETFONT without a font name changes only the size, so the second line is
still in "story", just smaller.
Exactly where
LOCATE counts rows and columns, which is lovely for lining things up but
coarse when you want a word at a particular pixel. !! origin gives the
pixel the rows and columns count from: LOCATE 1, 1 !! origin((200, 8)) puts
the cursor at x 200, y 8.
COLOR sets the color of the words, and PRINT !! same_line leaves the
cursor at the end of what it printed, so the next PRINT carries on along the
same line. Together, they make a score with a label in one color and the
number in another:
SCREEN 320, 240
score = 0
lives = 3
DO
IF COOLDOWN(1)
score = score + 7
FRAME
CLS
LOCATE 1, 1 !! origin((8, 8))
COLOR 14
PRINT "SCORE " !! same_line
COLOR 15
PRINT score
LOCATE 1, 1 !! origin((240, 8))
COLOR 12
PRINT "LIVES " !! same_line
COLOR 15
PRINT lives
END FRAME
END IF
LOOP
Crash-tan’s Tip:
COLOR 15, 1gives the words a blue background as well, which keeps them easy to read over a busy picture.
Somebody talking
Two more of PRINT’s modifiers are for conversations. words wraps a long
line at the edge of the screen between words, never in the middle of one.
rate types it out a letter at a time, this many milliseconds apart, the way
role-playing games always have.
PRINT doesn’t wait for the typing to finish, so your game carries on while
it goes. typing is TRUE until the last letter is out. Here the hero bobs up
and down while I talk, and stops when I’m done:
SCREEN 320, 240
LOADIMG "hero.png", "tan"
MEMORYBUFFER "box"
LINE (0, 172) -> (319, 239), 1 !! box fill
LINE (0, 172) -> (319, 239), 15 !! box
END MEMORYBUFFER
PUTIMAGE (0, 0), "box"
ENABLE SPRITE 0
SET SPRITE 0 !! image("tan") x(240) y(132)
SHOW SPRITE 0
COLOR 15, 1
LOCATE 1, 1 !! origin((8, 180))
PRINT "Hi! I'm Crash-tan, and this is my city. Mind the explosions: they're mostly harmless." !! rate(40) words
bob = 0
DO WHILE typing
IF COOLDOWN(5)
bob = 1 - bob
SET SPRITE 0 !! y(132 - bob * 3)
END IF
LOOP
SET SPRITE 0 !! y(132)
LOCATE 1, 1 !! origin((200, 224))
PRINT "press a key"
PAUSE
Try a rate of 10 for somebody in a hurry, or 120 for somebody very, very
sleepy.
Words you can move
Printed words stay where they’re printed. TEXTTOIMAGE writes words into a
picture instead: the text, a name for the picture, and if you like, a size and
a font. A picture can be stamped with PUTIMAGE, scaled, spun, or shown by a
sprite, so here’s a title that drops in and then floats:
SCREEN 320, 240
LOADFONT "font.ttf", "story"
LOADIMG "city.png", "city"
PUTIMAGE (0, 0), "city" !! scale_to((320, 240))
TEXTTOIMAGE "CRASH CITY", "title", 32, "story"
ENABLE SPRITE 0
SET SPRITE 0 !! image("title") x(160) y(-20) origin((0.5, 0.5))
SHOW SPRITE 0
y = -20
t = 0
DO
IF COOLDOWN(1)
IF y < 90 THEN y = y + 3
t = t + 1
SET SPRITE 0 !! y(y + sin(t / 15) * 4)
END IF
LOOP
The words are a sprite now, so I draw them every frame without any PRINT
at all.
A screen of letters
Some games are nothing but letters: a text adventure, a roguelike, a
terminal in a spaceship. SCREEN TEXT opens a screen measured in
characters, columns across and rows down, in place of pixels.
SCREEN TEXT 40, 25
COLOR 14
LOCATE 2, 14
PRINT "THE DARK CAVE"
COLOR 7
LOCATE 5, 3
PRINT "You are standing at the mouth of a cave."
LOCATE 6, 3
PRINT "A cold wind blows from inside."
COLOR 10
LOCATE 9, 3
PRINT "> go north"
THE DARK CAVE
You are standing at the mouth of a cave.
A cold wind blows from inside.
> go north
!! modern swaps my plain ASCII letters for my modern character set.
A pointer of your own
SET CURSOR turns any picture into the mouse pointer, and !! hotspot says
which of its pixels is the tip. SET CURSOR !! off brings the ordinary
pointer back.
SCREEN 320, 240
MEMORYBUFFER "arrow", 12, 12
POLYGON [(0, 0), (11, 5), (5, 6), (4, 11)], 15, 14
END MEMORYBUFFER
SET CURSOR "arrow" !! hotspot((0, 0))
PRINT "Move the mouse over the screen, then press a key."
PAUSE
SET CURSOR !! off
The arrow’s tip is its top-left pixel, (0, 0), so that’s the pixel the
pointer is pointing at.