All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.mathiewz.slick.AppGameContainer Maven / Gradle / Ivy

Go to download

The main purpose of this libraryis to modernize and maintain the slick2D library.

The newest version!
package com.github.mathiewz.slick;

import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.PrivilegedAction;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Cursor;
import org.lwjgl.input.Mouse;
import org.lwjgl.openal.AL;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.PixelFormat;

import com.github.mathiewz.slick.openal.SoundStore;
import com.github.mathiewz.slick.opengl.CursorLoader;
import com.github.mathiewz.slick.opengl.ImageData;
import com.github.mathiewz.slick.opengl.ImageIOImageData;
import com.github.mathiewz.slick.opengl.InternalTextureLoader;
import com.github.mathiewz.slick.opengl.LoadableImageData;
import com.github.mathiewz.slick.opengl.TGAImageData;
import com.github.mathiewz.slick.util.Log;
import com.github.mathiewz.slick.util.ResourceLoader;

/**
 * A game container that will display the game as an stand alone
 * application.
 *
 * @author kevin
 */
public class AppGameContainer extends GameContainer {
    static {
        AccessController.doPrivileged((PrivilegedAction) () -> {
            try {
                Display.getDisplayMode();
            } catch (Exception e) {
                Log.error(e);
            }
            return null;
        });
    }
    
    /** The original display mode before we tampered with things */
    protected DisplayMode originalDisplayMode;
    /** The display mode we're going to try and use */
    protected DisplayMode targetDisplayMode;
    /** True if we should update the game only when the display is visible */
    protected boolean updateOnlyOnVisible = true;
    /** Alpha background supported */
    protected boolean alphaSupport = false;
    
    /**
     * Create a new container wrapping a game
     *
     * @param game
     *            The game to be wrapped
     */
    public AppGameContainer(Game game) {
        this(game, 640, 480, false);
    }
    
    /**
     * Create a new container wrapping a game
     *
     * @param game
     *            The game to be wrapped
     * @param width
     *            The width of the display required
     * @param height
     *            The height of the display required
     * @param fullscreen
     *            True if we want fullscreen mode
     */
    public AppGameContainer(Game game, int width, int height, boolean fullscreen) {
        super(game);
        
        originalDisplayMode = Display.getDisplayMode();
        
        setDisplayMode(width, height, fullscreen);
    }
    
    /**
     * Check if the display created supported alpha in the back buffer
     *
     * @return True if the back buffer supported alpha
     */
    public boolean supportsAlphaInBackBuffer() {
        return alphaSupport;
    }
    
    /**
     * Set the title of the window
     *
     * @param title
     *            The title to set on the window
     */
    public void setTitle(String title) {
        Display.setTitle(title);
    }
    
    /**
     * Set the display mode to be used
     *
     * @param width
     *            The width of the display required
     * @param height
     *            The height of the display required
     * @param fullscreen
     *            True if we want fullscreen mode
     */
    public void setDisplayMode(int width, int height, boolean fullscreen) {
        if (this.width == width && this.height == height && isFullscreen() == fullscreen) {
            return;
        }
        
        try {
            targetDisplayMode = null;
            if (fullscreen) {
                DisplayMode[] modes = Display.getAvailableDisplayModes();
                int freq = 0;
                
                for (DisplayMode current : modes) {
                    if (current.getWidth() == width && current.getHeight() == height) {
                        if (targetDisplayMode == null || current.getFrequency() >= freq) {
                            if (targetDisplayMode == null || current.getBitsPerPixel() > targetDisplayMode.getBitsPerPixel()) {
                                targetDisplayMode = current;
                                freq = targetDisplayMode.getFrequency();
                            }
                        }
                        
                        // if we've found a match for bpp and frequence against the
                        // original display mode then it's probably best to go for this one
                        // since it's most likely compatible with the monitor
                        if (current.getBitsPerPixel() == originalDisplayMode.getBitsPerPixel() && current.getFrequency() == originalDisplayMode.getFrequency()) {
                            targetDisplayMode = current;
                            break;
                        }
                    }
                }
            } else {
                targetDisplayMode = new DisplayMode(width, height);
            }
            
            if (targetDisplayMode == null) {
                throw new SlickException("Failed to find value mode: " + width + "x" + height + " fs=" + fullscreen);
            }
            
            this.width = width;
            this.height = height;
            
            Display.setDisplayMode(targetDisplayMode);
            Display.setFullscreen(fullscreen);
            
            if (Display.isCreated()) {
                initGL();
                enterOrtho();
            }
            
            if (targetDisplayMode.getBitsPerPixel() == 16) {
                InternalTextureLoader.get().set16BitMode();
            }
        } catch (LWJGLException e) {
            throw new SlickException("Unable to setup mode " + width + "x" + height + " fullscreen=" + fullscreen, e);
        }
        
        getDelta();
    }
    
    /**
     * Check if the display is in fullscreen mode
     *
     * @return True if the display is in fullscreen mode
     */
    @Override
    public boolean isFullscreen() {
        return Display.isFullscreen();
    }
    
    /**
     * Indicate whether we want to be in fullscreen mode. Note that the current
     * display mode must be valid as a fullscreen mode for this to work
     *
     * @param fullscreen
     *            True if we want to be in fullscreen mode
     */
    @Override
    public void setFullscreen(boolean fullscreen) {
        if (isFullscreen() == fullscreen) {
            return;
        }
        
        if (!fullscreen) {
            try {
                Display.setFullscreen(fullscreen);
            } catch (LWJGLException e) {
                throw new SlickException("Unable to set fullscreen=" + fullscreen, e);
            }
        } else {
            setDisplayMode(width, height, fullscreen);
        }
        getDelta();
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#setMouseCursor(java.lang.String, int, int)
     */
    @Override
    public void setMouseCursor(String ref, int hotSpotX, int hotSpotY) {
        try {
            Cursor cursor = CursorLoader.get().getCursor(ref, hotSpotX, hotSpotY);
            Mouse.setNativeCursor(cursor);
        } catch (Throwable e) {
            Log.error("Failed to load and apply cursor.", e);
            throw new SlickException("Failed to set mouse cursor", e);
        }
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#setMouseCursor(com.github.mathiewz.slick.opengl.ImageData, int, int)
     */
    @Override
    public void setMouseCursor(ImageData data, int hotSpotX, int hotSpotY) {
        try {
            Cursor cursor = CursorLoader.get().getCursor(data, hotSpotX, hotSpotY);
            Mouse.setNativeCursor(cursor);
        } catch (Throwable e) {
            Log.error("Failed to load and apply cursor.", e);
            throw new SlickException("Failed to set mouse cursor", e);
        }
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#setMouseCursor(org.lwjgl.input.Cursor, int, int)
     */
    @Override
    public void setMouseCursor(Cursor cursor, int hotSpotX, int hotSpotY) {
        try {
            Mouse.setNativeCursor(cursor);
        } catch (Throwable e) {
            Log.error("Failed to load and apply cursor.", e);
            throw new SlickException("Failed to set mouse cursor", e);
        }
    }
    
    /**
     * Get the closest greater power of 2 to the fold number
     *
     * @param fold
     *            The target number
     * @return The power of 2
     */
    private int get2Fold(int fold) {
        int ret = 2;
        while (ret < fold) {
            ret *= 2;
        }
        return ret;
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#setMouseCursor(com.github.mathiewz.slick.Image, int, int)
     */
    @Override
    public void setMouseCursor(Image image, int hotSpotX, int hotSpotY) {
        try {
            Image temp = new Image(get2Fold(image.getWidth()), get2Fold(image.getHeight()));
            Graphics g = temp.getGraphics();
            
            ByteBuffer buffer = BufferUtils.createByteBuffer(temp.getWidth() * temp.getHeight() * 4);
            g.drawImage(image.getFlippedCopy(false, true), 0, 0);
            g.flush();
            g.getArea(0, 0, temp.getWidth(), temp.getHeight(), buffer);
            
            Cursor cursor = CursorLoader.get().getCursor(buffer, hotSpotX, hotSpotY, temp.getWidth(), image.getHeight());
            Mouse.setNativeCursor(cursor);
        } catch (Throwable e) {
            Log.error("Failed to load and apply cursor.", e);
            throw new SlickException("Failed to set mouse cursor", e);
        }
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#reinit()
     */
    @Override
    public void reinit() {
        InternalTextureLoader.get().clear();
        SoundStore.get().clear();
        initSystem();
        enterOrtho();
        
        try {
            game.init(this);
        } catch (SlickException e) {
            Log.error(e);
            running = false;
        }
    }
    
    /**
     * Try creating a display with the given format
     *
     * @param format
     *            The format to attempt
     * @throws LWJGLException
     *             Indicates a failure to support the given format
     */
    private void tryCreateDisplay(PixelFormat format) throws LWJGLException {
        if (SHARED_DRAWABLE == null) {
            Display.create(format);
        } else {
            Display.create(format, SHARED_DRAWABLE);
        }
    }
    
    /**
     * Start running the game
     *
     */
    public void start() {
        try {
            setup();
            
            getDelta();
            while (running()) {
                gameLoop();
            }
        } finally {
            destroy();
        }
        
        if (forceExit) {
            System.exit(0);
        }
    }
    
    /**
     * Setup the environment
     *
     */
    protected void setup() {
        if (targetDisplayMode == null) {
            setDisplayMode(640, 480, false);
        }
        
        Display.setTitle(game.getTitle());
        
        Log.info("LWJGL Version: " + Sys.getVersion());
        Log.info("OriginalDisplayMode: " + originalDisplayMode);
        Log.info("TargetDisplayMode: " + targetDisplayMode);
        
        AccessController.doPrivileged((PrivilegedAction) () -> {
            try {
                PixelFormat format1 = new PixelFormat(8, 8, stencil ? 8 : 0, samples);
                
                tryCreateDisplay(format1);
                supportsMultiSample = true;
            } catch (Exception e) {
                Display.destroy();
                
                try {
                    PixelFormat format2 = new PixelFormat(8, 8, stencil ? 8 : 0);
                    
                    tryCreateDisplay(format2);
                    alphaSupport = false;
                } catch (Exception e2) {
                    Display.destroy();
                    // if we couldn't get alpha, let us know
                    try {
                        tryCreateDisplay(new PixelFormat());
                    } catch (Exception e3) {
                        Log.error(e3);
                    }
                }
            }
            
            return null;
        });
        
        if (!Display.isCreated()) {
            throw new SlickException("Failed to initialise the LWJGL display");
        }
        
        initSystem();
        enterOrtho();
        
        try {
            getInput().initControllers();
        } catch (SlickException e) {
            Log.info("Controllers not available");
        } catch (Throwable e) {
            Log.info("Controllers not available");
        }
        
        try {
            game.init(this);
        } catch (SlickException e) {
            Log.error(e);
            running = false;
        }
    }
    
    /**
     * Strategy for overloading game loop context handling
     *
     */
    protected void gameLoop() {
        int delta = getDelta();
        if (!Display.isVisible() && updateOnlyOnVisible) {
            try {
                Thread.sleep(100);
            } catch (Exception e) {
            }
        } else {
            try {
                updateAndRender(delta);
            } catch (SlickException e) {
                Log.error(e);
                running = false;
                return;
            }
        }
        
        updateFPS();
        
        Display.update();
        
        if (Display.isCloseRequested()) {
            if (game.closeRequested()) {
                running = false;
            }
        }
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#setUpdateOnlyWhenVisible(boolean)
     */
    @Override
    public void setUpdateOnlyWhenVisible(boolean updateOnlyWhenVisible) {
        updateOnlyOnVisible = updateOnlyWhenVisible;
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#isUpdatingOnlyWhenVisible()
     */
    @Override
    public boolean isUpdatingOnlyWhenVisible() {
        return updateOnlyOnVisible;
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#setIcon(java.lang.String)
     */
    @Override
    public void setIcon(String ref) {
        setIcons(new String[] { ref });
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#setMouseGrabbed(boolean)
     */
    @Override
    public void setMouseGrabbed(boolean grabbed) {
        Mouse.setGrabbed(grabbed);
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#isMouseGrabbed()
     */
    @Override
    public boolean isMouseGrabbed() {
        return Mouse.isGrabbed();
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#hasFocus()
     */
    @Override
    public boolean hasFocus() {
        // hmm, not really the right thing, talk to the LWJGL guys
        return Display.isActive();
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#getScreenHeight()
     */
    @Override
    public int getScreenHeight() {
        return originalDisplayMode.getHeight();
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#getScreenWidth()
     */
    @Override
    public int getScreenWidth() {
        return originalDisplayMode.getWidth();
    }
    
    /**
     * Destroy the app game container
     */
    public void destroy() {
        Display.destroy();
        AL.destroy();
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#setIcons(java.lang.String[])
     */
    @Override
    public void setIcons(String[] refs) {
        ByteBuffer[] bufs = new ByteBuffer[refs.length];
        for (int i = 0; i < refs.length; i++) {
            LoadableImageData data;
            boolean flip = true;
            
            if (refs[i].endsWith(".tga")) {
                data = new TGAImageData();
            } else {
                flip = false;
                data = new ImageIOImageData();
            }
            
            try {
                bufs[i] = data.loadImage(ResourceLoader.getResourceAsStream(refs[i]), flip, false, null);
            } catch (Exception e) {
                Log.error(e);
                throw new SlickException("Failed to set the icon");
            }
        }
        
        Display.setIcon(bufs);
    }
    
    /**
     * @see com.github.mathiewz.slick.GameContainer#setDefaultMouseCursor()
     */
    @Override
    public void setDefaultMouseCursor() {
        try {
            Mouse.setNativeCursor(null);
        } catch (LWJGLException e) {
            Log.error("Failed to reset mouse cursor", e);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy