Skip to content

Simple Examples

NtinosTheGamer2324 edited this page Mar 7, 2026 · 1 revision

Simple NodGL Examples

Complete, working programs you can learn from!

Example 1: Bouncing DVD Logo

#include "NodGL.h"
#include "libc.h"

int md_main(long argc, char **argv) {
    NodGL_Device device;
    NodGL_Context ctx;
    NodGL_CreateDevice(NodGL_FEATURE_LEVEL_1_0, &device, &ctx, NULL);
    
    uint32_t screen_w, screen_h;
    NodGL_GetScreenResolution(device, &screen_w, &screen_h);
    
    int x = 100, y = 100;
    int dx = 3, dy = 2;
    uint32_t color = 0xFFFF0000;
    
    while (1) {
        // Move
        x += dx;
        y += dy;
        
        // Bounce and change color
        if (x <= 0 || x >= screen_w - 64) {
            dx = -dx;
            color = 0xFF000000 | (rand() & 0xFFFFFF);
        }
        if (y <= 0 || y >= screen_h - 32) {
            dy = -dy;
            color = 0xFF000000 | (rand() & 0xFFFFFF);
        }
        
        // Draw
        NodGL_ClearContext(ctx, NodGL_CLEAR_COLOR, 0xFF000000, 1.0f, 0);
        NodGL_FillRectContext(ctx, x, y, 64, 32, color);
        NodGL_PresentContext(ctx, 1);
        
        for (volatile int i = 0; i < 30000; i++);
    }
    
    NodGL_ReleaseDevice(device);
    return 0;
}

Example 2: Rainbow Bars

#include "NodGL.h"
#include "libc.h"

int md_main(long argc, char **argv) {
    NodGL_Device device;
    NodGL_Context ctx;
    NodGL_CreateDevice(NodGL_FEATURE_LEVEL_1_0, &device, &ctx, NULL);
    
    uint32_t screen_w, screen_h;
    NodGL_GetScreenResolution(device, &screen_w, &screen_h);
    
    uint32_t colors[] = {
        0xFFFF0000,  // Red
        0xFFFF7F00,  // Orange
        0xFFFFFF00,  // Yellow
        0xFF00FF00,  // Green
        0xFF0000FF,  // Blue
        0xFF4B0082,  // Indigo
        0xFF9400D3   // Violet
    };
    
    int bar_height = screen_h / 7;
    
    NodGL_ClearContext(ctx, NodGL_CLEAR_COLOR, 0xFF000000, 1.0f, 0);
    
    for (int i = 0; i < 7; i++) {
        NodGL_FillRectContext(ctx, 0, i * bar_height, screen_w, bar_height, colors[i]);
    }
    
    NodGL_PresentContext(ctx, 1);
    
    // Wait 10 seconds
    for (volatile int i = 0; i < 20000000; i++);
    
    NodGL_ReleaseDevice(device);
    return 0;
}

Example 3: Starfield

#include "NodGL.h"
#include "libc.h"

#define NUM_STARS 100

typedef struct {
    int x, y;
    int speed;
} Star;

int md_main(long argc, char **argv) {
    NodGL_Device device;
    NodGL_Context ctx;
    NodGL_CreateDevice(NodGL_FEATURE_LEVEL_1_0, &device, &ctx, NULL);
    
    uint32_t screen_w, screen_h;
    NodGL_GetScreenResolution(device, &screen_w, &screen_h);
    
    Star stars[NUM_STARS];
    
    // Initialize stars
    for (int i = 0; i < NUM_STARS; i++) {
        stars[i].x = rand() % screen_w;
        stars[i].y = rand() % screen_h;
        stars[i].speed = 1 + (rand() % 3);
    }
    
    for (int frame = 0; frame < 500; frame++) {
        NodGL_ClearContext(ctx, NodGL_CLEAR_COLOR, 0xFF000010, 1.0f, 0);
        
        for (int i = 0; i < NUM_STARS; i++) {
            // Move star
            stars[i].y += stars[i].speed;
            
            // Wrap around
            if (stars[i].y >= screen_h) {
                stars[i].y = 0;
                stars[i].x = rand() % screen_w;
            }
            
            // Brightness based on speed
            uint8_t brightness = 128 + stars[i].speed * 40;
            uint32_t color = NodGL_ColorARGB(255, brightness, brightness, brightness);
            
            // Draw star
            int size = stars[i].speed;
            NodGL_FillRectContext(ctx, stars[i].x, stars[i].y, size, size, color);
        }
        
        NodGL_PresentContext(ctx, 1);
        for (volatile int i = 0; i < 30000; i++);
    }
    
    NodGL_ReleaseDevice(device);
    return 0;
}

Example 4: Click to Draw Circles

#include "NodGL.h"
#include "libc.h"
#include "../include/moduos/kernel/events/events.h"

void draw_circle(NodGL_Context ctx, int cx, int cy, int radius, uint32_t color) {
    for (int y = -radius; y <= radius; y++) {
        for (int x = -radius; x <= radius; x++) {
            if (x * x + y * y <= radius * radius) {
                NodGL_FillRectContext(ctx, cx + x, cy + y, 1, 1, color);
            }
        }
    }
}

int md_main(long argc, char **argv) {
    NodGL_Device device;
    NodGL_Context ctx;
    NodGL_CreateDevice(NodGL_FEATURE_LEVEL_1_0, &device, &ctx, NULL);
    
    uint32_t screen_w, screen_h;
    NodGL_GetScreenResolution(device, &screen_w, &screen_h);
    
    // Create canvas
    NodGL_TextureDesc desc = {screen_w, screen_h, NodGL_FORMAT_R8G8B8A8_UNORM, 1, NULL, 0};
    NodGL_Texture canvas;
    NodGL_CreateTexture(device, &desc, &canvas);
    
    uint32_t *pixels;
    uint32_t pitch;
    NodGL_MapResource(ctx, canvas, (void**)&pixels, &pitch);
    
    // Clear to white
    for (int i = 0; i < screen_h * (pitch / 4); i++) {
        pixels[i] = 0xFFFFFFFF;
    }
    
    int queue_fd = open("/dev/event0", 0);
    int mx = 0, my = 0;
    int prev_buttons = 0;
    
    uint32_t colors[] = {
        0xFFFF0000, 0xFF00FF00, 0xFF0000FF,
        0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF
    };
    int color_index = 0;
    
    while (1) {
        event_t ev;
        int buttons = prev_buttons;
        
        while (read(queue_fd, &ev, sizeof(ev)) == sizeof(ev)) {
            if (ev.type == EVENT_MOUSE_MOVE) {
                mx = ev.mouse.x;
                my = ev.mouse.y;
            }
            if (ev.type == EVENT_MOUSE_BUTTON) {
                buttons = ev.mouse.buttons;
            }
        }
        
        // Detect left click
        if ((buttons & 1) && !(prev_buttons & 1)) {
            // Draw circle on canvas
            int radius = 20 + (rand() % 30);
            uint32_t color = colors[color_index];
            color_index = (color_index + 1) % 6;
            
            for (int dy = -radius; dy <= radius; dy++) {
                for (int dx = -radius; dx <= radius; dx++) {
                    if (dx * dx + dy * dy <= radius * radius) {
                        int px = mx + dx;
                        int py = my + dy;
                        if (px >= 0 && px < screen_w && py >= 0 && py < screen_h) {
                            pixels[py * (pitch / 4) + px] = color;
                        }
                    }
                }
            }
        }
        
        // Right click to clear
        if ((buttons & 2) && !(prev_buttons & 2)) {
            for (int i = 0; i < screen_h * (pitch / 4); i++) {
                pixels[i] = 0xFFFFFFFF;
            }
        }
        
        prev_buttons = buttons;
        
        // Display
        NodGL_ClearContext(ctx, NodGL_CLEAR_COLOR, 0xFF808080, 1.0f, 0);
        NodGL_DrawTexture(ctx, canvas, 0, 0, 0, 0, screen_w, screen_h);
        
        // Draw cursor
        NodGL_FillRectContext(ctx, mx - 3, my - 3, 6, 6, 0xFF000000);
        
        NodGL_PresentContext(ctx, 1);
        yield();
    }
    
    return 0;
}

Example 5: Simple Pong

#include "NodGL.h"
#include "libc.h"
#include "../include/moduos/kernel/events/events.h"

int md_main(long argc, char **argv) {
    NodGL_Device device;
    NodGL_Context ctx;
    NodGL_CreateDevice(NodGL_FEATURE_LEVEL_1_0, &device, &ctx, NULL);
    
    uint32_t screen_w, screen_h;
    NodGL_GetScreenResolution(device, &screen_w, &screen_h);
    
    int queue_fd = open("/dev/event0", 0);
    
    // Ball
    int ball_x = screen_w / 2, ball_y = screen_h / 2;
    int ball_dx = 3, ball_dy = 2;
    
    // Paddles
    int paddle_h = 80;
    int paddle_y = screen_h / 2 - paddle_h / 2;
    int cpu_y = screen_h / 2 - paddle_h / 2;
    
    int score_player = 0, score_cpu = 0;
    
    while (1) {
        event_t ev;
        while (read(queue_fd, &ev, sizeof(ev)) == sizeof(ev)) {
            if (ev.type == EVENT_MOUSE_MOVE) {
                paddle_y = ev.mouse.y - paddle_h / 2;
            }
        }
        
        // Clamp player paddle
        if (paddle_y < 0) paddle_y = 0;
        if (paddle_y > screen_h - paddle_h) paddle_y = screen_h - paddle_h;
        
        // Move ball
        ball_x += ball_dx;
        ball_y += ball_dy;
        
        // Bounce top/bottom
        if (ball_y <= 0 || ball_y >= screen_h - 10) {
            ball_dy = -ball_dy;
        }
        
        // Player paddle collision
        if (ball_x <= 20 && ball_y >= paddle_y && ball_y <= paddle_y + paddle_h) {
            ball_dx = -ball_dx;
            ball_x = 20;
        }
        
        // CPU paddle collision
        if (ball_x >= screen_w - 30 && ball_y >= cpu_y && ball_y <= cpu_y + paddle_h) {
            ball_dx = -ball_dx;
            ball_x = screen_w - 30;
        }
        
        // CPU AI - follow ball
        if (ball_y < cpu_y + paddle_h / 2) cpu_y -= 2;
        if (ball_y > cpu_y + paddle_h / 2) cpu_y += 2;
        
        // Clamp CPU paddle
        if (cpu_y < 0) cpu_y = 0;
        if (cpu_y > screen_h - paddle_h) cpu_y = screen_h - paddle_h;
        
        // Score
        if (ball_x < 0) {
            score_cpu++;
            ball_x = screen_w / 2;
            ball_y = screen_h / 2;
            ball_dx = 3;
        }
        if (ball_x > screen_w) {
            score_player++;
            ball_x = screen_w / 2;
            ball_y = screen_h / 2;
            ball_dx = -3;
        }
        
        // Draw
        NodGL_ClearContext(ctx, NodGL_CLEAR_COLOR, 0xFF001010, 1.0f, 0);
        
        // Center line
        for (int y = 0; y < screen_h; y += 20) {
            NodGL_FillRectContext(ctx, screen_w / 2 - 2, y, 4, 10, 0xFF404040);
        }
        
        // Paddles
        NodGL_FillRectContext(ctx, 10, paddle_y, 10, paddle_h, 0xFFFFFFFF);
        NodGL_FillRectContext(ctx, screen_w - 20, cpu_y, 10, paddle_h, 0xFFFFFFFF);
        
        // Ball
        NodGL_FillRectContext(ctx, ball_x, ball_y, 10, 10, 0xFFFFFF00);
        
        // Score display (simple)
        char score_text[32];
        snprintf(score_text, sizeof(score_text), "%d - %d", score_player, score_cpu);
        for (int i = 0; score_text[i]; i++) {
            NodGL_FillRectContext(ctx, screen_w / 2 - 40 + i * 10, 20, 8, 12, 0xFFFFFFFF);
        }
        
        NodGL_PresentContext(ctx, 1);
        
        for (volatile int i = 0; i < 20000; i++);
        yield();
    }
    
    NodGL_ReleaseDevice(device);
    return 0;
}

Building and Running

Save any example as myprogram.c and build it:

# Compile
gcc -m64 -O2 -ffreestanding -nostdlib -I/path/to/include \
    -c myprogram.c -o myprogram.o

# Link
ld -T user.ld myprogram.o libc.a lib_NodGL.a -o myprogram.sqr

# Run in ModuOS
./myprogram.sqr

Tips for Learning

  1. Start simple - Begin with Example 1 or 2
  2. Modify values - Change colors, speeds, sizes to see what happens
  3. Add features - Try adding sound effects or new game mechanics
  4. Combine examples - Mix starfield with pong for a cool background!
  5. Read the code - Understand each line before moving on

Challenges

Try these on your own:

  1. Breakout - Make a brick-breaking game
  2. Snake - Classic snake game with growing tail
  3. Flappy Bird - Side-scrolling obstacle avoidance
  4. Memory Match - Card matching game
  5. Space Invaders - Shoot falling enemies

Have fun coding! 🚀

Clone this wiki locally