This commit is contained in:
Daniel 2017-03-01 16:43:37 +01:00
commit 01b214f53b
7 changed files with 359 additions and 0 deletions

17
Makefile Normal file
View File

@ -0,0 +1,17 @@
CC=gcc
CFLAG= -O -g -o
objects=main.o\
playfield.o\
input_output.o
all:main
%.o:%.c
$(CC) -c $(CFLAG) $@ $<
main: clean $(objects)
$(CC) $(objects) $(CFLAG) main
clean:
rm $(objects) || true

21
conf.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef __conf__h_
#define __conf__h_
#define WIDTH 50
#define LINES 20
#define KEY_DEFAULT '_'
#define KEY_RIGHT 'd'
#define KEY_LEFT 'a'
#define KEY_EXIT 'q'
#define CHAR_ME '#'
#define CHAR_ENEMY '*'
#define ESCAPE_RED "\033[31m"
#define ESCAPE_GREEN "\033[32m"
#define ESCAPE_RESET "\033[0m"
#define CHRS_TO_CLEAR_ESCAPE 7
#endif

71
input_output.c Normal file
View File

@ -0,0 +1,71 @@
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/select.h>
#include<signal.h>
static volatile char EOF_received = 0;
#include "conf.h"
void put_line(char * line)
{
int i;
putc('|', stdout);
for(i = 0; i < WIDTH; i++)
{
// FIXME: add colors
if(line[i] == CHAR_ME)
{
printf(ESCAPE_GREEN);
}
if(line[i] == CHAR_ENEMY)
{
printf(ESCAPE_RED);
}
putc(line[i], stdout);
if(line[i] == CHAR_ME || line[i] == CHAR_ENEMY)
{
printf(ESCAPE_RESET);
}
}
putc('|', stdout);
putc('\n', stdout);
}
void clear_screen(void)
{
int i, j;
// clear the screen
for(i = 0; i < LINES + 3; i++)
{
for(j = 0; j < WIDTH + 3 + CHRS_TO_CLEAR_ESCAPE; j++)
{
putc('\b', stdout);
}
printf("\r\033[A");
}
}
char kb_hit(void)
{
struct timeval tv = { 0L, 0L };
fd_set fds;
FD_ZERO(&fds);
FD_SET(0, &fds);
return select(1, &fds, NULL, NULL, &tv);
}
char get_last_key_or_default(void)
{
int key = KEY_DEFAULT;
while(kb_hit())
{
key = getc(stdin);
}
if(key == EOF)
{
EOF_received = 1;
}
return key;
}

16
input_output.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef __input_output_h_
#define __input_output_h_
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/select.h>
#include<signal.h>
#include "conf.h"
void put_line(char * line);
void clear_screen(void);
char kb_hit(void);
char get_last_key_or_default(void);
static volatile char EOF_received = 0;
#endif

148
main.c Normal file
View File

@ -0,0 +1,148 @@
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<termios.h>
#include <sys/select.h>
#include<signal.h>
#include"input_output.h"
#include"playfield.h"
int difficulty = 200;
static struct termios oldt, newt;
char * playfield;
char ** horizon;
static volatile char sigint_received = 0;
int main(void)
{
// set up the terminal for our hacky game....
static struct termios oldt, newt;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
// ok done
int pos = 0;
unsigned long long int score = 0;
char input = KEY_DEFAULT;
int to_place = 0;
printf("q: end; d: right; a: left\n\n\n");
while(input != KEY_EXIT && !(EOF_received || sigint_received))
{
horizon_drop_one_line(horizon);
// clear both the cursor and
// the last enemy
playfield[pos] = ' ';
horizon[0][to_place] = ' ';
if(input == KEY_RIGHT)
{
pos++;
if(pos >= WIDTH)
{
pos = 0;
}
}
if(input == KEY_LEFT)
{
pos--;
if(pos < 0)
{
pos = WIDTH - 1;
}
}
if(input == KEY_EXIT)
{
break;
}
clear_screen();
print_horizon(horizon);
playfield[pos] = CHAR_ME;
to_place = (random() & 0xff) % WIDTH;
horizon[0][to_place] = CHAR_ENEMY;
put_line(playfield);
if(horizon[LINES - 1][pos] == CHAR_ENEMY)
{
printf("GAME OVER!\nYour score was: %llu\n", score);
break;
}
usleep(difficulty * 1000);
score++;
if(!(score % 50))
{
difficulty--;
}
if(score == 0)
{
printf("Congrats. You won the game.\nAnd you have absolutely no life.\nat all.\n");
break;
}
printf("SCORE: %llu\n", score);
// check this to prevent blocking
if(EOF_received || sigint_received)
{
break;
}
input = get_last_key_or_default();
}
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return 0;
}
void __attribute__((cold)) handle_sigint(int signum)
{
sigint_received = 1;
}
void __attribute__((cold)) handle_sigterm(int signum)
{
printf("\n\nTERMINATED!\n");
exit(1);
}
/*
Constructor: Add a sighandler for SIGINT and SIGTERM
*/
void __attribute__((constructor)) add_signal_handlers(void)
{
signal(SIGINT, handle_sigint);
signal(SIGTERM, handle_sigterm);
}
/*
Destructor: Free memory
*/
void __attribute__((destructor)) clean(void)
{
free(playfield);
delete_horizon(horizon);
printf("\n");
}
/*
Constructor: create all the data we need
*/
void __attribute__((constructor)) build_playfield(void)
{
playfield = allocate_playfield(WIDTH);
build_horizon(&horizon);
}

76
playfield.c Normal file
View File

@ -0,0 +1,76 @@
#include<stdlib.h>
#include<stdio.h>
#include"conf.h"
#include"input_output.h"
void build_horizon(char *** horizon)
{
char ** h = calloc(sizeof(char * ), LINES);
int i, j;
for(i = 0; i < LINES; i++)
{
h[i] = calloc(sizeof(char), WIDTH);
for(j = 0; j < WIDTH; j++)
{
h[i][j] = ' ';
}
putc('\n', stdout); // make space for the game
}
*horizon = h;
}
void horizon_drop_one_line(char ** horizon)
{
int i, j;
for(i = LINES - 1; i >= 1; i--)
{
for(j = 0; j < WIDTH; j++)
{
horizon[i][j] = horizon[i - 1][j];
}
}
}
void print_horizon(char ** horizon)
{
int i;
putc('+', stdout);
for(i = 0; i < WIDTH ; i++)
{
putc('-', stdout);
}
putc('+', stdout);
putc('\n', stdout);
for(i = 0; i < LINES; i++)
{
put_line(horizon[i]);
}
}
void delete_horizon(char ** horizon)
{
int i;
for(i = 0; i < LINES; i++)
{
free(horizon[i]);
}
free(horizon);
}
char * allocate_playfield(size_t width)
{
char * field = calloc(sizeof(char), width);
size_t i;
for(i = 0; i < width; i++)
{
field[i] = ' ';
}
return field;
}

10
playfield.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef __playfield_h_
#define __playfield_h_
void build_horizon(char *** horizon);
void horizon_drop_one_line(char ** horizon);
void print_horizon(char ** horizon);
void delete_horizon(char ** horizon);
char * allocate_playfield(size_t width);
#endif