12 KiB
gint
: Wrapper for the gint library
PythonExtra is developed with the fxSDK and uses the gint kernel as a runtime. The Python module gint
provides access to gint's internal functions for rendering, keyboard, and more. Since gint has many versatile functions with good performance, it is beneficial to use it instead of e.g. casioplot
or turtle
.
The gint
module tries to match its API with the original API of the C library, which is why few functions use keyword arguments or overloading. There are a few differences documented at the end of this document. For details not described in this document, one can refer to gint's header files which are always applicable unless this document explicitly says otherwise.
All constants, functions, etc. discussed here are in the gint
module.
import gint
# or:
from gint import *
Keyboard input
Reference headers: <gint/keyboard.h>
and <gint/keycodes.h>
.
The module provides integer constants to refer to keyboard keys, with the following names:
KEY_F1 |
KEY_F2 |
KEY_F3 |
KEY_F4 |
KEY_F5 |
KEY_F6 |
KEY_SHIFT |
KEY_OPTN |
KEY_VARS |
KEY_MENU |
KEY_LEFT |
KEY_UP |
KEY_ALPHA |
KEY_SQUARE |
KEY_POWER |
KEY_EXIT |
KEY_DOWN |
KEY_RIGHT |
KEY_XOT |
KEY_LOG |
KEY_LN |
KEY_SIN |
KEY_COS |
KEY_TAN |
KEY_FRAC |
KEY_FD |
KEY_LEFTP |
KEY_RIGHTP |
KEY_COMMA |
KEY_ARROW |
KEY_7 |
KEY_8 |
KEY_9 |
KEY_DEL |
KEY_ACON |
|
KEY_4 |
KEY_5 |
KEY_6 |
KEY_MUL |
KEY_DIV |
|
KEY_1 |
KEY_2 |
KEY_3 |
KEY_ADD |
KEY_SUB |
|
KEY_0 |
KEY_DOT |
KEY_EXP |
KEY_NEG |
KEY_EXE |
Keyboard events
key_event:
.time -> int
.mod -> bool
.shift -> bool
.alpha -> bool
.type -> KEYEV_NONE | KEYEV_DOWN | KEYEV_UP | KEYEV_HOLD
.key -> KEY_*
gint communicates information about keyboard activity through events. Events indicate when a key (.key
field) is pressed, repeated or released (.type
field equal to KEYEV_DOWN
, KEYEV_HOLD
and KEYEV_UP
respectively), when (.time
field), and whether modifiers (SHIFT, .shift
field, and ALPHA, .alpha
field) where active at that time.
(The .mod
field isn't very interesting, and the KEYEV_NONE
value for the .type
field is discussed later with pollevent()
.)
The functions getkey()
, getkey_opt()
, pollevent()
and waitevent()
all return events.
Waiting for a key press
getkey() -> key_event
The function getkey()
pauses the program until a key is pressed or repeated, and returns the associated event (which is always of type KEYEV_DOWN
or KEYEV_HOLD
). By default, only arrow keys are repeated, once after 400 ms, then every 40 ms.
A few things can happen while getkey()
is waiting. The user can press SHIFT or ALPHA which will trigger modifiers and affect the .shift
and .alpha
fields of the returned event. The user can also go to the main menu by pressing MENU or turn the calculator off with SHIFT+AC/ON.
Example. In a selection menu with N possible items, one could navigate with the up and down arrow keys, jump to the top or bottom with SHIFT up and SHIFT down, and validate with EXE.
ev = getkey()
if ev.key == KEY_EXE:
pass # Validate
elif ev.key == KEY_UP and ev.shift:
pos = 0 # Jump to top
elif ev.key == KEY_DOWN and ev.shift:
pos = N-1 # Jump to bottom
elif ev.key == KEY_UP and pos > 0:
pos -= 1 # Move one place up
elif ev.key == KEY_DOWN and pos < N-1:
pos += 1 # Move one place down
TODO: Mention getkey_opt()
Reading keyboard events in real time
pollevent() -> key_event
waitevent() -> key_event
clearevents() -> None
gint records keyboard activity in the background while the program is running. Events are placed in a queue until the program reads them. This is how getkey()
learns about keyboard activity, for example.
The pollevent()
function provides direct access to events. pollevent()
returns the oldest event that hasn't yet been read by the program. If there are no events waiting to be read, pollevent()
returns a "fake" event with type KEYEV_NONE
to indicate that the queue is empty.
Since pollevent()
returns instantly, it can be used to read keyboard activity without pausing the program.
Example. A game loop could, at every frame, read all pending events to determine when the player pressed the SHIFT key (in this example the "action" key) to perform an action.
# Render game...
while True:
ev = pollevent()
if ev.type == KEYEV_NONE:
break # We're done reading events
if ev.type == KEYEV_DOWN and ev.key == KEY_SHIFT:
pass # The SHIFT key was just pressed!
# Implicitly ignores other keys
# Simulate game...
The waitevent()
function operates similarly, but if there are no pending events it waits for something to happen before returning. It is used quite rarely because in waiting situations one usually uses getkey()
instead.
The function clearevents()
reads and ignores all events, i.e. it "throws away" all the information about recent keyboard activity. It is useful to know the immediate state of the keyboard with keydown()'
(see below). clearevents()
is equivalent to the following definition:
def clearevents():
ev = pollevent()
while ev.type != KEYEV_NONE:
ev = pollevent()
Reading the immediate state of the keyboard
keydown(key: int) -> bool
keydown_all(*keys: [int]) -> bool
keydown_any(*keys: [int]) -> bool
After events have been read and the event queue is empty, one can query the immediate state of keys with the keydown()
function. keydown(k)
returns True
if key k
is currently pressed, False
otherwise. This function only works after events have been read, which is usually done either with pollevent()
or with clearevents()
.
Example. A game loop could check the state of the left/right keys at every frame to move the player.
while True:
ev = pollevent()
# ... same thing as the pollevent() example
if keydown(KEY_LEFT):
player_x -= 1
if keydown(KEY_RIGHT):
player_x += 1
keydown_all()
takes a series of keys as parameters and returns True
if they are all pressed. keydown_any()
is similar and returns True
if at least one of the listed keys is pressed.
Quickly querying key state changes
cleareventflips() -> None
keypressed(key: int) -> bool
keyreleased(key: int) -> bool
keydown()
only tells whether keys are pressed at a given time; it cannot be used to check when keys change from the released state to the pressed state or the other way around. To do this, one must either read individual events (which can be annoying) or use the functions described below.
keypressed(k)
and keyreleased(k)
indicate whether key k
was pressed/released since the last call to cleareventflips()
. Be careful, here "pressed/released" should be interpreted as "indicated pressed/released by events read" not as a real-time state change.
Example. A game loop could test both the immediate state of some keys and state changes forother keys by using immediate functions after cleareventflips()
followed by clearevents()
.
# Render game...
cleareventflips()
clearevents()
if keypressed(KEY_SHIFT):
pass # Action !
if keydown(KEY_LEFT):
player_x -= 1
if keydown(KEY_RIGHT):
player_x += 1
# Simulate game...
Miscellaneous keyboard functions
keycode_function(key: int) -> int
keycode_digit(key: int) -> int
keycode_function(k)
returns the F-key number if k
(i.e. 1 for KEY_F1
, 2 for KEY_F2
, etc.) and -1 for other keys.
keycode_digit(k)
returns the digit associated with k
(i.e. 0 for KEY_0
, 1 for KEY_1
, etc.) and -1 for other keys.
Drawing and rendering
Reference headers: <gint/display.h>
, and for some details <gint/display-fx.h>
and <gint/display-cg.h>
.
Color manipulation
C_WHITE: int # White
C_BLACK: int # Black
C_LIGHT: int # Light gray (on B&W: gray engine)
C_DARK: int # Dark gray (on B&W: gray engine)
C_NONE: int # Transparent
C_INVERT: int # Function: inverse
# Black-and-white (B&W) models only:
C_LIGHTEN: int # Function: lighten (gray engine)
C_DARKEN: int # Function: darken (gray engine)
# fx-CG models only:
C_RED: int # Pure red
C_GREEN: int # Pure green
C_BLUE: int # Pure blue
C_RGB(r: int, g: int, b: int) -> int
Colors are all integers (manipulating (r,g,b)
tuples is excruciatingly slow and requires memory allocations all over the place). A few default colors are provided.
On the fx-CG series, the C_RGB()
function can be used to create colors from three components ranging from 0 to 31.
TODO: Explain the gray engine.
Basic rendering functions
DWIDTH: int
DHEIGHT: int
dupdate() -> None
dclear(color: int) -> None
dpixel(x: int, y: int, color: int) -> None
dgetpixel(x: int, y: int) -> int
The integers DWIDTH
and DHEIGHT
indicate the screen's dimensions. The screen is 128x64 on black-and-white models (like the G-III) and 396x224 on the fx-CG series (the full screen is available).
All rendering functions draw to an internal image called the "VRAM"; rendering calls are thus not immediate visible on the screen. For the result to be visible one must call the dupdate()
function, which transfers the contents of the VRAM to the real display. Usually, this is done after rendering everything we need on one frame instead of after each drawing function call.
In PythonExtra, dupdate()
also indicates a "switch to graphics mode". Due to certain optimizations any call to print()
is considered a "switch to text mode", and while in text mode the shell might redraw at any time. In order to draw after using text mode, one must call dupdate()
to force a switch to graphics mode before starting rendering. Otherwise the shell and program might render at the same time and produce incoherent results.
dclear()
fills the screen with a uniform color.
dpixel()
changes a pixel's color. Coordinates are universally (x,y) where x
is in the range 0 to DWIDTH-1 inclusive (0 being left) and y
is in the range 0 to DHEIGHT-1 inclusive (0 being top).
dgetpixel()
returns the color of a pixel. Note that dgetpixel()
reads from VRAM, not from the display.
Geometric shape rendering functions
TODO
Image rendering functions
TODO
Differences with gint's C API
dsubimage()
doesn't have its final parameterint flags
. The flags are only minor optimizations and could be removed in future gint versions.- Image constructors
image()
andimage_<format>()
don't exist in the C API. - Asynchronous volatile-flag-based timeouts are replaced with synchronous millisecond delays (integer value or
None
).
TODO: There are more.