more tetris

This commit is contained in:
manuelthieme 2020-02-06 14:34:35 +01:00
parent d3f188e86b
commit 3697a76f5f

199
tetris.c
View file

@ -2,6 +2,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <ncurses.h>
enum { enum {
HEIGHT = 20, HEIGHT = 20,
WIDTH = 10, WIDTH = 10,
@ -18,7 +20,7 @@ struct rotation {
struct brick { struct brick {
struct rotation *states; struct rotation *states;
int state; int rotation;
struct position position; struct position position;
}; };
@ -63,13 +65,8 @@ struct rotation t_brick_rotations[4] = {
}; };
struct game_state {
char running;
char game_grid[WIDTH][HEIGHT];
struct brick current_brick;
};
enum input { enum input {
I_NONE,
I_QUIT, I_QUIT,
I_LEFT, I_LEFT,
I_RIGHT, I_RIGHT,
@ -77,29 +74,42 @@ enum input {
I_ROTATE, I_ROTATE,
}; };
struct game_state {
char running;
char grid[WIDTH][HEIGHT];
struct brick current_brick;
enum input input;
unsigned int tick;
};
struct game_state construct_game_state(); struct game_state construct_game_state();
struct brick spawn_brick(); struct brick spawn_brick();
/* gravitate brick (darf der das?) */ int gravitate_brick(struct game_state *game_state);
/* (optional) drop brick */ /* (optional) drop brick */
/* should brick fall? */
/* rotate brick */
/* check for full line */ /* check for full line */
/* remove full line */ /* remove full line */
/* move brick */ int brick_collides_x(struct brick brick);
/* get input */ int brick_collides_y(struct brick brick);
/* evaluate input */ int brick_collides_grid(struct brick brick, struct game_state game_state);
void move_brick(struct brick *brick, int direction);
void rotate_brick(struct brick *brick);
enum input get_input();
void evaluate_input(struct game_state *game_state, enum input input);
/* brick to grid */ /* brick to grid */
void brick_to_grid(struct brick brick, struct game_state *game_state);
/* loose condition */ /* loose condition */
@ -108,22 +118,32 @@ void draw_game_state(struct game_state game_state);
int brick_on_position(int x, int y, struct brick brick); int brick_on_position(int x, int y, struct brick brick);
int main(void) { int main(void) {
initscr();
noecho();
nodelay(stdscr, TRUE);
struct game_state game_state = construct_game_state(); struct game_state game_state = construct_game_state();
while (game_state.running) { while (game_state.running) {
game_state.tick++;
draw_game_state(game_state); draw_game_state(game_state);
//get input enum input input = get_input();
//evaluate input evaluate_input(&game_state, input);
//game logic if (game_state.tick % 10 == 0) {
game_state.current_brick.position.y++; int brick_fell = gravitate_brick(&game_state);
sleep(1); if (!brick_fell) {
game_state.current_brick = spawn_brick();
}
}
usleep(100000);
} }
endwin();
} }
struct game_state construct_game_state() { struct game_state construct_game_state() {
struct game_state game_state = { struct game_state game_state = {
.running = 1, .running = 1,
.game_grid = {0}, .grid = {0},
.current_brick = spawn_brick() .current_brick = spawn_brick(),
.tick = 0,
}; };
return game_state; return game_state;
} }
@ -131,37 +151,37 @@ struct game_state construct_game_state() {
struct brick spawn_brick() { struct brick spawn_brick() {
struct brick brick = { struct brick brick = {
.states = t_brick_rotations, .states = t_brick_rotations,
.state = 0, .rotation = 0,
.position = {.x = 3, .y=0} .position = {.x = 3, .y=0}
}; };
return brick; return brick;
} }
void draw_game_state(struct game_state game_state) { void draw_game_state(struct game_state game_state) {
system("clear"); clear();
for (int y = 0; y < HEIGHT; ++y) { for (int y = 0; y < HEIGHT; ++y) {
printf("|"); printw("|");
for (int x = 0; x < WIDTH; ++x) { for (int x = 0; x < WIDTH; ++x) {
if (game_state.game_grid[x][y] if (game_state.grid[x][y]
|| brick_on_position(x, y, game_state.current_brick)) { || brick_on_position(x, y, game_state.current_brick)) {
printf("O"); printw("O");
} else { } else {
printf(" "); printw(" ");
} }
} }
printf("|\n"); printw("|\n");
} }
printf("|"); printw("|");
for (int x = 0; x < WIDTH; ++x) { for (int x = 0; x < WIDTH; ++x) {
printf("-"); printw("-");
} }
printf("|\n"); printw("|\n");
} }
int brick_on_position(int x, int y, struct brick brick) { int brick_on_position(int x, int y, struct brick brick) {
x -= brick.position.x; x -= brick.position.x;
y -= brick.position.y; y -= brick.position.y;
struct rotation *rotation = &brick.states[brick.state]; struct rotation *rotation = &brick.states[brick.rotation];
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
if (rotation->tiles[i].x == x && rotation->tiles[i].y == y) { if (rotation->tiles[i].x == x && rotation->tiles[i].y == y) {
return 1; return 1;
@ -169,3 +189,116 @@ int brick_on_position(int x, int y, struct brick brick) {
} }
return 0; return 0;
} }
enum input get_input() {
char in = getch();
switch (in) {
case 'w':
return I_ROTATE;
case 'q':
return I_QUIT;
case 'a':
return I_LEFT;
case 'd':
return I_RIGHT;
case 's':
return I_DROP;
default:
return I_NONE;
}
}
void evaluate_input(struct game_state *game_state, enum input input) {
switch (input) {
case I_ROTATE:
rotate_brick(&game_state->current_brick);
break;
case I_QUIT:
game_state->running = false;
break;
case I_LEFT:
move_brick(&game_state->current_brick, -1);
break;
case I_RIGHT:
move_brick(&game_state->current_brick, 1);
break;
case I_DROP:
while(gravitate_brick(game_state)) {
/* void */
}
break;
default:
break;
}
}
void rotate_brick(struct brick *brick) {
brick->rotation++;
brick->rotation %= 4;
if (brick_collides_x(*brick)) {
/* for real module, do +4 and -1 */
brick->rotation += 3;
brick->rotation %= 4;
}
}
void move_brick(struct brick *brick, int direction) {
brick->position.x += direction;
if (brick_collides_x(*brick)) {
brick->position.x -= direction;
}
}
int brick_collides_x(struct brick brick) {
for (int i = 0; i < 4; ++i) {
struct position tile_pos = brick.states[brick.rotation].tiles[i];
tile_pos.x += brick.position.x;
if (tile_pos.x > WIDTH - 1 || tile_pos.x < 0) {
return 1;
}
}
return 0;
}
int brick_collides_y(struct brick brick) {
for (int i = 0; i < 4; ++i) {
struct position tile_pos = brick.states[brick.rotation].tiles[i];
tile_pos.y += brick.position.y;
if (tile_pos.y > HEIGHT - 1) {
return 1;
}
}
return 0;
}
int brick_collides_grid(struct brick brick, struct game_state game_state) {
for (int i = 0; i < 4; ++i) {
struct position tile_pos = brick.states[brick.rotation].tiles[i];
tile_pos.x += brick.position.x;
tile_pos.y += brick.position.y;
if (game_state.grid[tile_pos.x][tile_pos.y]) {
return 1;
}
}
return 0;
}
int gravitate_brick(struct game_state *game_state) {
game_state->current_brick.position.y++;
if (brick_collides_grid(game_state->current_brick, *game_state)
|| brick_collides_y(game_state->current_brick)) {
game_state->current_brick.position.y--;
brick_to_grid(game_state->current_brick, game_state);
return 0;
}
return 1;
}
void brick_to_grid(struct brick brick, struct game_state *game_state) {
for (int i = 0; i < 4; ++i) {
struct position tile_pos = brick.states[brick.rotation].tiles[i];
tile_pos.x += brick.position.x;
tile_pos.y += brick.position.y;
game_state->grid[tile_pos.x][tile_pos.y] = 1;
}
}