timesynk/interface/curses.c

196 lines
6.7 KiB
C

#include <curses.h>
#include <string.h>
#include "curses.h"
#include "../helper.h"
#include "../player.h"
#include "../game.h"
#include "../wall.h"
#include "../main.h"
#include "../common.h"
#include "../context.h"
#include "../stubs.h"
#include "../tile.h" // for DoorTile, etc.
#include "../tiles/curses_tiles.h"
#include "../console.h"
int interfaceInit() {
// initialize ncurses library
if ((screen = initscr()) == NULL) {
perror("initscr() error'd");
return ERROR;
}
original_cursor = curs_set(0); // store original cursor position for restore and hide cursor
keypad(screen, TRUE); // enable arrow keys/keypad
noecho(); // turn off key echoing
nonl(); // do not do NL->CR/NL on output
cbreak(); // Handle char presses immediately, do not wait for \n
if (has_colors()) {
start_color();
// set up all possible color pairs using COLORS as our max (8 default)
int x, y;
for (x=0;x<COLORS;x++) {
for(y=0;y<COLORS;y++) {
init_pair(x*COLORS+y, x, y);
}
}
}
return SUCCESS;
}
void interfaceLoop() {
int key = getch();
globalContext(key);
}
void interfaceDraw() {
//clear();
int step_x = player->x - ((struct PlayerTile*)player->data)->vision;
int step_y = player->y - ((struct PlayerTile*)player->data)->vision;
int end_x = player->x + ((struct PlayerTile*)player->data)->vision;
int end_y = player->y + ((struct PlayerTile*)player->data)->vision;
float camera_offset_x = player->x - (80/2); // TODO: get term size
float camera_offset_y = player->y - (24/2);
while (step_x < end_x) {
step_y = player->y - ((struct PlayerTile*)player->data)->vision;
while (step_y < end_y) {
//if (visible_matrix[step_x][step_y] & TILE_VISIBLE) {
if (step_x >= 0 && step_y >= 0 && step_x < current_map->width && step_y < current_map->height) {
struct Tile *current_tile;
current_tile = &(current_map)->matrix[step_x][step_y];
while(current_tile) {
short tile_id = current_tile->id;
unsigned int type_id = current_tile->tid;
int color;
switch (type_id) {
case WALL:
color = curses_walls[tile_id].fg * COLORS + curses_walls[tile_id].bg;
attron(COLOR_PAIR(color) | curses_walls[tile_id].attr);
mvwaddch(screen, step_y-camera_offset_y, step_x-camera_offset_x, curses_walls[tile_id].ch);
attroff(COLOR_PAIR(color) | curses_walls[tile_id].attr);
break;
case FLOOR:
color = curses_walls[tile_id].fg * COLORS + curses_walls[tile_id].bg;
attron(COLOR_PAIR(color) | curses_walls[tile_id].attr);
mvwaddch(screen, step_y-camera_offset_y, step_x-camera_offset_x, '.');
attroff(COLOR_PAIR(color) | curses_walls[tile_id].attr);
break;
case DOOR:
// doors work by taking the original id(0) and adding the current state(0=closed,1=open,2=broken,3=missing). For one door, you need 4 individual tiles.
tile_id = tile_id*4;
tile_id += ((struct DoorTile*)(current_tile->data))->state;
color = curses_doors[tile_id].fg * COLORS + curses_doors[tile_id].bg;
attron(COLOR_PAIR(color) | curses_doors[tile_id].attr);
mvwaddch(screen, step_y-camera_offset_y, step_x-camera_offset_x, curses_doors[tile_id].ch);
attroff(COLOR_PAIR(color) | curses_doors[tile_id].attr);
break;
case PLAYER:
color = curses_players[tile_id].fg * COLORS + curses_players[tile_id].bg;
attron(COLOR_PAIR(color) | curses_players[tile_id].attr);
mvwaddch(screen, step_y-camera_offset_y, step_x-camera_offset_x, '@');
attroff(COLOR_PAIR(color) | curses_players[tile_id].attr);
break;
case NPC:
color = curses_npcs[tile_id].fg * COLORS + curses_npcs[tile_id].bg;
attron(COLOR_PAIR(color) | curses_npcs[tile_id].attr);
mvwaddch(screen, step_y-camera_offset_y, step_x-camera_offset_x, curses_npcs[tile_id].ch);
attroff(COLOR_PAIR(color) | curses_npcs[tile_id].attr);
break;
}
current_tile = current_tile->next;
}
} else {
mvwaddch(screen, step_y-camera_offset_y, step_x-camera_offset_x, ' ');
}
step_y++; // move down
}
step_x++; // move right
}
move(player->y-camera_offset_y, player->x-camera_offset_x);
if (current_context == &consoleContext) {
interfaceDrawConsole();
}
refresh();
}
void interfaceClose() {
wrefresh(screen);
delwin(screen);
endwin();
}
/* non-main() funcs */
void interfacePrint(const char *input_string) {
// TODO: "zero" out whole line before printing new one (so overlap is gone)
mvwaddstr(screen, 22, 0, input_string);
consoleLog(input_string);
}
void interfacePrintf(const char *input_string, ...) {
int *byte_location;
byte_location = &input_string+1; // our first arg, effectively
int byte_offset; // our memory reference used for getting argument offsets from the original string
char formatted_string[32];// start at 32?
//int formatted_string_length = 8;
int format_step = 0;
int input_step = 0;
char current_char = input_string[0];
formatted_string[0] = current_char;
int handle_format = 0;
while (current_char != '\0') {
input_step++;
current_char = input_string[input_step];
if (handle_format == 1) {
switch(current_char) {
case 'c': // for char
byte_offset = *byte_location++; // our arg location
handle_format = 0;
format_step++;
//formatted_string[format_step] = *byte_location;
formatted_string[format_step] = byte_offset;
// convert decimal to curses
break;
case 's':
handle_format = 0;
byte_offset = *byte_location++; // our arg location
while(byte_offset != '\0') {
format_step++;
formatted_string[format_step] = byte_offset;
byte_offset = *byte_location++; // our arg location
}
break;
}
} else if (current_char == '%') {
handle_format = 1;
} else {
format_step++;
formatted_string[format_step] = current_char;
}
}
mvwaddstr(screen, 22, 0, formatted_string);
}
void interfaceDrawConsole() {
int line;
struct ConsoleEntry *entry;
entry = console_last_entry;
for (line = 7;line >= 0;line--) {
move(line, 0);
if (entry->size > 0) {
addstr(consoleGetEntryString(entry));
}
if (entry->prev)
entry = entry->prev;
hline(' ', 80);
}
move(9, 0);
hline('-', 80);
move(8, 0);
hline(' ', 80);
move(8, 0);
addstr("> ");
addstr(console_cmd);
}