more tetris
This commit is contained in:
parent
d3f188e86b
commit
3697a76f5f
199
tetris.c
199
tetris.c
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue