pvjc24/final/game.c

150 lines
3.9 KiB
C
Raw Normal View History

2024-05-15 11:21:54 +00:00
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "world.h"
#define EMPTY ' '
#define BLOCK '#'
#define WIDTH 10
#define HEIGHT 20
typedef struct {
int x, y;
} Point;
typedef struct {
Point blocks[4];
Point position;
} Tetromino;
typedef struct {
char grid[HEIGHT][WIDTH];
Tetromino current;
} GameState;
Tetromino tetrominoes[] = {
2024-05-15 11:35:49 +00:00
{{{0,0}, {1,0}, {0,1}, {1,1}}, {0,0}}, // Štvorec
{{{0,0}, {1,0}, {2,0}, {3,0}}, {0,0}}, // Čiara
{{{0,0}, {1,0}, {1,1}, {2,1}}, {0,0}}, // Z tvar
{{{1,0}, {2,0}, {0,1}, {1,1}}, {0,0}}, // S tvar
{{{0,0}, {1,0}, {2,0}, {1,1}}, {0,0}}, // T tvar
{{{0,0}, {0,1}, {1,1}, {2,1}}, {0,0}}, // L tvar
{{{2,0}, {0,1}, {1,1}, {2,1}}, {0,0}} // J tvar
2024-05-15 11:21:54 +00:00
};
void draw_grid(GameState* game) {
clear_world();
for (int y = 0; y < HEIGHT; ++y) {
for (int x = 0; x < WIDTH; ++x) {
draw_character(game->grid[y][x], x, y);
}
}
for (int i = 0; i < 4; ++i) {
draw_character(BLOCK, game->current.position.x + game->current.blocks[i].x,
game->current.position.y + game->current.blocks[i].y);
}
refresh_world();
}
int is_valid_position(GameState* game, Point new_position) {
for (int i = 0; i < 4; ++i) {
int new_x = new_position.x + game->current.blocks[i].x;
int new_y = new_position.y + game->current.blocks[i].y;
if (new_x < 0 || new_x >= WIDTH || new_y < 0 || new_y >= HEIGHT || game->grid[new_y][new_x] != EMPTY) {
return 0;
}
}
return 1;
}
void place_tetromino(GameState* game) {
for (int i = 0; i < 4; ++i) {
int x = game->current.position.x + game->current.blocks[i].x;
int y = game->current.position.y + game->current.blocks[i].y;
game->grid[y][x] = BLOCK;
}
}
void clear_lines(GameState* game) {
for (int y = HEIGHT - 1; y >= 0; --y) {
int full = 1;
for (int x = 0; x < WIDTH; ++x) {
if (game->grid[y][x] == EMPTY) {
full = 0;
break;
}
}
if (full) {
for (int row = y; row > 0; --row) {
memcpy(game->grid[row], game->grid[row - 1], WIDTH);
}
memset(game->grid[0], EMPTY, WIDTH);
y++;
}
}
}
void* init_game() {
srand(time(NULL));
GameState* game = malloc(sizeof(GameState));
memset(game->grid, EMPTY, sizeof(game->grid));
game->current = tetrominoes[rand() % 7];
game->current.position.x = WIDTH / 2 - 1;
game->current.position.y = 0;
return game;
}
int game_event(struct event* event, void* state) {
GameState* game = (GameState*)state;
Point new_position = game->current.position;
if (event->key) {
switch (event->key) {
case 'a': new_position.x -= 1; break;
case 'd': new_position.x += 1; break;
case 's': new_position.y += 1; break;
case 'w': // TODO: Implement rotation
break;
case 27: return 1; // Escape key
}
if (is_valid_position(game, new_position)) {
game->current.position = new_position;
}
}
new_position.y += 1;
if (!is_valid_position(game, new_position)) {
place_tetromino(game);
clear_lines(game);
game->current = tetrominoes[rand() % 7];
game->current.position.x = WIDTH / 2 - 1;
game->current.position.y = 0;
if (!is_valid_position(game, game->current.position)) {
return 1; // Game over
}
} else {
game->current.position = new_position;
}
draw_grid(game);
return 0;
}
2024-05-15 11:35:49 +00:00
int main() {
init_world(WIDTH, HEIGHT);
void* game = init_game();
struct event ev;
while (1) {
ev.key = getch();
if (game_event(&ev, game)) {
break;
}
}
endwin();
free(game);
return 0;
}