Add terminal frontend

This commit is contained in:
Miloslav Číž 2020-09-29 19:22:39 +02:00
parent 535155a60d
commit ffe5dda22e
5 changed files with 223 additions and 20 deletions

View File

@ -210,13 +210,6 @@
*/ */
#define SFG_BASE_SPRITE_SIZE RCL_UNITS_PER_SQUARE #define SFG_BASE_SPRITE_SIZE RCL_UNITS_PER_SQUARE
/**
Says whether the game is running in very low resolution, which triggers some
simple rendering so that things fit the screen.
*/
#define SFG_VERY_LOW_RESOLUTION\
((SFG_GAME_RESOLUTION_X < 90) || (SFG_GAME_RESOLUTION_Y < 70))
// ---------------------------- // ----------------------------
// derived constants // derived constants
@ -263,8 +256,13 @@
#define SFG_WEAPON_IMAGE_POSITION_X \ #define SFG_WEAPON_IMAGE_POSITION_X \
(SFG_GAME_RESOLUTION_X / 2 - (SFG_WEAPON_IMAGE_SCALE * SFG_TEXTURE_SIZE) / 2) (SFG_GAME_RESOLUTION_X / 2 - (SFG_WEAPON_IMAGE_SCALE * SFG_TEXTURE_SIZE) / 2)
#define SFG_WEAPON_IMAGE_POSITION_Y \ #if SFG_GAME_RESOLUTION_Y > 50
(SFG_GAME_RESOLUTION_Y - (SFG_WEAPON_IMAGE_SCALE * SFG_TEXTURE_SIZE)) #define SFG_WEAPON_IMAGE_POSITION_Y \
(SFG_GAME_RESOLUTION_Y - (SFG_WEAPON_IMAGE_SCALE * SFG_TEXTURE_SIZE))
#else
#define SFG_WEAPON_IMAGE_POSITION_Y \
(SFG_GAME_RESOLUTION_Y - SFG_TEXTURE_SIZE / 2)
#endif
#define SFG_PLAYER_TURN_UNITS_PER_FRAME \ #define SFG_PLAYER_TURN_UNITS_PER_FRAME \
((SFG_PLAYER_TURN_SPEED * RCL_UNITS_PER_SQUARE) / (360 * SFG_FPS)) ((SFG_PLAYER_TURN_SPEED * RCL_UNITS_PER_SQUARE) / (360 * SFG_FPS))
@ -378,8 +376,8 @@
#define SFG_MAP_PIXEL_SIZE (SFG_GAME_RESOLUTION_Y / SFG_MAP_SIZE) #define SFG_MAP_PIXEL_SIZE (SFG_GAME_RESOLUTION_Y / SFG_MAP_SIZE)
#if SFG_MAP_PIXEL_SIZE == 0 #if SFG_MAP_PIXEL_SIZE == 0
#undef SFG_PIXEL_SIZE #undef SFG_MAP_PIXEL_SIZE
#define SFG_PIXEL_SIZE 1 #define SFG_MAP_PIXEL_SIZE 1
#endif #endif
#define SFG_AI_UPDATE_FRAME_INTERVAL \ #define SFG_AI_UPDATE_FRAME_INTERVAL \

12
game.h
View File

@ -3909,7 +3909,7 @@ static inline void SFG_clearScreen(uint8_t color)
void SFG_drawMap() void SFG_drawMap()
{ {
SFG_clearScreen(0); SFG_clearScreen(0);
uint16_t maxJ = uint16_t maxJ =
(SFG_MAP_PIXEL_SIZE * SFG_MAP_SIZE) < SFG_GAME_RESOLUTION_Y ? (SFG_MAP_PIXEL_SIZE * SFG_MAP_SIZE) < SFG_GAME_RESOLUTION_Y ?
(SFG_MAP_SIZE) : (SFG_GAME_RESOLUTION_Y / SFG_MAP_PIXEL_SIZE); (SFG_MAP_SIZE) : (SFG_GAME_RESOLUTION_Y / SFG_MAP_PIXEL_SIZE);
@ -4215,7 +4215,11 @@ void SFG_drawMenu()
SFG_GAME_RESOLUTION_X / 2 - 16 * SFG_FONT_SIZE_MEDIUM,y, SFG_GAME_RESOLUTION_X / 2 - 16 * SFG_FONT_SIZE_MEDIUM,y,
SFG_FONT_SIZE_MEDIUM); SFG_FONT_SIZE_MEDIUM);
#if SFG_GAME_RESOLUTION_Y > 50
y += 32 * SFG_FONT_SIZE_MEDIUM + SFG_characterSize(SFG_FONT_SIZE_MEDIUM); y += 32 * SFG_FONT_SIZE_MEDIUM + SFG_characterSize(SFG_FONT_SIZE_MEDIUM);
#else
y = 2;
#endif
uint8_t i = 0; uint8_t i = 0;
@ -4226,8 +4230,10 @@ void SFG_drawMenu()
if (item == SFG_MENU_ITEM_NONE) if (item == SFG_MENU_ITEM_NONE)
break; break;
#if SFG_VERY_LOW_RESOLUTION # if SFG_GAME_RESOLUTION_Y < 70
if (i != SFG_game.selectedMenuItem) // only display selected item // with low resolution only display the selected item
if (i != SFG_game.selectedMenuItem)
{ {
i++; i++;
continue; continue;

View File

@ -12,10 +12,14 @@
whatsoever. whatsoever.
*/ */
// #define SFG_START_LEVEL 8 // #define SFG_START_LEVEL 8
#include <stdio.h>
#define SFG_LOG(s) puts(s);
// #define SFG_UNLOCK_DOOR 1
// #define SFG_INFINITE_AMMO 1
#define SFG_FPS 25 #define SFG_FPS 25
#define SFG_CAN_EXIT 0 #define SFG_CAN_EXIT 0
//#define SFG_TEXTURE_DISTANCE 6000 //#define SFG_TEXTURE_DISTANCE 6000
@ -23,6 +27,7 @@
#define SFG_SCREEN_RESOLUTION_Y 88 #define SFG_SCREEN_RESOLUTION_Y 88
#define SFG_RESOLUTION_SCALEDOWN 1 #define SFG_RESOLUTION_SCALEDOWN 1
#define SFG_DITHERED_SHADOW 0 #define SFG_DITHERED_SHADOW 0
#define SFG_DIMINISH_SPRITES 0
#define SFG_FOG_DIMINISH_STEP 2048 #define SFG_FOG_DIMINISH_STEP 2048
#define SFG_RAYCASTING_MAX_STEPS 20 #define SFG_RAYCASTING_MAX_STEPS 20
#define SFG_RAYCASTING_MAX_HITS 5 #define SFG_RAYCASTING_MAX_HITS 5
@ -162,8 +167,8 @@ void SFG_playSound(uint8_t soundIndex, uint8_t volume)
for (int i = 0; i < SFG_SFX_SAMPLE_COUNT; ++i) for (int i = 0; i < SFG_SFX_SAMPLE_COUNT; ++i)
{ {
audioBuff[pos] = mixSamples(audioBuff[pos],SFG_GET_SFX_SAMPLE(soundIndex,i) audioBuff[pos] = mixSamples(audioBuff[pos],baseLevel +
>> volumeShift); (SFG_GET_SFX_SAMPLE(soundIndex,i) >> volumeShift));
pos = (pos < SFG_SFX_SAMPLE_COUNT - 1) ? (pos + 1) : 0; pos = (pos < SFG_SFX_SAMPLE_COUNT - 1) ? (pos + 1) : 0;
} }

View File

@ -27,12 +27,15 @@
#define SFG_LOG(str) puts(str); #define SFG_LOG(str) puts(str);
// #define SFG_START_LEVEL 6 #define SFG_START_LEVEL 1
// #define SFG_IMMORTAL 1 // #define SFG_IMMORTAL 1
#define SFG_UNLOCK_DOOR 1 #define SFG_UNLOCK_DOOR 1
// #define SFG_REVEAL_MAP 1 #define SFG_REVEAL_MAP 1
// #define SFG_INFINITE_AMMO 1 // #define SFG_INFINITE_AMMO 1
#define SFG_SCREEN_RESOLUTION_X 127
#define SFG_SCREEN_RESOLUTION_Y 42
// #define SFG_SCREEN_RESOLUTION_X 80 // #define SFG_SCREEN_RESOLUTION_X 80
// #define SFG_SCREEN_RESOLUTION_Y 64 // #define SFG_SCREEN_RESOLUTION_Y 64

191
main_terminal.c Normal file
View File

@ -0,0 +1,191 @@
/**
@file main_pokitto.cpp
This is Linux terminal implementation of the game front end. This needs root
priviledges (sudo) to work! This frontend is more of an experiment, don't
expect it to work perfectly and everywhere.
by Miloslav Ciz (drummyfish), 2019
Released under CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/)
plus a waiver of all other intellectual property. The goal of this work is
be and remain completely in the public domain forever, available for any use
whatsoever.
*/
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#define SFG_SCREEN_RESOLUTION_X 95
#define SFG_SCREEN_RESOLUTION_Y 43
#define SFG_DITHERED_SHADOW 1
#define SFG_FPS 20
#include "game.h"
#define NEWLINES 10
#define SCREENSIZE \
(NEWLINES + (SFG_SCREEN_RESOLUTION_X + 1) * SFG_SCREEN_RESOLUTION_Y)
char screen[SCREENSIZE];
const char shades[] = // adjust according to your terminal
{
' ','.','-',':','\\','h','M','@', // grey
'`','.',',',';','/','r','=','n' // non-grey
};
uint32_t timeStart;
typedef struct
{
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
} InputEvent;
InputEvent event;
#define TOTAL_KEYS 9
uint16_t keyCodes[TOTAL_KEYS] =
{
KEY_W,
KEY_S,
KEY_A,
KEY_D,
KEY_SPACE,
KEY_H,
KEY_J,
KEY_K,
KEY_Q
};
uint8_t keyStates[TOTAL_KEYS];
uint32_t getTime()
{
struct timeval now;
gettimeofday(&now, NULL);
return now.tv_sec * 1000 + now.tv_usec / 1000;
}
void SFG_setPixel(uint16_t x, uint16_t y, uint8_t colorIndex)
{
screen[NEWLINES + y * (SFG_SCREEN_RESOLUTION_X + 1) + x] =
shades[(colorIndex > 7) * 8 + colorIndex % 8];
}
uint32_t SFG_getTimeMs()
{
clock_t timeNow = clock();
return getTime() - timeStart;
}
void SFG_save(uint8_t data[SFG_SAVE_SIZE])
{
}
uint8_t SFG_load(uint8_t data[SFG_SAVE_SIZE])
{
return 0;
}
void SFG_sleepMs(uint16_t timeMs)
{
usleep(timeMs * 1000);
}
void SFG_getMouseOffset(int16_t *x, int16_t *y)
{
}
int8_t SFG_keyPressed(uint8_t key)
{
switch (key)
{
case SFG_KEY_UP: return keyStates[0]; break;
case SFG_KEY_RIGHT: return keyStates[3]; break;
case SFG_KEY_DOWN: return keyStates[1]; break;
case SFG_KEY_LEFT: return keyStates[2]; break;
case SFG_KEY_A: return keyStates[5]; break;
case SFG_KEY_B: return keyStates[6]; break;
case SFG_KEY_C: return keyStates[7]; break;
case SFG_KEY_MAP: return keyStates[8]; break;
default: return 0; break;
}
}
void SFG_enableMusic(uint8_t enable)
{
}
void SFG_playSound(uint8_t soundIndex, uint8_t volume)
{
}
int nextFlush = 0;
int main()
{
int devFile;
timeStart = getTime();
devFile = open("/dev/input/event0", O_RDONLY);
fcntl(devFile, F_SETFL, O_NONBLOCK);
SFG_init();
for (uint16_t i = 0; i < TOTAL_KEYS; ++i)
keyStates[i] = 0;
for (uint16_t i = 0; i < NEWLINES; ++i)
screen[i] = '\n';
for (uint16_t i = 1; i <= SFG_SCREEN_RESOLUTION_Y; ++i)
screen[NEWLINES + i * (SFG_SCREEN_RESOLUTION_X + 1) - 1] = '\n';
setvbuf(stdout, NULL, _IOFBF, SCREENSIZE + 1);
while (1)
{
while (1)
{
int n = read(devFile, &event, sizeof(event));
if (n <= 0)
break;
if (event.type == EV_KEY && (event.value == 1 || event.value == 0))
{
for (uint8_t i = 0; i < TOTAL_KEYS; ++i)
if (event.code == keyCodes[i])
{
keyStates[i] = event.value;
break;
}
}
}
uint32_t t = SFG_getTimeMs();
if (t >= nextFlush)
{
puts(screen);
fflush(stdout);
nextFlush = t + 200; // 5 rendering FPS
}
if (!SFG_mainLoopBody())
break;
}
}