TestSprite.bsh
なんか恒例のやつ.
BeanShell では任意の Java オブジェクトが扱えます.gcj でコンパイルしてあるので sdl4gcj*1を使えば当然 SDL も扱えるわけです.
そういうわけで SDL の testsprite.c の BeanShell 版.
#!/usr/bin/bsh-Interpreter import sdl4gcj.*; import sdl4gcj.video.*; import sdl4gcj.event.*; import sdl4gcj.input.*; TestSprite() { final int MAX_SPEED = 1; final Random random = new java.util.Random(); Sprite() { // init size int w = super.icon.w; int h = super.icon.h; int areaW = super.screen.w - w; int areaH = super.screen.h - h; // init location int x = random.nextInt(areaW); int y = random.nextInt(areaH); // init speed int dx, dy; while(dx == 0 && dy == 0) { dx = random.nextInt(MAX_SPEED * 2 + 1) - MAX_SPEED; dy = random.nextInt(MAX_SPEED * 2 + 1) - MAX_SPEED; } // for Rect interface int getX(){ return x; } int getY(){ return y; } int getW(){ return w; } int getH(){ return h; } void move() { x = x + dx; if (x < 0 || x > areaW) { dx = -dx; x += dx; } y = y + dy; if (y < 0 || y > areaH) { dy = -dy; y += dy; } } void draw() { super.screen.blitSurface(super.icon, x, y); } return this; } int screenWidth = 640; int screenHeight = 480; int bitsPerPixel = 8; int videoFlags = Screen.SDL_SWSURFACE; int numberOfSprite = 100; Surface screen = null; Surface icon = null; int bgColor = 0; Object[] sprites = null; Rect[] rects = null; long ticks = 0; int frames = 0; boolean useFlip = false; void run() { this.initScreen(); this.initIcon(); this.initSprites(); this.printInfo(); this.mainLoop(); this.freeIcon(); } double getFPS() { return ((double)frames * 1000)/ticks; } void initScreen() { screen = Screen.setVideoMode( screenWidth, screenHeight, bitsPerPixel, videoFlags); bgColor = screen.mapRGB(Color.BLACK); if ((screen.flags & screen.SDL_DOUBLEBUF) != 0) useFlip = true; } void initIcon() { // load icon image and change pixel format icon = Surface.loadBMP("icon.bmp"); icon.setColorKey(Surface.SDL_SRCCOLORKEY|Surface.SDL_RLEACCEL); icon.displayFormat(); // Run a sample blit to trigger blit acceleration screen.blitSurface(icon); screen.fillRect(bgColor); } void freeIcon() { icon.freeSurface(); icon = null; } void initSprites() { sprites = new Object[numberOfSprite]; rects = new Rect[numberOfSprite]; for (int i = numberOfSprite-1;i >= 0;i--) { sprites[i] = Sprite(); rects[i] = (Rect)sprites[i]; } } void updateSprites() { for (sprite : sprites) { sprite.move(); sprite.draw(); } } void updateScreen() { if (useFlip) screen.flip(); else screen.updateRects(rects); } void mainLoop() { boolean done = false; EventManager event = new EventManager(); frames = 0; System.gc(); ticks = SDLSystem.getTicks(); while (!done) { frames++; while(event.pollEvent() > 0) { switch (event.type) { case event.SDL_KEYDOWN: case event.SDL_QUIT: done = true; break; default: break; } } screen.fillRect(bgColor); updateSprites(); updateScreen(); } ticks = SDLSystem.getTicks() - ticks; } void printInfo() { if (screen != null) { System.out.println("Screen is at " + screen.getPixelFormat().getBitsPerPixel() + " bits per pixel"); var flags = screen.getFlags(); if ((flags & Surface.SDL_HWSURFACE) == Surface.SDL_HWSURFACE) System.out.println("Screen is in video memory"); else System.out.println("Screen is in system memory"); if ((flags & Surface.SDL_DOUBLEBUF) == Surface.SDL_DOUBLEBUF) System.out.println("Screen has double-buffering enabled"); } if (icon != null) { var iconFlags = icon.getFlags(); if ((iconFlags & Surface.SDL_HWSURFACE) == Surface.SDL_HWSURFACE) System.out.println("Sprite is in video memory"); else System.out.println("Sprite is in system memory"); if ((iconFlags & Surface.SDL_HWACCEL) == Surface.SDL_HWACCEL) System.out.println("Sprite blit uses hardware acceleration"); if ((iconFlags & Surface.SDL_RLEACCEL) == Surface.SDL_RLEACCEL) System.out.println("Sprite blit uses RLE acceleration"); } } return this; } // main SDLSystem.init(SDLSystem.SDL_INIT_VIDEO); try { testSprite = TestSprite(); // testSprite.numberOfSprite = 50; // testSprite.videoFlags = Screen.SDL_ANYFORMAT; // testSprite.videoFlags = Screen.SDL_DOUBLEBUF|Screen.SDL_FULLSCREEN; // testSprite.bitsPerPixel = 16; testSprite.run(); System.out.println(testSprite.getFPS() + " frames per second"); } catch (e) { System.out.println(e); e.printStackTrace(); } finally { System.out.println("SDLSystem.quit()"); SDLSystem.quit(); }
なんかすっごいJavaそっくり.とりあえず実行してみる.
% bsh-Interpreter TestSprite.bsh Screen is at 32 bits per pixel Screen is in system memory Sprite is in system memory Sprite blit uses RLE acceleration 42.78280978994026 frames per second
C言語版,Java版,JavaScript版と比べると以下のような感じです.
C言語版 | 327.05 |
Java版(gcj版) | 329.95 |
JavaScript版(インタープリタ) | 127.51 |
JavaScript版(コンパイル) | 162.48 |
BeanShell版 | 42.78 |
実行環境は以下の通り.
とりあえず結論,すっごく遅い.