diff options
Diffstat (limited to 'frontends/gl')
| -rw-r--r-- | frontends/gl/audio.c | 35 | ||||
| -rw-r--r-- | frontends/gl/audio.h | 18 | ||||
| -rw-r--r-- | frontends/gl/drawable.c | 26 | ||||
| -rw-r--r-- | frontends/gl/drawable.h | 3 | ||||
| -rw-r--r-- | frontends/gl/main.c | 136 | ||||
| -rw-r--r-- | frontends/gl/meson.build | 2 | ||||
| -rw-r--r-- | frontends/gl/skin.c | 52 | ||||
| -rw-r--r-- | frontends/gl/skin.h | 10 | ||||
| -rw-r--r-- | frontends/gl/ui.c | 134 | ||||
| -rw-r--r-- | frontends/gl/ui.h | 25 |
10 files changed, 364 insertions, 77 deletions
diff --git a/frontends/gl/audio.c b/frontends/gl/audio.c new file mode 100644 index 0000000..4278f4e --- /dev/null +++ b/frontends/gl/audio.c @@ -0,0 +1,35 @@ +#ifdef _WIN32 +#include <SDL.h> +#define format_str sprintf_s +#else +#include <SDL2/SDL.h> +#define format_str snprintf +#endif + +#include "audio.h" + +SDL_AudioDeviceID load_audio() { + SDL_AudioSpec spec; + SDL_memset(&spec, 0, sizeof(spec)); + spec.freq = 44100; + spec.format = AUDIO_S16; + spec.channels = 2; + spec.samples = 4096; + spec.callback = NULL; + + return SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0); +} + +void load_multiple_audio(char* name, char* dir_name, int *count, audio_clip_t* list) { + char file[120]; + + int index = 0; + for (int i = 0; i < (*count); i++) { + format_str(file, 120, "%s/%s_%i.wav", dir_name, name, i); + + if (SDL_LoadWAV(file, &list[index].wav_spec, + &list[index].wav_buffer, &list[index].wav_length) == NULL) { + (*count)--; + } else index++; + } +} diff --git a/frontends/gl/audio.h b/frontends/gl/audio.h new file mode 100644 index 0000000..736aec0 --- /dev/null +++ b/frontends/gl/audio.h @@ -0,0 +1,18 @@ +#pragma once + +#ifdef _WIN32 +#include <SDL.h> +#define format_str sprintf_s +#else +#include <SDL2/SDL.h> +#define format_str snprintf +#endif + +typedef struct { + SDL_AudioSpec wav_spec; + uint32_t wav_length; + uint8_t *wav_buffer; +} audio_clip_t; + +void load_multiple_audio(char* name, char* dir_name, int *count, audio_clip_t* list); +SDL_AudioDeviceID load_audio(); diff --git a/frontends/gl/drawable.c b/frontends/gl/drawable.c index 75c1ca5..d6fd8a1 100644 --- a/frontends/gl/drawable.c +++ b/frontends/gl/drawable.c @@ -20,13 +20,6 @@ GLuint elements[] = { 2, 3, 0 }; -void calc_pos(GLfloat *rect, GLfloat x, GLfloat y, GLfloat w, GLfloat h) { - rect[0] = rect[12] = -1.0f + (x / 200.0f); - rect[1] = rect[5] = 1.0f - (y / 400.0f); - rect[9] = rect[13] = rect[1] - (h) / 400.0f; - rect[4] = rect[8] = rect[0] + (w) / 200.0f; -} - bool load_image(char* file_name, drawable_t *drawable) { int w, h, channel; unsigned char *data = stbi_load(file_name, &w, &h, &channel, STBI_rgb_alpha); @@ -45,19 +38,30 @@ bool load_image(char* file_name, drawable_t *drawable) { return true; } +void crop_texture(drawable_t *drawable, int h, int w) { + drawable->vertices[2] = drawable->vertices[14] = w; + drawable->vertices[3] = drawable->vertices[7] = h; + drawable->vertices[6] = drawable->vertices[10] = 1.0f; + drawable->vertices[15] = drawable->vertices[11] = h; +} + void set_block_texture(drawable_t *drawable, uint8_t mino) { GLfloat index = (mino + 2) * .0625f; drawable->vertices[2] = drawable->vertices[14] = index; drawable->vertices[6] = drawable->vertices[10] = index + .0625f; - //vertices[5] = vertices[13] = vertices[21] = vertices[29] = opacity; } -void update_rect(drawable_t *drawable, GLfloat x, GLfloat y, GLfloat w, GLfloat h) { - calc_pos(drawable->vertices, x, y, w, h); +void update_rect(drawable_t *drawable, GLfloat x, GLfloat y, + GLfloat w, GLfloat h, GLfloat window_width, GLfloat window_height) { + GLfloat x_ratio = window_width / 2.0f; + GLfloat y_ratio = window_height / 2.0f; + drawable->vertices[0] = drawable->vertices[12] = -1.0f + (x / x_ratio); + drawable->vertices[1] = drawable->vertices[5] = 1.0f - (y / y_ratio); + drawable->vertices[9] = drawable->vertices[13] = drawable->vertices[1] - (h) / y_ratio; + drawable->vertices[4] = drawable->vertices[8] = drawable->vertices[0] + (w) / x_ratio; glBindBuffer(GL_ARRAY_BUFFER, drawable->vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), drawable->vertices, GL_DYNAMIC_DRAW); - //glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); } void new_rectangle(drawable_t* drawable) { diff --git a/frontends/gl/drawable.h b/frontends/gl/drawable.h index 4137d37..6b1e964 100644 --- a/frontends/gl/drawable.h +++ b/frontends/gl/drawable.h @@ -15,6 +15,7 @@ typedef struct { } drawable_t; void new_rectangle(drawable_t* drawable); -void update_rect(drawable_t *drawable, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +void update_rect(drawable_t *drawable, GLfloat x, GLfloat y, GLfloat w, GLfloat h, GLfloat window_width, GLfloat window_height); void set_block_texture(drawable_t *drawable, uint8_t mino); bool load_image(char* file_name, drawable_t *drawable); +void crop_texture(drawable_t *drawable, int h, int w); diff --git a/frontends/gl/main.c b/frontends/gl/main.c index e3aa591..90dbfa5 100644 --- a/frontends/gl/main.c +++ b/frontends/gl/main.c @@ -10,6 +10,7 @@ #include <cetris.h> #include <timer.h> #include <rules.h> +#include <ini.h> #include "shader.h" #include "skin.h" @@ -18,8 +19,8 @@ static const int FRAME_RATE = 144; static const int SCREEN_FULLSCREEN = 0; -static const int SCREEN_WIDTH = 400; -static const int SCREEN_HEIGHT = 800; +static const int SCREEN_WIDTH = 720; +static const int SCREEN_HEIGHT = 900; static SDL_Window *window = NULL; static SDL_GLContext maincontext; @@ -34,6 +35,113 @@ key_bindings_t default_keys = { .key_restart = 'r' }; +void load_config(cetris_ui *ui) { + ui->board.game.config = tetris_ds_config; + + ini_parser p; + if (load_ini_file(&p, "config.ini")) { + char* das = get_ini_value(&p, "das", "das"); + if (das) { + ui->board.game.config.das_das = atoi(das); + free(das); + } + + char *arr = get_ini_value(&p, "das", "arr"); + if (arr) { + ui->board.game.config.das_arr = atoi(arr); + free(arr); + } + + char* drop_delay = get_ini_value(&p, "game", "drop_delay"); + if (drop_delay) { + ui->board.game.config.drop_period = atoi(drop_delay); + free(drop_delay); + } + + char* next_piece_delay = get_ini_value(&p, "game", "next_piece_delay"); + if (next_piece_delay) { + ui->board.game.config.next_piece_delay = atoi(next_piece_delay); + free(next_piece_delay); + } + + char* lock_delay = get_ini_value(&p, "game", "lock_delay"); + if (lock_delay) { + ui->board.game.config.lock_delay = atoi(lock_delay); + free(lock_delay); + } + + char* force_lock = get_ini_value(&p, "game", "force_lock"); + if (force_lock) { + ui->board.game.config.force_lock = atoi(force_lock); + free(force_lock); + } + + char* wait_on_clear = get_ini_value(&p, "game", "wait_on_clear"); + if (wait_on_clear && !strcmp(wait_on_clear, "true")) { + ui->board.game.config.wait_on_clear = true; + free(wait_on_clear); + } else ui->board.game.config.wait_on_clear = false; + + char* line_delay_clear = get_ini_value(&p, "game", "line_clear_delay"); + if (line_delay_clear) { + ui->board.game.config.line_delay_clear = atoi(line_delay_clear); + free(line_delay_clear); + } + + char *skin = get_ini_value(&p, "ui", "skin"); + if (skin) { + load_skin(skin, &ui->board.skin); + } else load_skin("default", &ui->board.skin); + } +} + +void handle_game_events(cetris_ui *ui, tetris_board_t *board) { + /* + if (board->count_down < 0 && board->game.waiting) { + cetris_start_game(&board->game); + } + */ + + if (board->game.line_event > 0) { + int index; + //if (ui->skin.random_audio) { + // index = rand() % 4;//ui->skin.clear_sound_count; + //} else { + index = board->game.line_combo - 1; + //} + //if (index >= 4) + //index = ui->skin.clear_sound_count - 1; + + SDL_QueueAudio(ui->audio_device, board->skin.clear_sound[index].wav_buffer, + board->skin.clear_sound[index].wav_length); + + SDL_PauseAudioDevice(ui->audio_device, 0); + + board->game.line_event--; + if (board->game.lock_event) + board->game.lock_event = 0; + } + + if (board->game.tetris_event > 0) { + //int index = rand() % ui->skin.tetris_sound_count; + SDL_QueueAudio(ui->audio_device, board->skin.tetris_sound[0].wav_buffer, + board->skin.tetris_sound[0].wav_length); + + SDL_PauseAudioDevice(ui->audio_device, 0); + board->game.tetris_event--; + } + + if (board->game.lock_event > 0) { + SDL_QueueAudio(ui->audio_device, board->skin.lock_sound.wav_buffer, + board->skin.lock_sound.wav_length); + + SDL_PauseAudioDevice(ui->audio_device, 0); + board->game.lock_event--; + } +} + + + void handle_key(SDL_Event e, key_bindings_t *keys, tetris_board_t* board) { int sym; switch (e.type) { @@ -79,7 +187,7 @@ void handle_key(SDL_Event e, key_bindings_t *keys, tetris_board_t* board) { } int main(void) { - if (SDL_Init(SDL_INIT_VIDEO) < 0) { + if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0) { printf("error\n"); } @@ -113,9 +221,14 @@ int main(void) { SDL_GL_SetSwapInterval(1); cetris_ui ui; + ui.window_height = SCREEN_HEIGHT; + ui.window_width = SCREEN_WIDTH; + + ui.audio_device = load_audio(); + ui.keys = default_keys; - glViewport(0, 0, 400, 800); + glViewport(0, 0, 720, 900); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -129,15 +242,12 @@ int main(void) { glUseProgram(shaderProgram); ui.shader_program = shaderProgram; - printf("%i\n", tetris_ds_config.board_x); - ui.board.config = tetris_ds_config; - - init_game(&ui.board.game, &ui.board.config); + load_config(&ui); + init_game(&ui.board.game); cetris_start_game(&ui.board.game); - load_tetris_board(&ui.board, 50.0f, 155.0f, 250.0f, 500.0f); - - load_skin("test", &ui.skin); + load_tetris_board(&ui, &ui.board, 235.0f, 200.0f, 250.0f, 500.0f); + load_held_piece(&ui, &ui.board, 152.0f, 210.0f, 88.0f, 88.0f); SDL_Event e; @@ -149,7 +259,9 @@ int main(void) { handle_key(e, &ui.keys, &ui.board); } - draw_tetris_board(&ui); + draw_tetris_board(&ui); + draw_held_piece(&ui); + handle_game_events(&ui, &ui.board); SDL_GL_SwapWindow(window); diff --git a/frontends/gl/meson.build b/frontends/gl/meson.build index f947bf5..1e4e515 100644 --- a/frontends/gl/meson.build +++ b/frontends/gl/meson.build @@ -1,4 +1,4 @@ -src = ['ui.c', 'skin.c', 'drawable.c', 'shader.c', 'main.c', 'glad/src/glad.c'] +src = ['audio.c', 'ui.c', 'skin.c', 'drawable.c', 'shader.c', 'main.c', 'glad/src/glad.c'] inc = [cetris_inc, include_directories('glad/include')] deps = [cetris] diff --git a/frontends/gl/skin.c b/frontends/gl/skin.c index 1784d72..661f815 100644 --- a/frontends/gl/skin.c +++ b/frontends/gl/skin.c @@ -1,6 +1,7 @@ #include <glad/glad.h> #include "drawable.h" +#include "audio.h" #include "skin.h" #include <string.h> @@ -14,6 +15,16 @@ #define format_str snprintf #endif +void load_element(drawable_t* drawable, char* file_name, char* dir_name) { + char file[125]; + format_str(file, 125, "%s/%s", dir_name, file_name); + glGenTextures(1, &drawable->texture); + glBindTexture(GL_TEXTURE_2D, drawable->texture); + new_rectangle(drawable); + load_image(file, drawable); + glBindTexture(GL_TEXTURE_2D, 0); +} + void load_skin(char* name, cetris_skin_t* skin) { char *dir_name = malloc(100); format_str(dir_name, 100, "skins/%s", name); @@ -27,25 +38,30 @@ void load_skin(char* name, cetris_skin_t* skin) { if (!(stat(dir_name, &sb) == 0 && S_ISDIR(sb.st_mode))) dir_name = "skins/default"; #endif - - char file[125]; - format_str(file, 125, "%s/blocks.png", dir_name); - glGenTextures(1, &skin->block.texture); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, skin->block.texture); - new_rectangle(&skin->block); - if (load_image(file, &skin->block)) { - skin->has_block_texture = true; - } else skin->has_block_texture = false; - glBindTexture(GL_TEXTURE_2D, 0); - format_str(file, 125, "%s/overlay.png", dir_name); - glGenTextures(1, &skin->overlay.texture); - glBindTexture(GL_TEXTURE_2D, skin->overlay.texture); - new_rectangle(&skin->overlay); - if (load_image(file, &skin->overlay)) { - skin->has_overlay_texture = true; - } else skin->has_overlay_texture = false; - glBindTexture(GL_TEXTURE_2D, 0); + load_element(&skin->block, "blocks.png", dir_name); + load_element(&skin->overlay, "overlay.png", dir_name); + load_element(&skin->background, "background.png", dir_name); + load_element(&skin->playboard, "playboard.png", dir_name); + load_element(&skin->border, "border.png", dir_name); + + int clear_count = 5; + skin->clear_sound = + (audio_clip_t *)malloc(sizeof(audio_clip_t) * 5); + load_multiple_audio("clear", dir_name, + &clear_count, skin->clear_sound); + + int tetris_count = 5; + skin->tetris_sound = + (audio_clip_t *)malloc(sizeof(audio_clip_t) * 5); + load_multiple_audio("four_clear", dir_name, + &tetris_count, skin->tetris_sound); + + format_str(name, 120, "%s/lock.wav", dir_name); + SDL_LoadWAV(name, &skin->lock_sound.wav_spec, + &skin->lock_sound.wav_buffer, &skin->lock_sound.wav_length); + + } diff --git a/frontends/gl/skin.h b/frontends/gl/skin.h index 36e2e8b..b7aa994 100644 --- a/frontends/gl/skin.h +++ b/frontends/gl/skin.h @@ -1,14 +1,18 @@ #pragma once #include "drawable.h" +#include "audio.h" typedef struct { - bool has_block_texture; drawable_t block; - - bool has_overlay_texture; drawable_t overlay; + drawable_t playboard; + drawable_t border; + drawable_t background; + audio_clip_t *clear_sound; + audio_clip_t *tetris_sound; + audio_clip_t lock_sound; } cetris_skin_t; void load_skin(char* name, cetris_skin_t* skin); diff --git a/frontends/gl/ui.c b/frontends/gl/ui.c index fadfa4f..f252cbf 100644 --- a/frontends/gl/ui.c +++ b/frontends/gl/ui.c @@ -4,44 +4,77 @@ #include "ui.h" #include "drawable.h" -void load_tetris_board(tetris_board_t *board, GLfloat x, GLfloat y, GLfloat w, GLfloat h) { - board->block_width = w / (GLfloat)board->config.board_x; - board->block_height = h / board->config.board_visible; +void load_tetris_board(cetris_ui *ui, tetris_board_t *board, GLfloat x, GLfloat y, GLfloat w, GLfloat h) { + board->block_width = w / (GLfloat)board->game.config.board_x; + board->block_height = h / board->game.config.board_visible; board->x_offset = x; board->y_offset = y; - board->block_offset = (board->config.board_y - board->config.board_visible); + board->block_offset = (board->game.config.board_y - board->game.config.board_visible); + + update_rect(&board->skin.playboard, board->x_offset, board->y_offset - 10, + board->game.config.board_x * board->block_width, + (board->game.config.board_visible * board->block_height) + 10, + ui->window_width, ui->window_height); + + update_rect(&board->skin.border, board->x_offset - 110, board->y_offset - 45, 380, 600, + ui->window_width, ui->window_height); +} + +void load_held_piece(cetris_ui *ui, tetris_board_t *board, GLfloat x, GLfloat y, GLfloat w, GLfloat h) { + board->held.block_width = w / 4.0f; + board->held.block_height = h / 4.0f; + + board->held.x_offset = x; + board->held.y_offset = y; } void draw_tetris_board(cetris_ui *ui) { glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, ui->skin.overlay.texture); - glBindVertexArray(ui->skin.overlay.vao); - for (int y = 0; y < ui->board.game.config.board_visible; y++) { - update_rect(&ui->skin.overlay, ui->board.x_offset, - ui->board.y_offset + (y * ui->board.block_height), - ui->board.block_width * ui->board.game.config.board_x, - ui->board.block_height); + glBindTexture(GL_TEXTURE_2D, ui->board.skin.playboard.texture); + glBindVertexArray(ui->board.skin.playboard.vao); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + glBindTexture(GL_TEXTURE_2D, 0); + + glBindTexture(GL_TEXTURE_2D, ui->board.skin.overlay.texture); + glBindVertexArray(ui->board.skin.overlay.vao); + + for (int y = 0; y < ui->board.game.config.board_visible + 1; y++) { + GLfloat height = ui->board.block_height; + GLfloat y_pos = (ui->board.y_offset - ui->board.block_height) + (y * ui->board.block_height); + if (y == 0) { + ui->board.skin.overlay.vertices[3] = ui->board.skin.overlay.vertices[7] = 0.6f; + height = 10; + y_pos += 15; + } + update_rect(&ui->board.skin.overlay, ui->board.x_offset, + y_pos, ui->board.block_width * ui->board.game.config.board_x, + height, ui->window_width, + ui->window_height); + if (y == 0) + ui->board.skin.overlay.vertices[3] = ui->board.skin.overlay.vertices[7] = 0.0f; glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); } glBindTexture(GL_TEXTURE_2D, 0); - glBindTexture(GL_TEXTURE_2D, ui->skin.block.texture); + glBindTexture(GL_TEXTURE_2D, ui->board.skin.block.texture); - glBindVertexArray(ui->skin.block.vao); + glBindVertexArray(ui->board.skin.block.vao); for (int x = 0; x < ui->board.game.config.board_x; x++) { for (int y = ui->board.game.highest_line; y < ui->board.game.config.board_y; y++) { if (ui->board.game.board[x][y] & SLOT_OCCUPIED) { - set_block_texture(&ui->skin.block, (ui->board.game.board[x][y] >> 5)); - - update_rect(&ui->skin.block, + set_block_texture(&ui->board.skin.block, (ui->board.game.board[x][y] >> 5)); + + if (y < ui->board.block_offset - 1) continue; + + update_rect(&ui->board.skin.block, ui->board.x_offset + (x * ui->board.block_width), ui->board.y_offset + ((y - ui->board.block_offset) * ui->board.block_height), - ui->board.block_width, - ui->board.block_height); + ui->board.block_width, ui->board.block_height, + ui->window_width, ui->window_height); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); @@ -56,25 +89,30 @@ void draw_tetris_board(cetris_ui *ui) { ui->board.x_offset + (j + ui->board.game.current.pos.x) * ui->board.block_width; - GLfloat block_y = + GLfloat ghost_y = ui->board.y_offset + - (s + ui->board.game.current.pos.y - ui->board.block_offset) + (s + ui->board.game.current.ghost_y - ui->board.block_offset) * ui->board.block_height; - set_block_texture(&ui->skin.block, ui->board.game.current.t); - update_rect(&ui->skin.block, block_x, block_y, - ui->board.block_width, ui->board.block_height); + set_block_texture(&ui->board.skin.block, ui->board.game.current.t + 7); + update_rect(&ui->board.skin.block, block_x, ghost_y, + ui->board.block_width, ui->board.block_height, + ui->window_width, ui->window_height); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - GLfloat ghost_y = + if (s + ui->board.game.current.pos.y < ui->board.block_offset - 1) continue; + + GLfloat block_y = ui->board.y_offset + - (s + ui->board.game.current.ghost_y - ui->board.block_offset) + (s + ui->board.game.current.pos.y - ui->board.block_offset) * ui->board.block_height; - set_block_texture(&ui->skin.block, ui->board.game.current.t + 7); - update_rect(&ui->skin.block, block_x, ghost_y, - ui->board.block_width, ui->board.block_height); + set_block_texture(&ui->board.skin.block, ui->board.game.current.t); + update_rect(&ui->board.skin.block, block_x, block_y, + ui->board.block_width, ui->board.block_height, + ui->window_width, ui->window_height); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); } @@ -82,4 +120,44 @@ void draw_tetris_board(cetris_ui *ui) { } glBindTexture(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_2D, ui->board.skin.border.texture); + glBindVertexArray(ui->board.skin.border.vao); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + + glBindTexture(GL_TEXTURE_2D, 0); +} + +void draw_held_piece(cetris_ui *ui) { + if (!ui->board.game.piece_held) return; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_2D, ui->board.skin.block.texture); + glBindVertexArray(ui->board.skin.block.vao); + + for (int s = 0; s < 4; s++) { + for (int j = 0; j < 4; j++) { + if ((ui->board.game.held.m[s]>>(3 - j))&1) { + GLfloat block_x = + ui->board.held.x_offset + (j * ui->board.held.block_width); + GLfloat block_y = + ui->board.held.y_offset + (s * ui->board.held.block_height); + + if (ui->board.game.held.t == MINO_O) { + block_x -= ui->board.held.block_width / 1.5f; + } + if (ui->board.game.held.t == MINO_I) { + block_x -= ui->board.held.block_width / 1.5f; + } + + set_block_texture(&ui->board.skin.block, ui->board.game.held.t); + update_rect(&ui->board.skin.block, block_x, block_y, + ui->board.held.block_width, ui->board.held.block_height, + ui->window_width, ui->window_height); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + } + } + } + glBindTexture(GL_TEXTURE_2D, 0); } diff --git a/frontends/gl/ui.h b/frontends/gl/ui.h index 4b5a94f..6b7e93e 100644 --- a/frontends/gl/ui.h +++ b/frontends/gl/ui.h @@ -3,6 +3,15 @@ #include "drawable.h" #include "skin.h" +#include "audio.h" + +typedef struct { + GLfloat block_width; + GLfloat block_height; + + GLfloat x_offset; + GLfloat y_offset; +} held_piece_t; typedef struct { GLfloat block_width; @@ -13,7 +22,10 @@ typedef struct { GLfloat y_offset; cetris_game game; - cetris_config config; + + held_piece_t held; + + cetris_skin_t skin; } tetris_board_t; typedef struct { @@ -28,16 +40,23 @@ typedef struct { } key_bindings_t; typedef struct { + GLfloat window_height; + GLfloat window_width; + + SDL_AudioDeviceID audio_device; + key_bindings_t keys; char* skin_name; - cetris_skin_t skin; tetris_board_t board; GLuint shader_program; + } cetris_ui; void draw_tetris_board(cetris_ui *ui); +void draw_held_piece(cetris_ui *ui); void draw_current(cetris_ui *ui); -void load_tetris_board(tetris_board_t *board, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +void load_tetris_board(cetris_ui *ui, tetris_board_t *board, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +void load_held_piece(cetris_ui *ui, tetris_board_t *board, GLfloat x, GLfloat y, GLfloat w, GLfloat h); |