Path: blob/master/SLICK_HOME/src/org/newdawn/slick/ScalableGame.java
1456 views
package org.newdawn.slick;12import org.newdawn.slick.opengl.SlickCallable;3import org.newdawn.slick.opengl.renderer.Renderer;4import org.newdawn.slick.opengl.renderer.SGL;56/**7* A wrapper to allow any game to be scalable. This relies on knowing the8* normal width/height of the game - i.e. the dimensions that the game is9* expecting to be run at. The wrapper then takes the size of the container10* and scales rendering and input based on the ratio.11*12* Note: Using OpenGL directly within a ScalableGame can break it13*14* @author kevin15*/16public class ScalableGame implements Game {17/** The renderer to use for all GL operations */18private static SGL GL = Renderer.get();1920/** The normal or native width of the game */21private float normalWidth;22/** The normal or native height of the game */23private float normalHeight;24/** The game that is being wrapped */25private Game held;26/** True if we should maintain the aspect ratio */27private boolean maintainAspect;28/** The target width */29private int targetWidth;30/** The target height */31private int targetHeight;32/** The game container wrapped */33private GameContainer container;3435/**36* Create a new scalable game wrapper37*38* @param held The game to be wrapper and displayed at a different resolution39* @param normalWidth The normal width of the game40* @param normalHeight The noral height of the game41*/42public ScalableGame(Game held, int normalWidth, int normalHeight) {43this(held, normalWidth, normalHeight, false);44}4546/**47* Create a new scalable game wrapper48*49* @param held The game to be wrapper and displayed at a different resolution50* @param normalWidth The normal width of the game51* @param normalHeight The noral height of the game52* @param maintainAspect True if we should maintain the aspect ratio53*/54public ScalableGame(Game held, int normalWidth, int normalHeight, boolean maintainAspect) {55this.held = held;56this.normalWidth = normalWidth;57this.normalHeight = normalHeight;58this.maintainAspect = maintainAspect;59}6061/**62* @see org.newdawn.slick.BasicGame#init(org.newdawn.slick.GameContainer)63*/64public void init(GameContainer container) throws SlickException {65this.container = container;6667recalculateScale();68held.init(container);69}7071/**72* Recalculate the scale of the game73*74* @throws SlickException Indicates a failure to reinit the game75*/76public void recalculateScale() throws SlickException {77targetWidth = container.getWidth();78targetHeight = container.getHeight();7980if (maintainAspect) {81boolean normalIsWide = (normalWidth / normalHeight > 1.6 ? true : false);82boolean containerIsWide = ((float) targetWidth / (float) targetHeight > 1.6 ? true : false);83float wScale = targetWidth / normalWidth;84float hScale = targetHeight / normalHeight;8586if (normalIsWide & containerIsWide) {87float scale = (wScale < hScale ? wScale : hScale);88targetWidth = (int) (normalWidth * scale);89targetHeight = (int) (normalHeight * scale);90} else if (normalIsWide & !containerIsWide) {91targetWidth = (int) (normalWidth * wScale);92targetHeight = (int) (normalHeight * wScale);93} else if (!normalIsWide & containerIsWide) {94targetWidth = (int) (normalWidth * hScale);95targetHeight = (int) (normalHeight * hScale);96} else {97float scale = (wScale < hScale ? wScale : hScale);98targetWidth = (int) (normalWidth * scale);99targetHeight = (int) (normalHeight * scale);100}101102}103104if (held instanceof InputListener) {105container.getInput().addListener((InputListener) held);106}107container.getInput().setScale(normalWidth / targetWidth,108normalHeight / targetHeight);109110111int yoffset = 0;112int xoffset = 0;113114if (targetHeight < container.getHeight()) {115yoffset = (container.getHeight() - targetHeight) / 2;116}117if (targetWidth < container.getWidth()) {118xoffset = (container.getWidth() - targetWidth) / 2;119}120container.getInput().setOffset(-xoffset / (targetWidth / normalWidth),121-yoffset / (targetHeight / normalHeight));122123}124125/**126* @see org.newdawn.slick.BasicGame#update(org.newdawn.slick.GameContainer, int)127*/128public void update(GameContainer container, int delta) throws SlickException {129if ((targetHeight != container.getHeight()) ||130(targetWidth != container.getWidth())) {131recalculateScale();132}133134held.update(container, delta);135}136137/**138* @see org.newdawn.slick.Game#render(org.newdawn.slick.GameContainer, org.newdawn.slick.Graphics)139*/140public final void render(GameContainer container, Graphics g)141throws SlickException {142int yoffset = 0;143int xoffset = 0;144145if (targetHeight < container.getHeight()) {146yoffset = (container.getHeight() - targetHeight) / 2;147}148if (targetWidth < container.getWidth()) {149xoffset = (container.getWidth() - targetWidth) / 2;150}151152SlickCallable.enterSafeBlock();153g.setClip(xoffset, yoffset, targetWidth, targetHeight);154GL.glTranslatef(xoffset, yoffset, 0);155GL.glScalef(targetWidth / normalWidth, targetHeight / normalHeight,0);156GL.glPushMatrix();157held.render(container, g);158GL.glPopMatrix();159g.clearClip();160SlickCallable.leaveSafeBlock();161162renderOverlay(container, g);163}164165/**166* Render the overlay that will sit over the scaled screen167*168* @param container The container holding the game being render169* @param g Graphics context on which to render170*/171protected void renderOverlay(GameContainer container, Graphics g) {172}173174/**175* @see org.newdawn.slick.Game#closeRequested()176*/177public boolean closeRequested() {178return held.closeRequested();179}180181/**182* @see org.newdawn.slick.Game#getTitle()183*/184public String getTitle() {185return held.getTitle();186}187}188189190