4 This is ncurses (terminal) implementation of the game front end. This isn't
5 a full fledged version but rather a "show off" of what can be done with the
6 game; especially the limited ability of ncurses to handle input makes this
7 version very hard to play.
9 by Miloslav Ciz (drummyfish), 2024
11 Released under CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/)
12 plus a waiver of all other intellectual property. The goal of this work is to
13 be and remain completely in the public domain forever, available for any use
22 #define SFG_SCREEN_RESOLUTION_X 120
23 #define SFG_SCREEN_RESOLUTION_Y 40
28 uint8_t ncScreen
[SFG_SCREEN_RESOLUTION_X
* SFG_SCREEN_RESOLUTION_Y
];
29 uint8_t ncButtonStates
[SFG_KEY_COUNT
];
32 const char asciiPalette
[] =
39 uint32_t currentTime()
42 timespec_get(&t
,TIME_UTC
);
43 return 1000 * ((int64_t) t
.tv_sec
) + ((int64_t) t
.tv_nsec
) / 1000000;
46 int8_t SFG_keyPressed(uint8_t key
)
48 return ncButtonStates
[key
];
51 void SFG_getMouseOffset(int16_t *x
, int16_t *y
)
56 uint32_t SFG_getTimeMs()
58 return currentTime() - timeStart
;
61 void SFG_sleepMs(uint16_t timeMs
)
63 usleep(1000 * timeMs
);
66 void SFG_setPixel(uint16_t x
, uint16_t y
, uint8_t colorIndex
)
68 ncScreen
[y
* SFG_SCREEN_RESOLUTION_X
+ x
] = asciiPalette
[colorIndex
% 16];
71 void SFG_playSound(uint8_t soundIndex
, uint8_t volume
)
75 void SFG_setMusic(uint8_t value
)
79 void SFG_processEvent(uint8_t event
, uint8_t data
)
83 void SFG_save(uint8_t data
[SFG_SAVE_SIZE
])
87 uint8_t SFG_load(uint8_t data
[SFG_SAVE_SIZE
])
94 timeStart
= currentTime();
111 const uint8_t *scr
= ncScreen
;
113 for (int y
= 0; y
< SFG_SCREEN_RESOLUTION_Y
; ++y
)
117 for (int x
= 0; x
< SFG_SCREEN_RESOLUTION_X
; ++x
)
126 goOn
= SFG_mainLoopBody();
128 for (int i
= 0; i
< SFG_KEY_COUNT
; ++i
)
129 ncButtonStates
[i
] = 0;
140 case KEY_UP
: ncButtonStates
[SFG_KEY_UP
] = 1; break;
141 case KEY_LEFT
: ncButtonStates
[SFG_KEY_LEFT
] = 1; break;
142 case KEY_RIGHT
: ncButtonStates
[SFG_KEY_RIGHT
] = 1; break;
143 case KEY_DOWN
: ncButtonStates
[SFG_KEY_DOWN
] = 1; break;
145 case KEY_ENTER
: ncButtonStates
[SFG_KEY_A
] = 1; break;
148 case 's': ncButtonStates
[SFG_KEY_B
] = 1; break;
149 case 'd': ncButtonStates
[SFG_KEY_C
] = 1; break;
150 case ' ': ncButtonStates
[SFG_KEY_JUMP
] = 1; break;
151 case 'q': ncButtonStates
[SFG_KEY_MENU
] = 1; break;
152 case 'f': ncButtonStates
[SFG_KEY_NEXT_WEAPON
] = 1; break;
153 case 'g': ncButtonStates
[SFG_KEY_PREVIOUS_WEAPON
] = 1; break;
154 case 'n': ncButtonStates
[SFG_KEY_STRAFE_LEFT
] = 1; break;
155 case 'm': ncButtonStates
[SFG_KEY_STRAFE_RIGHT
] = 1; break;