joeylib2/examples/sprite/sprite.c

148 lines
5 KiB
C

// 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 <stdio.h>
#include <joey/joey.h>
#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;
}