// Sprite demo: bounces a 16x16 ball sprite around the screen using // surfaceBlitMasked. The ball is embedded as a `const JoeyAssetT` // directly in this file, so no .jas file or runtime allocation is // involved -- this exercises the static / embedded path. Press ESC // to quit. // // Each frame we redraw only the ball's old and new bounding boxes // (and present those two small rects), so the cost stays small even // with the slow 68000-class c2p in the ST and Amiga ports. #include #include #define BALL_W 16 #define BALL_H 16 #define BALL_PALETTE_IDX 0 #define COLOR_BG 0 #define COLOR_TRANSPARENT 0 // first palette slot doubles as mask // 16x16 ball sprite, 4bpp packed (8 bytes per row): // 0 = transparent (mask) // 2 = ball body (yellow) // 3 = highlight (white) // High nibble of each byte is the LEFT pixel. static const uint8_t gBallPixels[BALL_H * 8] = { 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, // row 0 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, // row 1 0x02, 0x22, 0x32, 0x22, 0x22, 0x22, 0x22, 0x20, // row 2 0x02, 0x23, 0x32, 0x22, 0x22, 0x22, 0x22, 0x20, // row 3 0x22, 0x33, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, // row 4 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, // row 5 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, // row 6 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, // row 7 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, // row 8 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, // row 9 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, // row 10 0x02, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x20, // row 11 0x02, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x20, // row 12 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, // row 13 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, // row 14 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00 // row 15 }; // Build the embedded ball asset at runtime. We could declare a // `static const JoeyAssetT` with this same data, but ORCA/C 2.1 // does not handle a file-scope static struct whose pointer field is // initialized from another static array's address (linker complains // of unresolved references). Building the struct in main() with a // local sidesteps the quirk and costs only a handful of stores. static void buildBallAsset(JoeyAssetT *ball) { uint16_t i; ball->width = BALL_W; ball->height = BALL_H; ball->hasPalette = true; ball->pixels = gBallPixels; for (i = 0; i < 16; i++) { ball->palette[i] = 0x0000; } ball->palette[2] = 0x0FF0; // yellow body ball->palette[3] = 0x0FFF; // white highlight } static void initialPaint(SurfaceT *screen) { surfaceClear(screen, COLOR_BG); surfacePresent(screen); } int main(void) { JoeyConfigT config; SurfaceT *screen; JoeyAssetT ball; int16_t x; int16_t y; int16_t vx; int16_t vy; int16_t lastX; int16_t lastY; config.hostMode = HOST_MODE_TAKEOVER; config.codegenBytes = 32 * 1024; config.maxSurfaces = 4; config.audioBytes = 64 * 1024; config.assetBytes = 128 * 1024; if (!joeyInit(&config)) { fprintf(stderr, "joeyInit failed: %s\n", joeyLastError()); return 1; } screen = surfaceGetScreen(); if (screen == NULL) { fprintf(stderr, "surfaceGetScreen returned NULL\n"); joeyShutdown(); return 1; } buildBallAsset(&ball); joeyAssetApplyPalette(screen, BALL_PALETTE_IDX, &ball); scbSetRange(screen, 0, SURFACE_HEIGHT - 1, BALL_PALETTE_IDX); initialPaint(screen); x = 40; y = 30; vx = 2; vy = 1; lastX = x; lastY = y; surfaceBlitMasked(screen, &ball, x, y, COLOR_TRANSPARENT); surfacePresentRect(screen, x, y, BALL_W, BALL_H); for (;;) { joeyWaitVBL(); joeyInputPoll(); if (joeyKeyPressed(KEY_ESCAPE)) { break; } // Erase old ball position by clearing its bounding rect. Any // pixel outside the ball that we wrote (we wrote no pixels // outside, since blitMasked respects transparency) stays as // background already. fillRect(screen, lastX, lastY, BALL_W, BALL_H, COLOR_BG); surfacePresentRect(screen, lastX, lastY, BALL_W, BALL_H); x = (int16_t)(x + vx); y = (int16_t)(y + vy); if (x <= 0) { x = 0; vx = (int16_t)-vx; } if (x >= SURFACE_WIDTH - BALL_W) { x = SURFACE_WIDTH - BALL_W; vx = (int16_t)-vx; } if (y <= 0) { y = 0; vy = (int16_t)-vy; } if (y >= SURFACE_HEIGHT - BALL_H) { y = SURFACE_HEIGHT - BALL_H; vy = (int16_t)-vy; } surfaceBlitMasked(screen, &ball, x, y, COLOR_TRANSPARENT); surfacePresentRect(screen, x, y, BALL_W, BALL_H); lastX = x; lastY = y; } joeyShutdown(); return 0; }