/** * Initialise offscreen rendering by checking what buffers are supported * by the card * * @throws SlickException Indicates no buffers are supported */ private static void init() throws SlickException { init = true; if (fbo) { fbo = GLContext.getCapabilities().GL_EXT_framebuffer_object; } pbuffer = (Pbuffer.getCapabilities() & Pbuffer.PBUFFER_SUPPORTED) != 0; pbufferRT = (Pbuffer.getCapabilities() & Pbuffer.RENDER_TEXTURE_SUPPORTED) != 0; if (!fbo && !pbuffer && !pbufferRT) { throw new SlickException("Your OpenGL card does not support offscreen buffers and hence can't handle the dynamic images required for this application."); } Log.info("Offscreen Buffers FBO="+fbo+" PBUFFER="+pbuffer+" PBUFFERRT="+pbufferRT); }
/** * Get a new particle from the system. This should be used by emitters to * request particles * * @param emitter The emitter requesting the particle * @param life The time the new particle should live for * @return A particle from the system */ public Particle getNewParticle(ParticleEmitter emitter, float life) { ParticlePool pool = (ParticlePool) particlesByEmitter.get(emitter); ArrayList available = pool.available; if (available.size() > 0) { Particle p = (Particle) available.remove(available.size()-1); p.init(emitter, life); p.setImage(sprite); return p; } Log.warn("Ran out of particles (increase the limit)!"); return dummy; }
/** * Creates display for program, sets title and size among other things. */ public static void createDisplay() { ContextAttribs attribs = new ContextAttribs(3, 3).withForwardCompatible(true).withProfileCore(true); try { Display.setDisplayMode(new DisplayMode(Reference.WINDOW_SIZE.width, Reference.WINDOW_SIZE.height)); Display.create(new PixelFormat().withSamples(8).withDepthBits(24), attribs); Display.setTitle(Reference.WINDOW_TITLE); GL11.glEnable(GL13.GL_MULTISAMPLE); } catch (LWJGLException e) { e.printStackTrace(); } GL11.glViewport(0, 0, Reference.WINDOW_SIZE.width, Reference.WINDOW_SIZE.height); Log.setVerbose(false); lastFrameTime = getCurrentTime(); }
/** * Create and load a piece of music (either OGG or MOD/XM) * @param in The stream to read the music from * @param ref The symbolic name of this music * @throws SlickException Indicates a failure to read the music from the stream */ public Music(InputStream in, String ref) throws SlickException { SoundStore.get().init(); try { if (ref.toLowerCase().endsWith(".ogg")) { sound = SoundStore.get().getOgg(in); } else if (ref.toLowerCase().endsWith(".wav")) { sound = SoundStore.get().getWAV(in); } else if (ref.toLowerCase().endsWith(".xm") || ref.toLowerCase().endsWith(".mod")) { sound = SoundStore.get().getMOD(in); } else if (ref.toLowerCase().endsWith(".aif") || ref.toLowerCase().endsWith(".aiff")) { sound = SoundStore.get().getAIF(in); } else { throw new SlickException("Only .xm, .mod, .ogg, and .aif/f are currently supported."); } } catch (Exception e) { Log.error(e); throw new SlickException("Failed to load music: "+ref); } }
/** * Load the image * * @param in The input stream to read the image from * @param ref The name that should be assigned to the image * @param flipped True if the image should be flipped on the y-axis on load * @param f The filter to use when scaling this image * @param transparent The color to treat as transparent * @throws SlickException Indicates a failure to load the image */ private void load(InputStream in, String ref, boolean flipped, int f, Color transparent) throws SlickException { this.filter = f == FILTER_LINEAR ? SGL.GL_LINEAR : SGL.GL_NEAREST; try { this.ref = ref; int[] trans = null; if (transparent != null) { trans = new int[3]; trans[0] = (int) (transparent.r * 255); trans[1] = (int) (transparent.g * 255); trans[2] = (int) (transparent.b * 255); } texture = InternalTextureLoader.get().getTexture(in, ref, flipped, filter, trans); } catch (IOException e) { Log.error(e); throw new SlickException("Failed to load image from: "+ref, e); } }
/** * Create an image based on a file at the specified location * * @param ref The location of the image file to load * @param flipped True if the image should be flipped on the y-axis on load * @param f The filtering method to use when scaling this image * @param transparent The color to treat as transparent * @throws SlickException Indicates a failure to load the image */ public Image(String ref, boolean flipped, int f, Color transparent) throws SlickException { this.filter = f == FILTER_LINEAR ? SGL.GL_LINEAR : SGL.GL_NEAREST; this.transparent = transparent; this.flipped = flipped; try { this.ref = ref; int[] trans = null; if (transparent != null) { trans = new int[3]; trans[0] = (int) (transparent.r * 255); trans[1] = (int) (transparent.g * 255); trans[2] = (int) (transparent.b * 255); } texture = InternalTextureLoader.get().getTexture(ref, flipped, filter, trans); } catch (IOException e) { Log.error(e); throw new SlickException("Failed to load image from: "+ref, e); } }
/** * @see Font#drawString(float, float, String, Color, int, int) */ public void drawString(float x, float y, String text, Color col, int startIndex, int endIndex) { try { byte[] data = text.getBytes("US-ASCII"); for (int i = 0; i < data.length; i++) { int index = data[i] - startingCharacter; if (index < numChars) { int xPos = (index % horizontalCount); int yPos = (index / horizontalCount); if ((i >= startIndex) || (i <= endIndex)) { font.getSprite(xPos, yPos) .draw(x + (i * charWidth), y, col); } } } } catch (UnsupportedEncodingException e) { // Should never happen, ASCII is supported pretty much anywhere Log.error(e); } }
/** * Initialise the GL context */ protected void initGL() { Log.info("Starting display "+width+"x"+height); GL.initDisplay(width, height); if (input == null) { input = new Input(height); } input.init(height); // no need to remove listeners? //input.removeAllListeners(); if (game instanceof InputListener) { input.removeListener((InputListener) game); input.addListener((InputListener) game); } if (graphics != null) { graphics.setDimensions(getWidth(), getHeight()); } lastGame = game; }
/** * Create a new graphics context. Only the container should be doing this * really * * @param width * The width of the screen for this context * @param height * The height of the screen for this context */ public Graphics(int width, int height) { if (DEFAULT_FONT == null) { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { try { DEFAULT_FONT = new AngelCodeFont( "org/newdawn/slick/data/defaultfont.fnt", "org/newdawn/slick/data/defaultfont.png"); } catch (SlickException e) { Log.error(e); } return null; // nothing to return } }); } this.font = DEFAULT_FONT; screenWidth = width; screenHeight = height; }
/** * Check PNG loader property. If set the native PNG loader will * not be used. */ private static void checkProperty() { if (!pngLoaderPropertyChecked) { pngLoaderPropertyChecked = true; try { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { String val = System.getProperty(PNG_LOADER); if ("false".equalsIgnoreCase(val)) { usePngLoader = false; } Log.info("Use Java PNG Loader = " + usePngLoader); return null; } }); } catch (Throwable e) { // ignore, security failure - probably an applet } } }
/** * @see org.newdawn.slick.GameContainer#setMouseCursor(org.newdawn.slick.Image, int, int) */ public void setMouseCursor(Image image, int hotSpotX, int hotSpotY) throws SlickException { 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); } }
/** * Create a new Sound * * @param in The location of the OGG or MOD/XM to load * @param ref The name to associate this stream * @throws SlickException Indicates a failure to load the sound effect */ public Sound(InputStream in, String ref) throws SlickException { SoundStore.get().init(); try { if (ref.toLowerCase().endsWith(".ogg")) { sound = SoundStore.get().getOgg(in); } else if (ref.toLowerCase().endsWith(".wav")) { sound = SoundStore.get().getWAV(in); } else if (ref.toLowerCase().endsWith(".aif")) { sound = SoundStore.get().getAIF(in); } else if (ref.toLowerCase().endsWith(".xm") || ref.toLowerCase().endsWith(".mod")) { sound = SoundStore.get().getMOD(in); } else { throw new SlickException("Only .xm, .mod, .aif, .wav and .ogg are currently supported."); } } catch (Exception e) { Log.error(e); throw new SlickException("Failed to load sound: "+ref); } }
/** * Initialise the PBuffer that will be used to render to * * @throws SlickException */ private void init() throws SlickException { try { Texture tex = InternalTextureLoader.get().createTexture(image.getWidth(), image.getHeight(), image.getFilter()); pbuffer = new Pbuffer(screenWidth, screenHeight, new PixelFormat(8, 0, 0), null, null); // Initialise state of the pbuffer context. pbuffer.makeCurrent(); initGL(); image.draw(0,0); GL11.glBindTexture(GL11.GL_TEXTURE_2D, tex.getTextureID()); GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, 0, 0, tex.getTextureWidth(), tex.getTextureHeight(), 0); image.setTexture(tex); Display.makeCurrent(); } catch (Exception e) { Log.error(e); throw new SlickException("Failed to create PBuffer for dynamic image. OpenGL driver failure?"); } }
/** * Get a cursor based on a set of image data * * @param buf The image data (stored in RGBA) to load the cursor from * @param x The x-coordinate of the cursor hotspot (left -> right) * @param y The y-coordinate of the cursor hotspot (bottom -> top) * @param width The width of the image data provided * @param height The height of the image data provided * @return The create cursor * @throws IOException Indicates a failure to load the image * @throws LWJGLException Indicates a failure to create the hardware cursor */ public Cursor getCursor(ByteBuffer buf,int x,int y,int width,int height) throws IOException, LWJGLException { for (int i=0;i<buf.limit();i+=4) { byte red = buf.get(i); byte green = buf.get(i+1); byte blue = buf.get(i+2); byte alpha = buf.get(i+3); buf.put(i+2, red); buf.put(i+1, green); buf.put(i, blue); buf.put(i+3, alpha); } try { int yspot = height - y - 1; if (yspot < 0) { yspot = 0; } return new Cursor(width,height, x, yspot, 1, buf.asIntBuffer(), null); } catch (Throwable e) { Log.info("Chances are you cursor is too small for this platform"); throw new LWJGLException(e); } }
/** * Get a cursor based on a set of image data * * @param imageData The data from which the cursor can read it's contents * @param x The x-coordinate of the cursor hotspot (left -> right) * @param y The y-coordinate of the cursor hotspot (bottom -> top) * @return The create cursor * @throws IOException Indicates a failure to load the image * @throws LWJGLException Indicates a failure to create the hardware cursor */ public Cursor getCursor(ImageData imageData,int x,int y) throws IOException, LWJGLException { ByteBuffer buf = imageData.getImageBufferData(); for (int i=0;i<buf.limit();i+=4) { byte red = buf.get(i); byte green = buf.get(i+1); byte blue = buf.get(i+2); byte alpha = buf.get(i+3); buf.put(i+2, red); buf.put(i+1, green); buf.put(i, blue); buf.put(i+3, alpha); } try { int yspot = imageData.getHeight() - y - 1; if (yspot < 0) { yspot = 0; } return new Cursor(imageData.getTexWidth(), imageData.getTexHeight(), x, yspot, 1, buf.asIntBuffer(), null); } catch (Throwable e) { Log.info("Chances are you cursor is too small for this platform"); throw new LWJGLException(e); } }
/** * Create an underlying graphics context for the given image * * @param image The image we want to render to * @return The graphics context created * @throws SlickException */ private static Graphics createGraphics(Image image) throws SlickException { init(); if (fbo) { try { return new FBOGraphics(image); } catch (Exception e) { fbo = false; Log.warn("FBO failed in use, falling back to PBuffer"); } } if (pbuffer) { if (pbufferRT) { return new PBufferGraphics(image); } else { return new PBufferUniqueGraphics(image); } } throw new SlickException("Failed to create offscreen buffer even though the card reports it's possible"); }
/** * Initialise the PBuffer that will be used to render to * * @throws SlickException */ private void init() throws SlickException { try { Texture tex = InternalTextureLoader.get().createTexture(image.getWidth(), image.getHeight(), image.getFilter()); final RenderTexture rt = new RenderTexture(false, true, false, false, RenderTexture.RENDER_TEXTURE_2D, 0); pbuffer = new Pbuffer(screenWidth, screenHeight, new PixelFormat(8, 0, 0), rt, null); // Initialise state of the pbuffer context. pbuffer.makeCurrent(); initGL(); GL.glBindTexture(GL11.GL_TEXTURE_2D, tex.getTextureID()); pbuffer.releaseTexImage(Pbuffer.FRONT_LEFT_BUFFER); image.draw(0,0); image.setTexture(tex); Display.makeCurrent(); } catch (Exception e) { Log.error(e); throw new SlickException("Failed to create PBuffer for dynamic image. OpenGL driver failure?"); } }
/** * @see org.newdawn.slick.Graphics#enable() */ protected void enable() { SlickCallable.enterSafeBlock(); try { if (pbuffer.isBufferLost()) { pbuffer.destroy(); init(); } pbuffer.makeCurrent(); } catch (Exception e) { Log.error("Failed to recreate the PBuffer"); throw new RuntimeException(e); } // Put the renderer contents to the texture GL.glBindTexture(GL11.GL_TEXTURE_2D, image.getTexture().getTextureID()); pbuffer.releaseTexImage(Pbuffer.FRONT_LEFT_BUFFER); TextureImpl.unbind(); initGL(); }
/** * @see org.newdawn.slick.Graphics#disable() */ protected void disable() { // Bind the texture after rendering. GL11.glBindTexture(GL11.GL_TEXTURE_2D, image.getTexture().getTextureID()); GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, 0, 0, image.getTexture().getTextureWidth(), image.getTexture().getTextureHeight(), 0); try { Display.makeCurrent(); } catch (LWJGLException e) { Log.error(e); } SlickCallable.leaveSafeBlock(); }
/** * @see org.newdawn.slick.Graphics#enable() */ protected void enable() { SlickCallable.enterSafeBlock(); try { if (pbuffer.isBufferLost()) { pbuffer.destroy(); init(); } pbuffer.makeCurrent(); } catch (Exception e) { Log.error("Failed to recreate the PBuffer"); Log.error(e); throw new RuntimeException(e); } // Put the renderer contents to the texture TextureImpl.unbind(); initGL(); }
/** * Create a new Sound * * @param ref The location of the OGG or MOD/XM to load * @throws SlickException Indicates a failure to load the sound effect */ public Sound(String ref) throws SlickException { SoundStore.get().init(); try { if (ref.toLowerCase().endsWith(".ogg")) { sound = SoundStore.get().getOgg(ref); } else if (ref.toLowerCase().endsWith(".wav")) { sound = SoundStore.get().getWAV(ref); } else if (ref.toLowerCase().endsWith(".aif")) { sound = SoundStore.get().getAIF(ref); } else if (ref.toLowerCase().endsWith(".xm") || ref.toLowerCase().endsWith(".mod")) { sound = SoundStore.get().getMOD(ref); } else { throw new SlickException("Only .xm, .mod, .aif, .wav and .ogg are currently supported."); } } catch (Exception e) { Log.error(e); throw new SlickException("Failed to load sound: "+ref); } }
/** * Create and load a piece of music (either OGG or MOD/XM) * * @param url The location of the music * @param streamingHint A hint to indicate whether streaming should be used if possible * @throws SlickException */ public Music(URL url, boolean streamingHint) throws SlickException { SoundStore.get().init(); String ref = url.getFile(); try { if (ref.toLowerCase().endsWith(".ogg")) { if (streamingHint) { sound = SoundStore.get().getOggStream(url); } else { sound = SoundStore.get().getOgg(url.openStream()); } } else if (ref.toLowerCase().endsWith(".wav")) { sound = SoundStore.get().getWAV(url.openStream()); } else if (ref.toLowerCase().endsWith(".xm") || ref.toLowerCase().endsWith(".mod")) { sound = SoundStore.get().getMOD(url.openStream()); } else if (ref.toLowerCase().endsWith(".aif") || ref.toLowerCase().endsWith(".aiff")) { sound = SoundStore.get().getAIF(url.openStream()); } else { throw new SlickException("Only .xm, .mod, .ogg, and .aif/f are currently supported."); } } catch (Exception e) { Log.error(e); throw new SlickException("Failed to load sound: "+url); } }
/** * @see java.io.InputStream#read(byte[], int, int) */ public int read(byte[] b, int off, int len) throws IOException { for (int i=0;i<len;i++) { try { int value = read(); if (value >= 0) { b[i] = (byte) value; } else { if (i == 0) { return -1; } else { return i; } } } catch (IOException e) { Log.error(e); return i; } } return len; }
/** * Create a duplicate of this system. This would have been nicer as a different interface * but may cause to much API change headache. Maybe next full version release it should be * rethought. * * TODO: Consider refactor at next point release * * @return A copy of this particle system * @throws SlickException Indicates a failure during copy or a invalid particle system to be duplicated */ public ParticleSystem duplicate() throws SlickException { for (int i=0;i<emitters.size();i++) { if (!(emitters.get(i) instanceof ConfigurableEmitter)) { throw new SlickException("Only systems contianing configurable emitters can be duplicated"); } } ParticleSystem theCopy = null; try { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ParticleIO.saveConfiguredSystem(bout, this); ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); theCopy = ParticleIO.loadConfiguredSystem(bin); } catch (IOException e) { Log.error("Failed to duplicate particle system"); throw new SlickException("Unable to duplicated particle system", e); } return theCopy; }
/** * Get the next transition pair that we'lluse * * @return The pair of transitions used to enter and leave the next state */ public Transition[] getNextTransitionPair() { Transition[] pair = new Transition[2]; try { if (transitions[index][0] != null) { pair[0] = (Transition) transitions[index][0].newInstance(); } if (transitions[index][1] != null) { pair[1] = (Transition) transitions[index][1].newInstance(); } } catch (Throwable e) { Log.error(e); } index++; if (index >= transitions.length) { index = 0; } return pair; }
/** * @see org.newdawn.slick.BasicGame#keyPressed(int, char) */ public void keyPressed(int key, char c) { if (key == Input.KEY_ESCAPE) { System.exit(0); } if (key == Input.KEY_F2) { app.setDefaultMouseCursor(); } if (key == Input.KEY_F1) { if (app != null) { try { app.setDisplayMode(640,480,false); } catch (SlickException e) { Log.error(e); } } } }
/** * {@inheritDoc} */ public void setMouseCursor(Image image, int hotSpotX, int hotSpotY) throws SlickException { 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(),temp.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); } }
/** * Sets the {@link #timingPoints} field from a string. * @param s the string */ public void timingPointsFromString(String s) { this.timingPoints = new ArrayList<TimingPoint>(); if (s == null) return; String[] tokens = s.split("\\|"); for (int i = 0; i < tokens.length; i++) { try { timingPoints.add(new TimingPoint(tokens[i])); } catch (Exception e) { Log.warn(String.format("Failed to read timing point '%s'.", tokens[i]), e); } } timingPoints.trimToSize(); }
/** * @see org.newdawn.slick.Graphics#disable() */ protected void disable() { GL.flush(); // Bind the texture after rendering. GL.glBindTexture(GL11.GL_TEXTURE_2D, image.getTexture().getTextureID()); pbuffer.bindTexImage(Pbuffer.FRONT_LEFT_BUFFER); try { Display.makeCurrent(); } catch (LWJGLException e) { Log.error(e); } SlickCallable.leaveSafeBlock(); }