diff options
| -rw-r--r-- | Makefile | 5 | ||||
| -rw-r--r-- | counter.c | 60 | ||||
| -rw-r--r-- | counter.h | 10 | ||||
| -rw-r--r-- | digits.h | 129 | ||||
| -rw-r--r-- | main.c | 1 | ||||
| -rw-r--r-- | world.c | 56 | ||||
| -rw-r--r-- | world.h | 1 |
7 files changed, 254 insertions, 8 deletions
@@ -3,13 +3,14 @@ SDL_HEADERS=/usr/include/SDL2 CFLAGS=-g -Wall -pedantic -std=c99 $$(sdl2-config --cflags) LFLAGS=$$(sdl2-config --libs) -findgame: main.o world.o random.o generator.o save.o die.o +findgame: main.o world.o random.o generator.o save.o counter.o die.o $(CC) -o $@ $^ $(LFLAGS) main.o: world.h random.h save.h -world.o: world.h random.h generator.h save.h +world.o: world.h random.h generator.h save.h counter.h generator.o: world.h random.h save.o: world.h die.h +counter.o: digits.h .SUFFIXES: .c .o .c.o: diff --git a/counter.c b/counter.c new file mode 100644 index 0000000..5a9913c --- /dev/null +++ b/counter.c @@ -0,0 +1,60 @@ +#include <SDL.h> + +#include "digits.h" + +static SDL_Texture *get_font(SDL_Renderer *rend) { + static SDL_Texture *font = NULL; + if (!font) { + font = SDL_CreateTexture(rend, + SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, + FONT_WIDTH, sizeof(digits) / FONT_WIDTH); + SDL_SetTextureBlendMode(font, SDL_BLENDMODE_BLEND); + SDL_assert(font); + + int pitch; + void *out; + SDL_assert(SDL_LockTexture(font, NULL, &out, &pitch) >= 0); + SDL_Color *pixels = out; + + for (int i = 0; i < sizeof(digits); i++) { + pixels[i] = + (SDL_Color) {0xFF, 0xFF, 0xFF, digits[i] ? 0xFF : 0x00}; + } + + SDL_UnlockTexture(font); + } + return font; +} + +int draw_counter(SDL_Renderer *rend, + SDL_Point screen_pos, double size, SDL_Color color, + int number, int digits) { + double scale = size / FONT_HEIGHT; + + SDL_Texture *font = get_font(rend); + SDL_SetTextureColorMod(font, color.r, color.g, color.b); + + if (digits == 0) { + for (int n = number; n > 0; n /= DIGIT_BASE) + digits += 1; + digits = SDL_max(digits, 1); + } + + int n = number; + for (int i = digits - 1; i >= 0; i--) { + int digit = n % DIGIT_BASE; + + int width = SDL_round((double) FONT_WIDTH * scale); + int height = SDL_round((double) FONT_HEIGHT * scale); + int offset = SDL_round((double) FONT_WIDTH * scale * (double) i); + SDL_Rect draw = {screen_pos.x + offset, screen_pos.y, width, height}; + SDL_Rect digit_rect = { + 0, FONT_HEIGHT * digit, FONT_WIDTH, FONT_HEIGHT, + }; + SDL_RenderCopy(rend, font, &digit_rect, &draw); + + n /= DIGIT_BASE; + } + + return SDL_round((double) FONT_WIDTH * scale * (double) digits); +} diff --git a/counter.h b/counter.h new file mode 100644 index 0000000..7dcb97c --- /dev/null +++ b/counter.h @@ -0,0 +1,10 @@ +#ifndef COUNTER_H +#define COUNTER_H + +#include <SDL.h> + +int draw_counter(SDL_Renderer *rend, + SDL_Point screen_pos, double size, SDL_Color color, + int number, int digits); + +#endif diff --git a/digits.h b/digits.h new file mode 100644 index 0000000..a1d5466 --- /dev/null +++ b/digits.h @@ -0,0 +1,129 @@ +#ifndef DIGITS_H +#define DIGITS_H + +#include <SDL.h> + +static const Uint8 digits[] = { + 0, 1, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + + 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + + 0, 1, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + + 0, 1, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + + 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + + 0, 1, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + + 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + + 0, 1, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 0, 1, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + + 0, 1, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 0, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + + 0, 1, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, + 1, 1, 0, 1, 1, 0, + 0, 1, 1, 1, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 1, 1, 1, 0, 0, + 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + + 1, 1, 1, 1, 1, 0, + 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +}; + +#define FONT_WIDTH 6 +#define FONT_HEIGHT 8 +#define DIGIT_BASE 12 + +#endif @@ -86,6 +86,7 @@ int main(int argc, char *argv[]) { "error creating renderer: %s", SDL_GetError()); return 1; } + SDL_SetRenderDrawBlendMode(rend, SDL_BLENDMODE_BLEND); init_world(&game); while (run()); @@ -4,6 +4,7 @@ #include "random.h" #include "generator.h" #include "save.h" +#include "counter.h" SDL_Color tile_colors[] = { [TILE_RED] = {0xFF, 0x00, 0x00, 0xFF}, @@ -12,6 +13,7 @@ SDL_Color tile_colors[] = { [TILE_LIGHT] = {0xFF, 0xFF, 0xFF, 0xFF}, [TILE_EMPTY] = {0x00, 0x00, 0x00, 0xFF}, [TILE_WALL] = {0x50, 0x50, 0x50, 0xFF}, + [TILE_BLOCK_WHITE] = {0x80, 0x80, 0x80, 0xFF}, }; chunk *get_chunk(world *w, SDL_Point chunk_pos) { @@ -106,7 +108,13 @@ void set_tile(world *w, SDL_Point world_pos, tile t) { } SDL_bool is_solid(tile t) { - return t == TILE_WALL; + switch (t) { + case TILE_WALL: + case TILE_BLOCK_WHITE: + return SDL_TRUE; + default: + return SDL_FALSE; + } } SDL_bool player_grounded(world *w) { @@ -160,11 +168,11 @@ void player_place(world *w, int x, int y) { SDL_Point place = {w->player.pos.x + x, w->player.pos.y + y}; if (!is_solid(get_tile(w, place))) { player_collect(w, place); - set_tile(w, place, TILE_WALL); + set_tile(w, place, TILE_BLOCK_WHITE); } else { SDL_Point push = {w->player.pos.x - x, w->player.pos.y - y}; if (!is_solid(get_tile(w, push))) { - set_tile(w, w->player.pos, TILE_WALL); + set_tile(w, w->player.pos, TILE_BLOCK_WHITE); w->player.pos = push; } } @@ -190,7 +198,7 @@ void player_destroy(world *w, int x, int y) { } } -void draw_world(world *w, SDL_Window *win, SDL_Renderer *rend) { +static double get_view_scale(SDL_Window *win) { int sw, sh; SDL_GetWindowSize(win, &sw, &sh); @@ -200,6 +208,40 @@ void draw_world(world *w, SDL_Window *win, SDL_Renderer *rend) { else view_scale = (double) sw / (double) VIEW_DIM; + return view_scale; +} + +static void draw_ui(world *w, SDL_Window *win, SDL_Renderer *rend) { + int sw, sh; + SDL_GetWindowSize(win, &sw, &sh); + double view_scale = get_view_scale(win); + + double bar_size = 1.5; + double padding = 0.16; + + SDL_Rect bar = { + 0, sh - view_scale * (bar_size + padding), sw, view_scale * 3, + }; + SDL_SetRenderDrawColor(rend, 0x00, 0x00, 0x00, 0xFF); + SDL_RenderFillRect(rend, &bar); + + int x = view_scale * padding; + for (int i = 0; i < MAX_COLLECTIBLE; i++) { + int score = w->player.scores[i]; + SDL_Color grey = {0x20, 0x20, 0x10, 0xFF}; + SDL_Color collectible_color = tile_colors[i]; + SDL_Color color = score > 0 ? collectible_color : grey; + SDL_Point pos = {x, bar.y + view_scale * padding}; + x += draw_counter(rend, pos, view_scale * bar_size, color, score, 3); + x += view_scale * 1; + } +} + +void draw_world(world *w, SDL_Window *win, SDL_Renderer *rend) { + int sw, sh; + SDL_GetWindowSize(win, &sw, &sh); + double view_scale = get_view_scale(win); + double view_width = (double) sw / view_scale; double view_height = (double) sh / view_scale; double view_x = w->view_pos.x - view_width / 2; @@ -221,8 +263,8 @@ void draw_world(world *w, SDL_Window *win, SDL_Renderer *rend) { SDL_Point min = chunk_pos_at((SDL_Point) {view_x, view_y}); SDL_Point max = chunk_pos_at( (SDL_Point) {view_x + view_width, view_y + view_height}); - for (int y = min.y; y <= max.y; y++) { - for (int x = min.x; x <= max.x; x++) { + for (int y = min.y - 1; y <= max.y; y++) { + for (int x = min.x - 1; x <= max.x; x++) { chunk *c = load_chunk(w, (SDL_Point) {x, y}); if (!c) continue; SDL_Texture *tex = render_chunk(rend, c); @@ -247,6 +289,8 @@ void draw_world(world *w, SDL_Window *win, SDL_Renderer *rend) { }; SDL_SetRenderDrawColor(rend, 0xFF, 0x00, 0xFF, 0xFF); SDL_RenderFillRect(rend, &player_rect); + + draw_ui(w, win, rend); } void tick_world(world *w) { @@ -14,6 +14,7 @@ typedef enum tile { TILE_EMPTY, TILE_WALL, + TILE_BLOCK_WHITE, } tile; extern SDL_Color tile_colors[]; |
