// Simple infinite 360degree scroller using either digital or analogue pad. // Press Left/Right/up/down to speedup/slowdown change direction etc. // Just an experimental demo made available to illustrate the technique. // by James Shaughnessy james@manc.u-net.com // http://www.netyaroze-europe.com/~shaughnj #define MAXSPEED 24 // Max scroll speed pixels/frame #define NULLZONE 32 // PAD centre nullzone radius // Acts as PAD sensitivity -- // Lower number = higher sensitivity #include #include #include "pad.h" // Global Variables u_long padStatus = 0; short offsetx = 0, offsety = 0; // Offset level short incx = 0, incy = 0; // Scroll increment pixel/frame u_char PAD1lh, PAD1lv, PAD1rh, PAD1rv; // Analog PAD values extern DISPENV GsDISPENV; // Function Declarations void DrawPicture(); void SetScrollSpeed(); main() { RECT tleft, tright; RECT bleft, bright; // Setup graphics PAL SetVideoMode(MODE_PAL); GsInitGraph(320, 256, 4, 0, 0); GsDISPENV.screen.y = 20; GsDISPENV.screen.h = 256; GsDefDispBuff(0, 0, 0, 0); PadInit(); DrawPicture(); while(1) { padStatus = PadRead(); // Quit if both Select and Start pressed if (padStatus & PAD1select && padStatus & PAD1start) break; SetScrollSpeed(); // Set rects tleft.x = 0; tleft.y = 256; tleft.w = offsetx; tleft.h = offsety; tright.x = offsetx; tright.y = 256; tright.w = 320 - offsetx; tright.h = offsety; bleft.x = 0; bleft.y = 256 + offsety; bleft.w = offsetx; bleft.h = 256 - offsety; bright.x = offsetx; bright.y = 256 + offsety; bright.w = 320 - offsetx; bright.h = 256 - offsety; // Wait for a vertical blank VSync(0); // Copy virtual screen parts to visible area MoveImage(&bright, 0, 0); if (offsetx) MoveImage(&bleft, 320 - offsetx, 0); if (offsety) MoveImage(&tright, 0, 256 - offsety); if (offsetx && offsety) MoveImage(&tleft, 320 - offsetx, 256 - offsety); DrawSync(0); GsSwapDispBuff(); // Increment offsets (scroll!) and wrap around offsetx += incx; offsety += incy; if (offsetx >= 320) offsetx -= 320; else if (offsetx < 0) offsetx += 320; if (offsety >= 256) offsety -= 256; else if (offsety < 0) offsety += 256; } ResetGraph(0); } // Draw a 'picture' on the virtual screen (0,256)-(320,512) // (50 Random rectangles) void DrawPicture() { RECT scr; // Virtual screen RECT box; int i; scr.x = 0; scr.y = 256; scr.w = 320; scr.h = 256; ClearImage(&scr, 0, 0, 0); for (i=0; i < 50; i++) { box.x = rand()%290 + scr.x; box.y = rand()%226 + scr.y; box.w = 10 + rand()%30; box.h = 10 + rand()%30; ClearImage(&box, rand()%256, rand()%256, rand()%256); } } // Tests PAD for type and movement level void SetScrollSpeed() { if ((*(bb0+1) >> 4) == 4) // Digital PAD connected { if (padStatus & PAD1left) if (incx > -MAXSPEED) incx--; if (padStatus & PAD1right) if (incx < MAXSPEED) incx++; if (padStatus & PAD1up) if (incy > -MAXSPEED) incy--; if (padStatus & PAD1down) if (incy < MAXSPEED) incy++; } else // Analog PAD connected if ( (*(bb0+1) >> 4) == 7 || (*(bb0+1) >> 4) == 5 ) { if (PAD1lh < (128 - NULLZONE) || PAD1lh > (128+NULLZONE)) { if (PAD1lh < 128) incx = (MAXSPEED * (PAD1lh - 128 + NULLZONE)) / (128 - NULLZONE); else incx = (MAXSPEED * (PAD1lh - 128 - NULLZONE)) / (128 - NULLZONE); } else incx = 0; if (PAD1lv < (128 - NULLZONE) || PAD1lv > (128 + NULLZONE)) { if (PAD1lv < 128) incy = (MAXSPEED * (PAD1lv - 128 + NULLZONE)) / (128 - NULLZONE); else incy = (MAXSPEED * (PAD1lv - 128 - NULLZONE)) / (128 - NULLZONE); } else incy = 0; } } // ****** PAD routines ****** // call once only in program initialisation void PadInit (void) { GetPadBuf(&bb0, &bb1); } // call once per VSync(0) u_long PadRead(void) { // Get analog values PAD1rh = *(bb0+4); PAD1rv = *(bb0+5); PAD1lh = *(bb0+6); PAD1lv = *(bb0+7); return(~(*(bb0+3) | *(bb0+2) << 8 | *(bb1+3) << 16 | *(bb1+2) << 24)); }