/** @see Font#drawString(float, float, String, Color, int, int) */ public void drawString(float x, float y, String text, Color col, int startIndex, int endIndex) { fontImage.bind(); col.bind(); GL.glTranslatef(x, y, 0); if (displayListCaching && startIndex == 0 && endIndex == text.length() - 1) { DisplayList displayList = (DisplayList) displayLists.get(text + "" + startIndex + "" + endIndex); if (displayList != null) { GL.glCallList(displayList.id); } else { // Compile a new display list. displayList = new DisplayList(); displayList.text = text; int displayListCount = displayLists.size(); if (displayListCount < DISPLAY_LIST_CACHE_SIZE) { displayList.id = baseDisplayListID + displayListCount; } else { displayList.id = eldestDisplayListID; displayLists.remove(eldestDisplayList.text); } displayLists.put(text + "" + startIndex + "" + endIndex, displayList); GL.glNewList(displayList.id, SGL.GL_COMPILE_AND_EXECUTE); render(text, startIndex, endIndex); GL.glEndList(); } } else { render(text, startIndex, endIndex); } GL.glTranslatef(-x, -y, 0); }
/** * Render based on immediate rendering * * @param text The text to be rendered * @param start The index of the first character in the string to render * @param end The index of the last character in the string to render */ private void render(String text, int start, int end) { GL.glBegin(SGL.GL_QUADS); int x = 0, y = 0; CharDef lastCharDef = null; char[] data = text.toCharArray(); for (int i = 0; i < data.length; i++) { int id = data[i]; if (id == '\n') { x = 0; y += getLineHeight(); continue; } if (id >= chars.length) { continue; } CharDef charDef = chars[id]; if (charDef == null) { continue; } if (lastCharDef != null) x += lastCharDef.getKerning(id); lastCharDef = charDef; if ((i >= start) && (i <= end)) { charDef.draw(x, y); } x += charDef.xadvance; } GL.glEnd(); }
public void setBlendMode(int mode) { oldBlendMode = blendMode; blendMode = mode; GL14.glBlendEquation(GL14.GL_FUNC_ADD); if (mode < 100) { g.setDrawMode(mode); return; } try { Reflection.invokePrivateMethod(mPredraw, g); } catch (Exception e) { App.getApp().handle(e); } gl.glEnable(SGL.GL_BLEND); gl.glColorMask(true, true, true, true); if (mode == BM_ADD || mode == BM_SUBTRACT) { gl.glBlendFunc(SGL.GL_SRC_ALPHA, SGL.GL_ONE); if (mode == BM_SUBTRACT) { GL14.glBlendEquation(GL14.GL_FUNC_SUBTRACT); GL14.glBlendEquation(GL14.GL_FUNC_REVERSE_SUBTRACT); } } try { Reflection.invokePrivateMethod(mPostdraw, g); } catch (Exception e) { App.getApp().handle(e); } }
/** * Draw the outline of the given shape. Only the vertices are set. The colour has to be set * independently of this method. * * @param shape The shape to draw. * @param fill The fill to apply */ public static final void draw(Shape shape, ShapeFill fill) { float points[] = shape.getPoints(); Texture t = TextureImpl.getLastBind(); TextureImpl.bindNone(); float center[] = shape.getCenter(); GL.glBegin(SGL.GL_LINE_STRIP); for (int i = 0; i < points.length; i += 2) { fill.colorAt(shape, points[i], points[i + 1]).bind(); Vector2f offset = fill.getOffsetAt(shape, points[i], points[i + 1]); GL.glVertex2f(points[i] + offset.x, points[i + 1] + offset.y); } if (shape.closed()) { fill.colorAt(shape, points[0], points[1]).bind(); Vector2f offset = fill.getOffsetAt(shape, points[0], points[1]); GL.glVertex2f(points[0] + offset.x, points[1] + offset.y); } GL.glEnd(); if (t == null) { TextureImpl.bindNone(); } else { t.bind(); } }
/** * Uploads the pixel data to the given texture at the specified position. This only needs to be * called once, after the pixel data has changed. * * @param texture the texture to modify * @param x the x position to place the pixel data on the texture * @param y the y position to place the pixel data on the texture */ public void apply(Texture texture, int x, int y) { if (x + width > texture.getTextureWidth() || y + height > texture.getTextureHeight()) throw new IndexOutOfBoundsException("pixel data won't fit in given texture"); position(length()); pixels.flip(); int glFmt = format.getOGLType(); final SGL GL = Renderer.get(); texture.bind(); GL.glTexSubImage2D( SGL.GL_TEXTURE_2D, 0, x, y, width, height, glFmt, SGL.GL_UNSIGNED_BYTE, pixels); }
/** * Draw the the given shape filled in. Only the vertices are set. The colour has to be set * independently of this method. * * @param shape The shape to fill. * @param callback The callback that will be invoked for each shape point */ private static final void fill(Shape shape, PointCallback callback) { Triangulator tris = shape.getTriangles(); GL.glBegin(SGL.GL_TRIANGLES); for (int i = 0; i < tris.getTriangleCount(); i++) { for (int p = 0; p < 3; p++) { float[] pt = tris.getTrianglePoint(i, p); float[] np = callback.preRenderPoint(shape, pt[0], pt[1]); if (np == null) { GL.glVertex2f(pt[0], pt[1]); } else { GL.glVertex2f(np[0], np[1]); } } } GL.glEnd(); }
public void resetAnimState() { if (stateNew == null) return; if (stateNew.scaleH != 1 || stateNew.scaleV != 1) g.scale(stateNew.scaleH, stateNew.scaleV); if (stateNew.angle != 0) gl.glRotatef(stateNew.angle, 0f, 0f, 1f); if (stateNew.pos.x != 0 || stateNew.pos.y != 0) g.translate(stateNew.pos.x, stateNew.pos.y); Color.white.bind(); g.setColor(stateColor); stateNew = null; }
public void setAnimState(AnimState state) { if (state != null) resetAnimState(); getPrivates(); stateColor = g.getColor(); stateNew = new AnimState(state); g.setColor(state.color); state.color.bind(); if (state.pos.x != 0 || state.pos.y != 0) g.translate(-state.pos.x, -state.pos.y); if (state.angle != 0) gl.glRotatef(-state.angle, 0f, 0f, 1f); if (state.scaleH != 1 || state.scaleV != 1) g.scale(1f / state.scaleH, 1f / state.scaleV); }
/** * @see org.newdawn.slick.Game#render(org.newdawn.slick.GameContainer, org.newdawn.slick.Graphics) */ public final void render(GameContainer container, Graphics g) throws SlickException { int yoffset = 0; int xoffset = 0; if (targetHeight < container.getHeight()) { yoffset = (container.getHeight() - targetHeight) / 2; } if (targetWidth < container.getWidth()) { xoffset = (container.getWidth() - targetWidth) / 2; } SlickCallable.enterSafeBlock(); g.setClip(xoffset, yoffset, targetWidth, targetHeight); GL.glTranslatef(xoffset, yoffset, 0); g.scale(targetWidth / normalWidth, targetHeight / normalHeight); GL.glPushMatrix(); held.render(container, g); GL.glPopMatrix(); g.clearClip(); SlickCallable.leaveSafeBlock(); renderOverlay(container, g); }
public void drawRectangleGradient( Vector2f p1, Vector2f p2, Color topLeft, Color topRight, Color bottomLeft, Color bottomRight) { getPrivates(); try { Reflection.invokePrivateMethod(mPredraw, g); } catch (Exception e) { App.getApp().handle(e); } TextureImpl.bindNone(); Color.white.bind(); GL11.glBegin(GL11.GL_POLYGON); Color c; c = topLeft; gl.glColor4f(c.r, c.g, c.b, c.a); gl.glVertex2f(p1.x, p1.y); c = topRight; gl.glColor4f(c.r, c.g, c.b, c.a); gl.glVertex2f(p2.x, p1.y); c = bottomRight; gl.glColor4f(c.r, c.g, c.b, c.a); gl.glVertex2f(p2.x, p2.y); c = bottomLeft; gl.glColor4f(c.r, c.g, c.b, c.a); gl.glVertex2f(p1.x, p2.y); gl.glEnd(); try { Reflection.invokePrivateMethod(mPostdraw, g); } catch (Exception e) { App.getApp().handle(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; }
public void drawTriangle(Vector2f p1, Vector2f p2, Vector2f p3, Color c1, Color c2, Color c3) { getPrivates(); try { Reflection.invokePrivateMethod(mPredraw, g); } catch (Exception e) { App.getApp().handle(e); } TextureImpl.bindNone(); Color.white.bind(); gl.glBegin(SGL.GL_TRIANGLES); gl.glColor4f(c1.r, c1.g, c1.b, c1.a); gl.glVertex2f(p1.x, p1.y); gl.glColor4f(c2.r, c2.g, c2.b, c2.a); gl.glVertex2f(p2.x, p2.y); gl.glColor4f(c3.r, c3.g, c3.b, c3.a); gl.glVertex2f(p3.x, p3.y); gl.glEnd(); try { Reflection.invokePrivateMethod(mPostdraw, g); } catch (Exception e) { App.getApp().handle(e); } }
/** * Render the particles in the system * * @param x The x coordinate to render the particle system at (in the current coordinate space) * @param y The y coordinate to render the particle system at (in the current coordiante space) */ public void render(float x, float y) { if ((sprite == null) && (defaultImageName != null)) { loadSystemParticleImage(); } if (!visible) { return; } GL.glTranslatef(x, y, 0); if (blendingMode == BLEND_ADDITIVE) { GL.glBlendFunc(SGL.GL_SRC_ALPHA, SGL.GL_ONE); } if (usePoints()) { GL.glEnable(SGL.GL_POINT_SMOOTH); TextureImpl.bindNone(); } // iterate over all emitters for (int emitterIdx = 0; emitterIdx < emitters.size(); emitterIdx++) { // get emitter ParticleEmitter emitter = (ParticleEmitter) emitters.get(emitterIdx); // check for additive override and enable when set if (emitter.useAdditive()) { GL.glBlendFunc(SGL.GL_SRC_ALPHA, SGL.GL_ONE); } // now get the particle pool for this emitter and render all particles that are in use ParticlePool pool = (ParticlePool) particlesByEmitter.get(emitter); Image image = emitter.getImage(); if (image == null) { image = this.sprite; } if (!emitter.isOriented() && !emitter.usePoints(this)) { image.startUse(); } for (int i = 0; i < pool.particles.length; i++) { if (pool.particles[i].inUse()) pool.particles[i].render(); } if (!emitter.isOriented() && !emitter.usePoints(this)) { image.endUse(); } // reset additive blend mode if (emitter.useAdditive()) { GL.glBlendFunc(SGL.GL_SRC_ALPHA, SGL.GL_ONE_MINUS_SRC_ALPHA); } } if (usePoints()) { GL.glDisable(SGL.GL_POINT_SMOOTH); } if (blendingMode == BLEND_ADDITIVE) { GL.glBlendFunc(SGL.GL_SRC_ALPHA, SGL.GL_ONE_MINUS_SRC_ALPHA); } Color.white.bind(); GL.glTranslatef(-x, -y, 0); }
/** * Parse the font definition file * * @param fntFile The stream from which the font file can be read * @throws SlickException */ private void parseFnt(InputStream fntFile) throws SlickException { if (displayListCaching) { baseDisplayListID = GL.glGenLists(DISPLAY_LIST_CACHE_SIZE); if (baseDisplayListID == 0) displayListCaching = false; } try { // now parse the font file BufferedReader in = new BufferedReader(new InputStreamReader(fntFile)); String info = in.readLine(); String common = in.readLine(); String page = in.readLine(); Map kerning = new HashMap(64); List charDefs = new ArrayList(MAX_CHAR); int maxChar = 0; boolean done = false; while (!done) { String line = in.readLine(); if (line == null) { done = true; } else { if (line.startsWith("chars c")) { // ignore } else if (line.startsWith("char")) { CharDef def = parseChar(line); if (def != null) { maxChar = Math.max(maxChar, def.id); charDefs.add(def); } } if (line.startsWith("kernings c")) { // ignore } else if (line.startsWith("kerning")) { StringTokenizer tokens = new StringTokenizer(line, " ="); tokens.nextToken(); // kerning tokens.nextToken(); // first short first = Short.parseShort(tokens.nextToken()); // first value tokens.nextToken(); // second int second = Integer.parseInt(tokens.nextToken()); // second value tokens.nextToken(); // offset int offset = Integer.parseInt(tokens.nextToken()); // offset value List values = (List) kerning.get(new Short(first)); if (values == null) { values = new ArrayList(); kerning.put(new Short(first), values); } // Pack the character and kerning offset into a short. values.add(new Short((short) ((offset << 8) | second))); } } } chars = new CharDef[maxChar + 1]; for (Iterator iter = charDefs.iterator(); iter.hasNext(); ) { CharDef def = (CharDef) iter.next(); chars[def.id] = def; } // Turn each list of kerning values into a short[] and set on the chardef. for (Iterator iter = kerning.entrySet().iterator(); iter.hasNext(); ) { Entry entry = (Entry) iter.next(); short first = ((Short) entry.getKey()).shortValue(); List valueList = (List) entry.getValue(); short[] valueArray = new short[valueList.size()]; int i = 0; for (Iterator valueIter = valueList.iterator(); valueIter.hasNext(); i++) valueArray[i] = ((Short) valueIter.next()).shortValue(); chars[first].kerning = valueArray; } } catch (IOException e) { Log.error(e); throw new SlickException("Failed to parse font file: " + fntFile); } }
/** * Enter the orthographic mode * * @param xsize The size of the panel being used * @param ysize The size of the panel being used */ protected void enterOrtho(int xsize, int ysize) { GL.enterOrtho(xsize, ysize); }
/** * Update and render the game * * @param delta The change in time since last update and render * @throws SlickException Indicates an internal fault to the game. */ protected void updateAndRender(int delta) throws SlickException { if (smoothDeltas) { if (getFPS() != 0) { delta = 1000 / getFPS(); } } input.poll(width, height); Music.poll(delta); if (!paused) { storedDelta += delta; if (storedDelta >= minimumLogicInterval) { try { if (maximumLogicInterval != 0) { long cycles = storedDelta / maximumLogicInterval; for (int i = 0; i < cycles; i++) { game.update(this, (int) maximumLogicInterval); } int remainder = (int) (storedDelta % maximumLogicInterval); if (remainder > minimumLogicInterval) { game.update(this, (int) (remainder % maximumLogicInterval)); storedDelta = 0; } else { storedDelta = remainder; } } else { game.update(this, (int) storedDelta); storedDelta = 0; } } catch (Throwable e) { // Log.error(e); throw new SlickException("Game.update() failure.", e); } } } else { game.update(this, 0); } if (hasFocus() || getAlwaysRender()) { if (clearEachFrame) { GL.glClear(SGL.GL_COLOR_BUFFER_BIT | SGL.GL_DEPTH_BUFFER_BIT); } GL.glLoadIdentity(); graphics.resetTransform(); graphics.resetFont(); graphics.resetLineWidth(); graphics.setAntiAlias(false); try { game.render(this, graphics); } catch (Throwable e) { // Log.error(e); throw new SlickException("Game.render() failure.", e); } graphics.resetTransform(); if (showFPS) { defaultFont.drawString(10, 10, "FPS: " + recordedFPS); } GL.flush(); } if (targetFPS != -1) { Display.sync(targetFPS); } }