-
Notifications
You must be signed in to change notification settings - Fork 0
Core Concepts
Understanding these concepts will help you build better games with BlitEngine.
Every game runs in a continuous loop:
while (blit_is_running(&engine)) {
// 1. INPUT - Read what the player is doing
blit_update_input(&engine);
// 2. UPDATE - Process game logic
update_physics();
check_collisions();
update_ai();
// 3. RENDER - Draw everything
blit_begin_frame(&engine, 0xFF000000);
draw_background();
draw_game_objects();
draw_ui();
blit_end_frame(&engine);
}This runs as fast as possible (typically 60+ times per second).
Sprites are images you can draw on screen. Think of them as textures or pictures.
// Solid color rectangle
Sprite *red_box = blit_sprite_create_color(&engine, 32, 32, 0xFFFF0000);
// Circle
Sprite *blue_ball = blit_sprite_create_circle(&engine, 16, 0xFF0000FF);
// From pixel data
uint32_t pixels[64 * 64];
// ... fill pixels array ...
Sprite *custom = blit_sprite_create(&engine, 64, 64, pixels);// Draw at position (100, 200)
blit_sprite_draw(&engine, my_sprite, 100, 200);
// Draw multiple times (efficient!)
for (int i = 0; i < 10; i++) {
blit_sprite_draw(&engine, coin_sprite, i * 50, 100);
}// 1. Create (once at startup)
Sprite *player_sprite = blit_sprite_create_color(&engine, 32, 32, 0xFF00FF00);
// 2. Use (every frame)
while (blit_is_running(&engine)) {
blit_sprite_draw(&engine, player_sprite, x, y);
}
// 3. Free (at shutdown)
blit_sprite_free(&engine, player_sprite);Important: Create sprites once, not every frame!
Entities are game objects with position, velocity, and optional sprite.
Entities bundle together:
- Position (x, y)
- Velocity (vx, vy)
- Size (width, height)
- Visual (sprite)
- State (active/inactive)
- Custom data (user_data)
This makes game object management much easier!
// Create sprite first
Sprite *player_sprite = blit_sprite_create_color(&engine, 32, 32, 0xFF00FF00);
// Create entity
Entity *player = blit_entity_create(
100, 100, // x, y position
32, 32, // width, height (for collision)
player_sprite // visual appearance
);
// Set velocity
player->vx = 5; // Moves 5 pixels right per update
player->vy = -2; // Moves 2 pixels up per update// Manual update
blit_entity_update(player); // Adds vx to x, vy to y
// Or do it yourself
player->x += player->vx;
player->y += player->vy;blit_entity_draw(&engine, player);Managing multiple entities:
#define MAX_ENEMIES 20
Entity *enemies[MAX_ENEMIES];
// Initialize
for (int i = 0; i < MAX_ENEMIES; i++) {
enemies[i] = blit_entity_create(
blit_random_int(0, 800),
blit_random_int(0, 600),
24, 24,
enemy_sprite
);
enemies[i]->vy = 2; // Fall downward
}
// Update all
for (int i = 0; i < MAX_ENEMIES; i++) {
if (enemies[i]->active) {
blit_entity_update(enemies[i]);
}
}
// Draw all
for (int i = 0; i < MAX_ENEMIES; i++) {
if (enemies[i]->active) {
blit_entity_draw(&engine, enemies[i]);
}
}// Check if on screen
if (blit_entity_on_screen(&engine, entity)) {
blit_entity_draw(&engine, entity);
}
// Keep entity in bounds
blit_entity_clamp_to_screen(&engine, player);
// Collision detection
if (blit_entity_collides(player, enemy)) {
printf("Hit!\n");
}Store game-specific data:
typedef struct {
int health;
int ammo;
int score;
} PlayerData;
// Create and attach
PlayerData *data = malloc(sizeof(PlayerData));
data->health = 100;
data->ammo = 50;
player->user_data = data;
// Access later
PlayerData *pd = (PlayerData*)player->user_data;
pd->health -= 10;BlitEngine handles input automatically.
// Check if key is currently held down
if (blit_key_down(&engine, KEY_W)) {
player_y -= speed; // Continuous movement
}
// Check if key was just pressed (one-shot)
if (blit_key_pressed(&engine, KEY_SPACE)) {
fire_weapon(); // Fires once per press
}Common Keys:
KEY_W, KEY_A, KEY_S, KEY_D // WASD
KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT
KEY_SPACE, KEY_ENTER, KEY_ESC
KEY_1, KEY_2, KEY_3 ... KEY_0// Get position
int mx = engine.input.mouse_x;
int my = engine.input.mouse_y;
// Check buttons (held)
if (blit_mouse_down(&engine, MOUSE_LEFT)) {
printf("Dragging...\n");
}
// Check buttons (clicked)
if (blit_mouse_clicked(&engine, MOUSE_LEFT)) {
printf("Just clicked!\n");
}Mouse Buttons:
MOUSE_LEFT // Left button (bit 1)
MOUSE_RIGHT // Right button (bit 2)
MOUSE_MIDDLE // Middle button (bit 4)Movement:
// Smooth 8-direction movement
if (blit_key_down(&engine, KEY_W)) player->vy = -3;
if (blit_key_down(&engine, KEY_S)) player->vy = 3;
if (blit_key_down(&engine, KEY_A)) player->vx = -3;
if (blit_key_down(&engine, KEY_D)) player->vx = 3;
// Apply friction when no keys pressed
if (!blit_key_down(&engine, KEY_A) && !blit_key_down(&engine, KEY_D)) {
player->vx *= 0.9;
}Button Actions:
// Prevent rapid-fire with key_pressed (not key_down)
if (blit_key_pressed(&engine, KEY_SPACE)) {
fire_bullet(); // Only fires when key first pressed
}Mouse Targeting:
// Point entity toward mouse
int dx = engine.input.mouse_x - player->x;
int dy = engine.input.mouse_y - player->y;
float angle = atan2(dy, dx); // Calculate angleCheck if two rectangles overlap:
if (blit_rects_overlap(
player_x, player_y, player_w, player_h,
enemy_x, enemy_y, enemy_w, enemy_h
)) {
printf("Collision!\n");
}if (blit_entity_collides(player, enemy)) {
// Handle collision
player->health -= 10;
enemy->active = 0;
}Check if a point is inside a rectangle:
// Is mouse over button?
if (blit_point_in_rect(mx, my, button_x, button_y, button_w, button_h)) {
// Highlight button
if (blit_mouse_clicked(&engine, MOUSE_LEFT)) {
// Button clicked!
}
}Bounce:
if (ball_x < 0 || ball_x > screen_width) {
ball_vx = -ball_vx; // Reverse horizontal velocity
}
if (ball_y < 0 || ball_y > screen_height) {
ball_vy = -ball_vy; // Reverse vertical velocity
}Wrap Around:
if (player_x > screen_width) player_x = 0;
if (player_x < 0) player_x = screen_width;Stop at Boundary:
if (player_x < 0) {
player_x = 0;
player_vx = 0;
}// Random integer (inclusive)
int dice = blit_random_int(1, 6); // 1, 2, 3, 4, 5, or 6
int spawn_x = blit_random_int(0, 800); // 0 to 800
// Random float (0.0 to 1.0)
float chance = blit_random_float();
if (chance < 0.1) { // 10% chance
spawn_powerup();
}// Manhattan distance (fast approximation)
float dist = blit_distance(x1, y1, x2, y2);
// Check if entities are close
if (blit_distance(player->x, player->y, enemy->x, enemy->y) < 50) {
printf("Enemy nearby!\n");
}Keep values in range:
// Health between 0 and 100
health = blit_clamp(health, 0, 100);
// Speed limit
speed = blit_clamp(speed, -5, 5);// Rectangle (filled)
blit_draw_rect(&engine, x, y, width, height, color);
// Rectangle (outline)
blit_draw_rect_outline(&engine, x, y, width, height, color, thickness);
// Circle (filled)
blit_draw_circle(&engine, center_x, center_y, radius, color);
// Line
blit_draw_line(&engine, x0, y0, x1, y1, color, thickness);// Simple text (each character is a small rectangle)
blit_draw_text(&engine, "Score: 100", 10, 10, 0xFFFFFFFF);
// Dynamic text
char message[64];
snprintf(message, sizeof(message), "Health: %d / 100", player_health);
blit_draw_text(&engine, message, 10, 30, 0xFFFF0000);// GOOD - Create once
Sprite *bullet = blit_sprite_create_circle(&engine, 4, 0xFFFFFF00);
for (int frame = 0; frame < 1000; frame++) {
blit_sprite_draw(&engine, bullet, x, y);
}
// BAD - Creates 1000 sprites!
for (int frame = 0; frame < 1000; frame++) {
Sprite *bullet = blit_sprite_create_circle(&engine, 4, 0xFFFFFF00);
blit_sprite_draw(&engine, bullet, x, y);
blit_sprite_free(&engine, bullet);
}for (int i = 0; i < MAX_ENTITIES; i++) {
if (!entities[i]->active) continue; // Skip early
blit_entity_update(entities[i]);
blit_entity_draw(&engine, entities[i]);
}if (blit_entity_on_screen(&engine, entity)) {
blit_entity_draw(&engine, entity); // Only draw visible ones
}- Tutorial: Catch the Stars - Build your first complete game
- Using Entities - Advanced entity patterns
- Example Games - Study working games
- API Reference - Complete function list
Now you understand BlitEngine's core! Let's make games! 🎮