// Simple program: Move N sprites around on the screen as fast as possible // Ported to SDLmm from the SDL test program. #include "sdlmm_config.h" RCSID("$Id: sprite.cpp,v 1.25 2001/07/09 01:21:11 rad_ad Exp $"); #include #include #include #include "sdlmm.h" using namespace SDLmm; const int NUM_SPRITES = 100; const int MAX_SPEED = 1; namespace { Surface sprite; int numsprites; SRect *sprite_rects; SRect *positions; SRect *velocities; int sprites_visible; }; // Our event handler class MyEventHandler : public EventHandler { public: MyEventHandler() : keep_going(true) { } bool HandleKeyPressEvent(SDL_keysym &keysym) { std::cout << "Got kbd press event: sym = " << keysym.sym << " (" << Event::GetKeyName(keysym.sym) << ").\n"; keep_going = false; return true; } bool HandleQuitEvent() { std::cout << "Got quit event.\n"; keep_going = false; return true; } operator bool() { return keep_going; }; private: bool keep_going; }; bool LoadSprite(Display& screen, char *file) { // Load the sprite image sprite = Surface::LoadBMP(file); if(!sprite.valid()) { std::cerr << "Failed to load sprite: " << GetError() << "\n"; return false; } // Set transparent pixel as the pixel at (0,0) if ( sprite.GetPixelFormat().palette() ) { sprite.SetColorKey((SDL_SRCCOLORKEY|SDL_RLEACCEL), *(Uint8 *)sprite.pixels()); } // Convert sprite to video format if (!sprite.SetDisplayFormat()) { std::cerr << "Couldn't convert background: " << GetError() << ".\n"; return false; } // We're ready to roll. :) return true; } void MoveSprites(Display& screen, Uint32 background) { // Erase all the sprites if necessary if ( sprites_visible ) { screen.Fill(background); } // Move the sprite, bounce at the wall, and draw int nupdates = 0; for (int i=0; i= screen.w()) ) { velocity.x = -velocity.x; position.x += velocity.x; } position.y += velocity.y; if ( (position.y < 0) || (position.y >= screen.h()) ) { velocity.y = -velocity.y; position.y += velocity.y; } // Blit the sprite onto the screen SRect area(position); screen.Blit(sprite, area); sprite_rects[nupdates++] = area; } // Update the screen! if ( (screen.flags() & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { screen.Flip(); } else { screen.UpdateRects(nupdates, sprite_rects); } sprites_visible = 1; } // This is a way of telling whether or not to use hardware surfaces Uint32 FastestFlags(Uint32 flags) { VideoInfo info; // Hardware acceleration is only used in fullscreen mode flags |= SDL_FULLSCREEN; // Check for various video capabilities if ( info.blit_hw_CC() && info.blit_fill() ) { // We use accelerated colorkeying and color filling flags |= SDL_HWSURFACE; } // If we have enough video memory, and will use accelerated // blits directly to it, then use page flipping. if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { // Direct hardware blitting without double-buffering // causes really bad flickering. Display &screen = Display::GetDisplay(); if ( screen.valid() && static_cast(info.video_mem()) > (screen.h() * screen.pitch()) ) { flags |= SDL_DOUBLEBUF; } else { flags &= ~SDL_HWSURFACE; } } // Return the flags return(flags); } int main(int argc, char *argv[]) { Display &screen = Display::GetDisplay(); // Initialize SDL if (!Display::Init()) { std::cerr << "Couldn't initialize SDL: " << GetError() << ".\n"; exit(1); } atexit(Quit); screen.SetCaption("SDLmm Sprite Test", "SDLmm Sprite Test"); numsprites = NUM_SPRITES; Uint32 videoflags = SDL_SWSURFACE|SDL_ANYFORMAT; int width = 640, height = 480; Uint8 video_bpp = 8; while ( argc > 1 ) { --argc; if ( strcmp(argv[argc-1], "-width") == 0 ) { width = atoi(argv[argc]); --argc; } else if ( strcmp(argv[argc-1], "-height") == 0 ) { height = atoi(argv[argc]); --argc; } else if ( strcmp(argv[argc-1], "-bpp") == 0 ) { video_bpp = atoi(argv[argc]); videoflags &= ~SDL_ANYFORMAT; --argc; } else if ( strcmp(argv[argc], "-fast") == 0 ) { videoflags = FastestFlags(videoflags); } else if ( strcmp(argv[argc], "-hw") == 0 ) { videoflags ^= SDL_HWSURFACE; } else if ( strcmp(argv[argc], "-flip") == 0 ) { videoflags ^= SDL_DOUBLEBUF; } else if ( strcmp(argv[argc], "-fullscreen") == 0 ) { videoflags ^= SDL_FULLSCREEN; } else if ( isdigit(argv[argc][0]) ) { numsprites = atoi(argv[argc]); } else { std::cerr << "Usage: " << argv[0] << " [-bpp N] [-hw] [-flip] [-fast] [-fullscreen] [numsprites]" << std::endl; exit(1); } } // Set video mode, using the static function SetVideoMode in the // Display object. You could also access it directly in an // Display instance as usual. This syntax is used for // demonstration purposes only. if (!screen.SetVideoMode(width, height, video_bpp, videoflags)) { std::cerr << "Couldn't set " << width << "x" << height << "video mode: " << GetError() << "\n"; exit(2); } // Load the sprite if (!LoadSprite(screen, "icon.bmp")) { exit(1); } // Allocate memory for the sprite info sprite_rects = new SRect[numsprites]; positions = new SRect[numsprites]; velocities = new SRect[numsprites]; srand(time(0)); for (int i=0; i(screen.GetPixelFormat().BitsPerPixel()) << " bits per pixel\n"; if ( (screen.flags() & SDL_HWSURFACE) == SDL_HWSURFACE ) { std::cout << "Screen is in video memory\n"; } else { std::cout << "Screen is in system memory\n"; } if ( (screen.flags() & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { std::cout << "Screen has double-buffering enabled\n"; } // Run a sample blit to trigger blit acceleration SRect dst(sprite.w(), sprite.h()); screen.Blit(sprite, dst); screen.FillRect(dst, background); if ( (sprite.flags() & SDL_HWACCEL) == SDL_HWACCEL ) { std::cout << "Sprite blit uses hardware acceleration\n"; } if ( (sprite.flags() & SDL_RLEACCEL) == SDL_RLEACCEL ) { std::cout << "Sprite blit uses RLE acceleration\n"; } Uint32 then = SDL_GetTicks(); Uint32 frames = 0; MyEventHandler ev; sprites_visible = 0; // Loop, blitting sprites and waiting for a keystroke while ( ev ) { // Check for events ++frames; Event::HandleEvents(ev); MoveSprites(screen, background); } delete[] sprite_rects; delete[] positions; delete[] velocities; // Print out some timing information Uint32 now = SDL_GetTicks(); if ( now > then ) { std::cout << ((double)frames*1000)/(now-then) << " frames per second\n"; } return(0); } /* * Local Variables: * mode: c++ * c-basic-offset: 2 * End: */