summaryrefslogtreecommitdiff
path: root/frontends
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2019-11-01 18:31:14 -0400
committerAndrew Opalach <andrew@akon.city> 2019-11-01 18:31:14 -0400
commit9f4130dde0a0ea9a036fccdbb30ae2644daae9a4 (patch)
tree29e1a6ee56532a83e16086490e2e5d96c3c78954 /frontends
parenteabc92f014041d8dc546bcc6024fe4aaf20611eb (diff)
downloadcetris-9f4130dde0a0ea9a036fccdbb30ae2644daae9a4.tar.gz
cetris-9f4130dde0a0ea9a036fccdbb30ae2644daae9a4.tar.bz2
cetris-9f4130dde0a0ea9a036fccdbb30ae2644daae9a4.zip
add all the skining elements to opengl frontend
Diffstat (limited to 'frontends')
-rw-r--r--frontends/gl/audio.c35
-rw-r--r--frontends/gl/audio.h18
-rw-r--r--frontends/gl/drawable.c26
-rw-r--r--frontends/gl/drawable.h3
-rw-r--r--frontends/gl/main.c136
-rw-r--r--frontends/gl/meson.build2
-rw-r--r--frontends/gl/skin.c52
-rw-r--r--frontends/gl/skin.h10
-rw-r--r--frontends/gl/ui.c134
-rw-r--r--frontends/gl/ui.h25
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);