Banjo API 1.0.0-rc.2
Low-level C99 game development API
Loading...
Searching...
No Matches
drawing_2d.c
Go to the documentation of this file.
1
105
106#include <banjo/app.h>
107#include <banjo/bitmap.h>
108#include <banjo/draw.h>
109#include <banjo/event.h>
110#include <banjo/log.h>
111#include <banjo/main.h>
112#include <banjo/pixel.h>
113#include <banjo/system.h>
114#include <banjo/window.h>
115
117
118// The scene is composed at a fixed internal resolution: every draw call below
119// is sized for a 500x500 area. The window itself is resizable, so we render
120// the scene once into this off-screen canvas and scale that onto the
121// framebuffer each frame, rather than drawing straight into a framebuffer
122// whose size changes (which would push the fixed coordinates out of bounds).
123enum { CANVAS_W = 500, CANVAS_H = 500 };
124static bj_bitmap* canvas = 0;
125
126static void on_draw(
127 struct bj_window* w,
128 struct bj_render_target* target,
129 const struct bj_rect* dirty,
130 void* user_data
131);
132
133void draw(bj_bitmap* bmp) {
134 // Clear the bitmap to black before drawing.
135 bj_clear_bitmap(bmp);
136
137 // Create colours in the bitmap's native pixel format. Always use
138 // bj_make_bitmap_pixel() rather than hardcoding values, as the format
139 // varies by platform and configuration.
140 const uint32_t color_red = bj_make_bitmap_pixel(bmp, 0xFF, 0x00, 0x00);
141 const uint32_t color_cyan = bj_make_bitmap_pixel(bmp, 0x7F, 0xFF, 0xD4);
142 const uint32_t color_white = bj_make_bitmap_pixel(bmp, 0xFF, 0xFF, 0xFF);
143
144 // Draw individual pixels. bj_put_pixel() sets a single pixel at (x, y).
145 // This is the most basic drawing operation.
146 for (size_t x = 10; x < 490; ++x) {
147 if (x % 7 == 0) {
148 bj_put_pixel(bmp, x, 10, color_red);
149 }
150 }
151
152 // Draw a polyline (connected line segments). The last parameter (BJ_TRUE)
153 // closes the shape by connecting the last point back to the first.
154 // This draws a banjo outline.
155 int poly_x[] = { 100, 95, 95, 100, 100, 95, 75, 75, 95, 120, 140, 140, 120, 115, 115, 120, 120, 115, };
156 int poly_y[] = { 20, 25, 50, 55, 100, 100, 120, 145, 165, 165, 145, 120, 100, 100, 55, 50, 25, 20, };
157 bj_draw_polyline(bmp, 18, poly_x, poly_y, BJ_TRUE, color_cyan);
158
159 // Draw outlined triangles by indexing into a vertex array. This technique
160 // is common in graphics programming and efficiently reuses vertex data.
161 // Here we draw 13 triangles forming a fox shape.
162 int verts[][2] = {
163 {330, 270}, {270, 210}, {210, 270}, {210, 150}, {390, 210}, {450, 270},
164 {450, 150}, {180, 330}, {270, 390}, {390, 390}, {480, 330}, {330, 450},
165 {300, 480}, {360, 480},
166 };
167
168 size_t tris[13][3] = {
169 {0, 1, 2}, {0, 2, 3}, {0, 4, 5}, {0, 1, 4}, {4, 6, 5}, {2, 8, 7},
170 {0, 8, 2}, {0, 5, 9}, {9, 5, 10}, {8, 9, 11}, {8, 11, 12},
171 {9, 13, 11}, {11, 12, 13},
172 };
173
174 for (size_t t = 0; t < 13; ++t) {
176 verts[tris[t][0]][0], verts[tris[t][0]][1],
177 verts[tris[t][1]][0], verts[tris[t][1]][1],
178 verts[tris[t][2]][0], verts[tris[t][2]][1],
179 color_white
180 );
181 }
182
183 // Draw a checkerboard pattern using filled rectangles. The bj_rect
184 // structure defines a rectangle's position and size.
185 bj_rect board = {.w = 10, .h = 10,};
186 for(size_t y = 0 ; y < 8 ; ++y) {
187 for(size_t x = 0 ; x < 8 ; ++x) {
188 board.x = 200 + x * board.w;
189 board.y = 50 + y * board.h;
190 // XOR determines checkerboard pattern (alternating squares).
191 if((x ^ y) & 1) {
192 bj_draw_filled_rectangle(bmp, &board, color_red);
193 }
194 }
195 }
196 // Draw an outline around the entire checkerboard. Note the difference
197 // between bj_draw_rectangle (outline) and bj_draw_filled_rectangle (solid).
199 &(bj_rect) {.x = 200, .y = 50, .w = 80, .h = 80,},
200 color_cyan
201 );
202
203 // Draw concentric circles with alternating colours. bj_draw_filled_circle()
204 // takes centre (x, y), radius, and colour.
205 for (int r = 80; r > 0; r -= 20) {
206 bj_draw_filled_circle(bmp, 100, 400, r, (r/20) % 2 ? color_red : color_white);
207 }
208
209 // Draw filled triangles for a simple mountain scene. Filled triangles are
210 // drawn with bj_draw_filled_triangle(), taking three vertices and a colour.
211 const uint32_t color_dark_gray = bj_make_bitmap_pixel(bmp, 0x50, 0x50, 0x50);
212 const uint32_t color_gray = bj_make_bitmap_pixel(bmp, 0x80, 0x80, 0x80);
213 const uint32_t color_light_gray = bj_make_bitmap_pixel(bmp, 0xB0, 0xB0, 0xB0);
214
215 bj_draw_filled_triangle(bmp, 250, 400, 200, 480, 300, 480, color_gray);
216 bj_draw_filled_triangle(bmp, 300, 420, 250, 480, 350, 480, color_dark_gray);
217 bj_draw_filled_triangle(bmp, 350, 390, 300, 480, 400, 480, color_light_gray);
218}
219
220// Static drawing: banjo asks, we present. The scene was rendered into the
221// canvas once in setup; here we just scale that fixed 500x500 image onto the
222// window's framebuffer at whatever size the window currently is. Passing 0
223// for both areas means "whole source -> whole destination", and
224// bj_blit_stretched clips to the destination, so this is always in bounds no
225// matter how the window is resized.
226static void on_draw(
227 struct bj_window* w,
228 struct bj_render_target* target,
229 const struct bj_rect* dirty,
230 void* user_data
231) {
232 (void)w; (void)dirty; (void)user_data;
234}
235
236static void* setup(struct bj_app* app, void* init_data) {
237 (void)init_data;
238
239 if (!bj_begin(BJ_VIDEO_SYSTEM, 0)) {
240 bj_quit_app(app, 1);
241 return 0;
242 }
243
244 // Fixed-resolution canvas: the scene is static, so render it once here.
245 // on_draw then only scales it onto the framebuffer.
247 if (canvas == 0) {
248 bj_quit_app(app, 1);
249 return 0;
250 }
251 draw(canvas);
252
253 window = bj_bind_window("2D Drawing", 100, 100, CANVAS_W, CANVAS_H,
255
259 return 0;
260}
261
262static void step(struct bj_app* app, struct bj_tick_info tick, void* user_data) {
263 (void)tick;
264 (void)user_data;
266
268 bj_quit_app(app, 0);
269 }
270}
271
272static void teardown(struct bj_app* app, void* user_data) {
273 (void)user_data;
276 bj_end();
277}
278
279int main(int argc, char* argv[]) {
280 (void)argc; (void)argv;
281 return bj_run_app(setup, step, 0, teardown, 0);
282}
Application lifecycle: callback-driven setup, step, and teardown.
int main(int argc, char *argv[])
Definition audio_pcm.c:177
static void step(struct bj_app *app, struct bj_tick_info tick, void *user_data)
Definition audio_pcm.c:144
static void teardown(struct bj_app *app, void *user_data)
Definition audio_pcm.c:170
static void * setup(struct bj_app *app, void *init_data)
Definition audio_pcm.c:107
Header file for Bitmap type.
static void on_draw(struct bj_window *w, struct bj_render_target *target, const struct bj_rect *dirty, void *user_data)
Definition bitmap_blit.c:32
bj_window * window
Definition bitmap_blit.c:24
Header file for Bitmap drawing functions.
static bj_bitmap * canvas
Definition drawing_2d.c:124
void draw(bj_bitmap *bmp)
Definition drawing_2d.c:133
Sytem event management API.
int bj_run_app(bj_app_setup_fn setup, bj_app_step_fn step, bj_app_fixed_step_fn fixed_step, bj_app_teardown_fn teardown, void *init_data)
Drive the application lifecycle.
void bj_quit_app(struct bj_app *app, int exit_code)
Signal the given application to exit on the next iteration.
Timing snapshot handed to the step and fixed-step callbacks.
Definition app.h:106
void bj_clear_bitmap(struct bj_bitmap *bitmap)
Fills the entire bitmap with the clear colour.
bj_bool bj_blit_stretched(const struct bj_bitmap *src, const struct bj_rect *src_area, struct bj_bitmap *dst, const struct bj_rect *dst_area, enum bj_blit_op op)
Stretched bitmap blitting (nearest neighbor).
uint32_t bj_make_bitmap_pixel(struct bj_bitmap *bitmap, uint8_t red, uint8_t green, uint8_t blue)
Returns an opaque value representing a pixel colour, given its RGB composition.
struct bj_bitmap * bj_create_bitmap(size_t width, size_t height, enum bj_pixel_mode mode, size_t stride)
Creates a new struct bj_bitmap with the specified width and height.
void bj_put_pixel(struct bj_bitmap *bitmap, size_t x, size_t y, uint32_t value)
Change the pixel colour at given coordinate.
void bj_destroy_bitmap(struct bj_bitmap *bitmap)
Deletes a struct bj_bitmap object and releases associated memory.
@ BJ_BLIT_OP_COPY
Copy source to destination (fast path when formats match)
Definition bitmap.h:93
struct bj_render_target bj_render_target
Definition api.h:346
struct bj_bitmap bj_bitmap
Definition api.h:328
struct bj_window bj_window
Definition api.h:354
#define BJ_TRUE
Boolean true value (1).
Definition api.h:275
void bj_draw_rectangle(struct bj_bitmap *bitmap, const struct bj_rect *area, uint32_t pixel)
Draws a rectangle in the given bitmap.
void bj_draw_polyline(struct bj_bitmap *bitmap, size_t count, const int *x, const int *y, bj_bool loop, uint32_t color)
Draw a polyline from C-style coordinate arrays.
void bj_draw_triangle(struct bj_bitmap *bitmap, int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color)
Draws the edges of a triangle given its 3 corners.
void bj_draw_filled_rectangle(struct bj_bitmap *bitmap, const struct bj_rect *area, uint32_t pixel)
Draws a filled rectangle in the given bitmap.
void bj_draw_filled_circle(struct bj_bitmap *bitmap, int cx, int cy, int radius, uint32_t color)
Draw a filled circle onto a bitmap.
void bj_draw_filled_triangle(struct bj_bitmap *bitmap, int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color)
Draws a filled triangle given its 3 corners.
void bj_dispatch_events(void)
Poll and dispatch all pending events.
void bj_close_on_escape(struct bj_window *window, const struct bj_key_event *event, void *user_data)
Handle the ESC key to close a window.
bj_key_callback_fn bj_set_key_callback(bj_key_callback_fn callback, void *user_data)
Set the global callback for keyboard key events.
uint16_t w
Width in pixels.
Definition rect.h:36
uint16_t h
Height in pixels.
Definition rect.h:37
int16_t y
Y coordinate of the top-left corner (pixels, can be negative).
Definition rect.h:35
int16_t x
X coordinate of the top-left corner (pixels, can be negative).
Definition rect.h:34
Axis-aligned rectangle: a top-left corner plus a width and height.
Definition rect.h:33
@ BJ_PIXEL_MODE_XRGB8888
32bpp RGB
Definition pixel.h:94
bj_bool bj_begin(int systems, struct bj_error **error)
Initialises the system.
void bj_end(void)
De-initialises the system.
@ BJ_VIDEO_SYSTEM
Definition system.h:81
void bj_set_draw_callback(struct bj_window *window, bj_window_draw_fn fn, void *user_data)
Register the redraw callback for window.
static void bj_invalidate_window(struct bj_window *window)
Mark the whole window as needing a repaint.
Definition window.h:470
struct bj_window * bj_bind_window(const char *title, uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t flags, struct bj_error **error)
Create a new struct bj_window with the specified attributes.
struct bj_bitmap * bj_render_target_bitmap(struct bj_render_target *target)
Reach the software framebuffer behind a render target.
bj_bool bj_should_close_window(struct bj_window *window)
Get the close flag state of a window.
void bj_unbind_window(struct bj_window *window)
Deletes a struct bj_window object and releases associated memory.
@ BJ_WINDOW_FLAG_RESIZABLE
User may resize the window.
Definition window.h:190
Logging utility functions.
Portable main() replacement with platform-aware entry shim.
Header file for general pixel manipulation facilities.
#define CANVAS_W
Definition shaders.c:26
#define CANVAS_H
Definition shaders.c:27
Header file for system interactions.
Header file for bj_window type.