# Simple NodGL Examples Complete, working programs you can learn from! ## Example 1: Bouncing DVD Logo ```c #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 ```c #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 ```c #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 ```c #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 ```c #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: ```bash # 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! 🚀