1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-11-18 06:35:12 +00:00

the hyperroid subdirectory was incorrectly named hydroid

This commit is contained in:
Zeno Rogue
2017-03-23 14:18:11 +01:00
parent cd34d9b990
commit 6978d4bc65
51 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,420 @@
// taken from Texample,
// http://fractiousg.blogspot.com/201/4/rendering-text-in-opengl-on-android.html
// Zeno Rogue's modifications (for HyperRogue 4.2):
// * to provide a Typeface as an argument, instead of Assets
// * drawAlign to provide alignment in HyperRogue-compatible fashion
// For HyperRogue 5.3:
// * Unicode characters
// This is a OpenGL ES 1.0 dynamic font rendering system. It loads actual font
// files, generates a font map (texture) from them, and allows rendering of
// text strings.
//
// NOTE: the rendering portions of this class uses a sprite batcher in order
// provide decent speed rendering. Also, rendering assumes a BOTTOM-LEFT
// origin, and the (x,y) positions are relative to that, as well as the
// bottom-left of the string to render.
package com.android.texample;
import javax.microedition.khronos.opengles.GL10;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.opengl.GLUtils;
public class GLText {
//
StringBuffer allchars;
void buildAllchars() {
allchars = new StringBuffer();
for(char c=32; c<=126; c++)
allchars.append(c);
allchars.append("°´ÁÄÇÉÍÎÖÚÜßáâäçèéìíîóöøùúüýąćČčĎďĘęĚěğİıŁłńňŘřŚśŞşŠšťůŹźŻżŽžϕЁАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяё");
}
int numChars() {
return allchars.length() + 1;
}
int charIndex(char c) {
int l = allchars.length();
for(int i=0; i<l; i++)
if(allchars.charAt(i) == c)
return i;
return allchars.length();
}
//--Constants--//
public final static char CHAR_NONE = '?'; // Character to Use for Unknown (ASCII Code)
public final static int FONT_SIZE_MIN = 6; // Minumum Font Size (Pixels)
public final static int FONT_SIZE_MAX = 180; // Maximum Font Size (Pixels)
public final static int CHAR_BATCH_SIZE = 100; // Number of Characters to Render Per Batch
//--Members--//
GL10 gl; // GL10 Instance
AssetManager assets; // Asset Manager
SpriteBatch batch; // Batch Renderer
int fontPadX, fontPadY; // Font Padding (Pixels; On Each Side, ie. Doubled on Both X+Y Axis)
float fontHeight; // Font Height (Actual; Pixels)
float fontAscent; // Font Ascent (Above Baseline; Pixels)
float fontDescent; // Font Descent (Below Baseline; Pixels)
int textureId; // Font Texture ID [NOTE: Public for Testing Purposes Only!]
int textureSize; // Texture Size for Font (Square) [NOTE: Public for Testing Purposes Only!]
TextureRegion textureRgn; // Full Texture Region
float charWidthMax; // Character Width (Maximum; Pixels)
float charHeight; // Character Height (Maximum; Pixels)
final float[] charWidths; // Width of Each Character (Actual; Pixels)
TextureRegion[] charRgn; // Region of Each Character (Texture Coordinates)
int cellWidth, cellHeight; // Character Cell Width/Height
int rowCnt, colCnt; // Number of Rows/Columns
float scaleX, scaleY; // Font Scale (X,Y Axis)
float spaceX; // Additional (X,Y Axis) Spacing (Unscaled)
//--Constructor--//
// D: save GL instance + asset manager, create arrays, and initialize the members
// A: gl - OpenGL ES 10 Instance
public GLText(GL10 gl) {
this.gl = gl; // Save the GL10 Instance
buildAllchars();
batch = new SpriteBatch( gl, CHAR_BATCH_SIZE ); // Create Sprite Batch (with Defined Size)
charWidths = new float[numChars()]; // Create the Array of Character Widths
charRgn = new TextureRegion[numChars()]; // Create the Array of Character Regions
// initialize remaining members
fontPadX = 0;
fontPadY = 0;
fontHeight = 0.0f;
fontAscent = 0.0f;
fontDescent = 0.0f;
textureId = -1;
textureSize = 0;
charWidthMax = 0;
charHeight = 0;
cellWidth = 0;
cellHeight = 0;
rowCnt = 0;
colCnt = 0;
scaleX = 1.0f; // Default Scale = 1 (Unscaled)
scaleY = 1.0f; // Default Scale = 1 (Unscaled)
spaceX = 0.0f;
}
//--Load Font--//
// description
// this will load the specified font file, create a texture for the defined
// character range, and setup all required values used to render with it.
// arguments:
// file - Filename of the font (.ttf, .otf) to use. In 'Assets' folder.
// size - Requested pixel size of font (height)
// padX, padY - Extra padding per character (X+Y Axis); to prevent overlapping characters.
public boolean load(Typeface tf, int size, int padX, int padY) {
// setup requested values
fontPadX = padX; // Set Requested X Axis Padding
fontPadY = padY; // Set Requested Y Axis Padding
// load the font and setup paint instance for drawing
// Typeface tf = Typeface.createFromAsset( assets, file ); // Create the Typeface from Font File
Paint paint = new Paint(); // Create Android Paint Instance
paint.setAntiAlias( true ); // Enable Anti Alias
paint.setTextSize( size ); // Set Text Size
paint.setColor( 0xffffffff ); // Set ARGB (White, Opaque)
// paint.setTypeface( tf ); // Set Typeface
paint.setTypeface(tf);
// get font metrics
Paint.FontMetrics fm = paint.getFontMetrics(); // Get Font Metrics
fontHeight = (float)Math.ceil( Math.abs( fm.bottom ) + Math.abs( fm.top ) ); // Calculate Font Height
fontAscent = (float)Math.ceil( Math.abs( fm.ascent ) ); // Save Font Ascent
fontDescent = (float)Math.ceil( Math.abs( fm.descent ) ); // Save Font Descent
// determine the width of each character (including unknown character)
// also determine the maximum character width
char[] s = new char[2]; // Create Character Array
charWidthMax = charHeight = 0; // Reset Character Width/Height Maximums
float[] w = new float[2]; // Working Width Value
int cnt = 0; // Array Counter
for ( int i=0; i<allchars.length(); i++ ) { // FOR Each Character
s[0] = allchars.charAt(i); // Set Character
paint.getTextWidths( s, 0, 1, w ); // Get Character Bounds
charWidths[cnt] = w[0]; // Get Width
if ( charWidths[cnt] > charWidthMax ) // IF Width Larger Than Max Width
charWidthMax = charWidths[cnt]; // Save New Max Width
cnt++; // Advance Array Counter
}
s[0] = CHAR_NONE; // Set Unknown Character
paint.getTextWidths( s, 0, 1, w ); // Get Character Bounds
charWidths[cnt] = w[0]; // Get Width
if ( charWidths[cnt] > charWidthMax ) // IF Width Larger Than Max Width
charWidthMax = charWidths[cnt]; // Save New Max Width
cnt++; // Advance Array Counter
// set character height to font height
charHeight = fontHeight; // Set Character Height
// find the maximum size, validate, and setup cell sizes
cellWidth = (int)charWidthMax + ( 2 * fontPadX ); // Set Cell Width
cellHeight = (int)charHeight + ( 2 * fontPadY ); // Set Cell Height
int maxSize = cellWidth > cellHeight ? cellWidth : cellHeight; // Save Max Size (Width/Height)
if ( maxSize < FONT_SIZE_MIN || maxSize > FONT_SIZE_MAX ) // IF Maximum Size Outside Valid Bounds
return false; // Return Error
// set texture size based on max font size (width or height)
// NOTE: these values are fixed, based on the defined characters. when
// changing start/end characters (CHAR_START/CHAR_END) this will need adjustment too!
if ( maxSize <= 24 ) // IF Max Size is 18 or Less
textureSize = 256; // Set 256 Texture Size
else if ( maxSize <= 40 ) // ELSE IF Max Size is 40 or Less
textureSize = 512; // Set 512 Texture Size
else if ( maxSize <= 80 ) // ELSE IF Max Size is 80 or Less
textureSize = 1024; // Set 1024 Texture Size
else // ELSE IF Max Size is Larger Than 80 (and Less than FONT_SIZE_MAX)
textureSize = 2048; // Set 2048 Texture Size
// create an empty bitmap (alpha only)
Bitmap bitmap = Bitmap.createBitmap( textureSize, textureSize, Bitmap.Config.ALPHA_8 ); // Create Bitmap
Canvas canvas = new Canvas( bitmap ); // Create Canvas for Rendering to Bitmap
bitmap.eraseColor( 0x00000000 ); // Set Transparent Background (ARGB)
// calculate rows/columns
// NOTE: while not required for anything, these may be useful to have :)
colCnt = textureSize / cellWidth; // Calculate Number of Columns
rowCnt = (int)Math.ceil( (float)numChars() / (float)colCnt ); // Calculate Number of Rows
// render each of the characters to the canvas (ie. build the font map)
float x = fontPadX; // Set Start Position (X)
float y = ( cellHeight - 1 ) - fontDescent - fontPadY; // Set Start Position (Y)
for (int i=0; i<allchars.length(); i++) { // FOR Each Character
s[0] = allchars.charAt(i); // Set Character to Draw
canvas.drawText( s, 0, 1, x, y, paint ); // Draw Character
x += cellWidth; // Move to Next Character
if ( ( x + cellWidth - fontPadX ) > textureSize ) { // IF End of Line Reached
x = fontPadX; // Set X for New Row
y += cellHeight; // Move Down a Row
}
}
s[0] = CHAR_NONE; // Set Character to Use for NONE
canvas.drawText( s, 0, 1, x, y, paint ); // Draw Character
// generate a new texture
int[] textureIds = new int[1]; // Array to Get Texture Id
gl.glGenTextures( 1, textureIds, 0 ); // Generate New Texture
textureId = textureIds[0]; // Save Texture Id
// setup filters for texture
gl.glBindTexture( GL10.GL_TEXTURE_2D, textureId ); // Bind Texture
gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST ); // Set Minification Filter
gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR ); // Set Magnification Filter
gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE ); // Set U Wrapping
gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE ); // Set V Wrapping
// load the generated bitmap onto the texture
GLUtils.texImage2D( GL10.GL_TEXTURE_2D, 0, bitmap, 0 ); // Load Bitmap to Texture
gl.glBindTexture( GL10.GL_TEXTURE_2D, 0 ); // Unbind Texture
// release the bitmap
bitmap.recycle(); // Release the Bitmap
// setup the array of character texture regions
x = 0; // Initialize X
y = 0; // Initialize Y
for ( int c = 0; c < numChars(); c++ ) { // FOR Each Character (On Texture)
charRgn[c] = new TextureRegion( textureSize, textureSize, x, y, cellWidth-1, cellHeight-1 ); // Create Region for Character
x += cellWidth; // Move to Next Char (Cell)
if ( x + cellWidth > textureSize ) {
x = 0; // Reset X Position to Start
y += cellHeight; // Move to Next Row (Cell)
}
}
// create full texture region
textureRgn = new TextureRegion( textureSize, textureSize, 0, 0, textureSize, textureSize ); // Create Full Texture Region
// return success
return true; // Return Success
}
//--Begin/End Text Drawing--//
// D: call these methods before/after (respectively all draw() calls using a text instance
// NOTE: color is set on a per-batch basis, and fonts should be 8-bit alpha only!!!
// A: red, green, blue - RGB values for font (default = 1.0)
// alpha - optional alpha value for font (default = 1.0)
// R: [none]
public void begin() {
begin( 1.0f, 1.0f, 1.0f, 1.0f ); // Begin with White Opaque
}
public void begin(float alpha) {
begin( 1.0f, 1.0f, 1.0f, alpha ); // Begin with White (Explicit Alpha)
}
public void begin(float red, float green, float blue, float alpha) {
gl.glColor4f( red, green, blue, alpha ); // Set Color+Alpha
gl.glBindTexture( GL10.GL_TEXTURE_2D, textureId ); // Bind the Texture
batch.beginBatch(); // Begin Batch
}
public void end() {
batch.endBatch(); // End Batch
gl.glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); // Restore Default Color/Alpha
}
//--Draw Text--//
// D: draw text at the specified x,y position
// A: text - the string to draw
// x, y - the x,y position to draw text at (bottom left of text; including descent)
// R: [none]
public void draw(String text, float x, float y) {
float chrHeight = cellHeight * scaleY; // Calculate Scaled Character Height
float chrWidth = cellWidth * scaleX; // Calculate Scaled Character Width
int len = text.length(); // Get String Length
x += ( chrWidth / 2.0f ) - ( fontPadX * scaleX ); // Adjust Start X
y += ( chrHeight / 2.0f ) - ( fontPadY * scaleY ); // Adjust Start Y
for ( int i = 0; i < len; i++ ) { // FOR Each Character in String
int c = charIndex(text.charAt( i )); // Calculate Character Index (Offset by First Char in Font)
batch.drawSprite( x, y, chrWidth, chrHeight, charRgn[c] ); // Draw the Character
x += ( charWidths[c] + spaceX ) * scaleX; // Advance X Position by Scaled Character Width
}
}
//--Draw Text Centered--//
// D: draw text CENTERED at the specified x,y position
// A: text - the string to draw
// x, y - the x,y position to draw text at (bottom left of text)
// R: the total width of the text that was drawn
public float drawC(String text, float x, float y) {
float len = getLength( text ); // Get Text Length
draw( text, x - ( len / 2.0f ), y - ( getCharHeight() / 2.0f ) ); // Draw Text Centered
return len; // Return Length
}
public float drawCX(String text, float x, float y) {
float len = getLength( text ); // Get Text Length
draw( text, x - ( len / 2.0f ), y ); // Draw Text Centered (X-Axis Only)
return len; // Return Length
}
public void drawCY(String text, float x, float y) {
draw( text, x, y - ( getCharHeight() / 2.0f ) ); // Draw Text Centered (Y-Axis Only)
}
public void drawAlign(String text, float x, float y, int align) {
float len = getLength( text ); // Get Text Length
draw( text, x - len * (align / 16.0f), y - ( getCharHeight() / 2.0f ) ); // Draw Text Centered (Y-Axis Only)
}
//--Set Scale--//
// D: set the scaling to use for the font
// A: scale - uniform scale for both x and y axis scaling
// sx, sy - separate x and y axis scaling factors
// R: [none]
public void setScale(float scale) {
scaleX = scaleY = scale; // Set Uniform Scale
}
public void setScale(float sx, float sy) {
scaleX = sx; // Set X Scale
scaleY = sy; // Set Y Scale
}
//--Get Scale--//
// D: get the current scaling used for the font
// A: [none]
// R: the x/y scale currently used for scale
public float getScaleX() {
return scaleX; // Return X Scale
}
public float getScaleY() {
return scaleY; // Return Y Scale
}
//--Set Space--//
// D: set the spacing (unscaled; ie. pixel size) to use for the font
// A: space - space for x axis spacing
// R: [none]
public void setSpace(float space) {
spaceX = space; // Set Space
}
//--Get Space--//
// D: get the current spacing used for the font
// A: [none]
// R: the x/y space currently used for scale
public float getSpace() {
return spaceX; // Return X Space
}
//--Get Length of a String--//
// D: return the length of the specified string if rendered using current settings
// A: text - the string to get length for
// R: the length of the specified string (pixels)
public float getLength(String text) {
float len = 0.0f; // Working Length
int strLen = text.length(); // Get String Length (Characters)
for ( int i = 0; i < strLen; i++ ) { // For Each Character in String (Except Last
int c = charIndex(text.charAt( i )); // Calculate Character Index (Offset by First Char in Font)
len += ( charWidths[c] * scaleX ); // Add Scaled Character Width to Total Length
}
len += ( strLen > 1 ? ( ( strLen - 1 ) * spaceX ) * scaleX : 0 ); // Add Space Length
return len; // Return Total Length
}
//--Get Width/Height of Character--//
// D: return the scaled width/height of a character, or max character width
// NOTE: since all characters are the same height, no character index is required!
// NOTE: excludes spacing!!
// A: chr - the character to get width for
// R: the requested character size (scaled)
public float getCharWidth(char chr) {
return ( charWidths[charIndex(chr)] * scaleX ); // Return Scaled Character Width
}
public float getCharWidthMax() {
return ( charWidthMax * scaleX ); // Return Scaled Max Character Width
}
public float getCharHeight() {
return ( charHeight * scaleY ); // Return Scaled Character Height
}
//--Get Font Metrics--//
// D: return the specified (scaled) font metric
// A: [none]
// R: the requested font metric (scaled)
public float getAscent() {
return ( fontAscent * scaleY ); // Return Font Ascent
}
public float getDescent() {
return ( fontDescent * scaleY ); // Return Font Descent
}
public float getHeight() {
return ( fontHeight * scaleY ); // Return Font Height (Actual)
}
//--Draw Font Texture--//
// D: draw the entire font texture (NOTE: for testing purposes only)
// A: width, height - the width and height of the area to draw to. this is used
// to draw the texture to the top-left corner.
public void drawTexture(int width, int height) {
batch.beginBatch( textureId ); // Begin Batch (Bind Texture)
batch.drawSprite( textureSize / 2, height - ( textureSize / 2 ), textureSize, textureSize, textureRgn ); // Draw
batch.endBatch(); // End Batch
}
}

View File

@@ -0,0 +1,125 @@
// taken from Texample,
// http://fractiousg.blogspot.com/201/4/rendering-text-in-opengl-on-android.html
package com.android.texample;
// import android.util.FloatMath;
import javax.microedition.khronos.opengles.GL10;
public class SpriteBatch {
//--Constants--//
final static int VERTEX_SIZE = 4; // Vertex Size (in Components) ie. (X,Y,U,V)
final static int VERTICES_PER_SPRITE = 4; // Vertices Per Sprite
final static int INDICES_PER_SPRITE = 6; // Indices Per Sprite
//--Members--//
GL10 gl; // GL Instance
Vertices vertices; // Vertices Instance Used for Rendering
float[] vertexBuffer; // Vertex Buffer
int bufferIndex; // Vertex Buffer Start Index
int maxSprites; // Maximum Sprites Allowed in Buffer
int numSprites; // Number of Sprites Currently in Buffer
//--Constructor--//
// D: prepare the sprite batcher for specified maximum number of sprites
// A: gl - the gl instance to use for rendering
// maxSprites - the maximum allowed sprites per batch
public SpriteBatch(GL10 gl, int maxSprites) {
this.gl = gl; // Save GL Instance
this.vertexBuffer = new float[maxSprites * VERTICES_PER_SPRITE * VERTEX_SIZE]; // Create Vertex Buffer
this.vertices = new Vertices( gl, maxSprites * VERTICES_PER_SPRITE, maxSprites * INDICES_PER_SPRITE, false, true, false ); // Create Rendering Vertices
this.bufferIndex = 0; // Reset Buffer Index
this.maxSprites = maxSprites; // Save Maximum Sprites
this.numSprites = 0; // Clear Sprite Counter
short[] indices = new short[maxSprites * INDICES_PER_SPRITE]; // Create Temp Index Buffer
int len = indices.length; // Get Index Buffer Length
short j = 0; // Counter
for ( int i = 0; i < len; i+= INDICES_PER_SPRITE, j += VERTICES_PER_SPRITE ) { // FOR Each Index Set (Per Sprite)
indices[i + 0] = (short)( j + 0 ); // Calculate Index 0
indices[i + 1] = (short)( j + 1 ); // Calculate Index 1
indices[i + 2] = (short)( j + 2 ); // Calculate Index 2
indices[i + 3] = (short)( j + 2 ); // Calculate Index 3
indices[i + 4] = (short)( j + 3 ); // Calculate Index 4
indices[i + 5] = (short)( j + 0 ); // Calculate Index 5
}
vertices.setIndices( indices, 0, len ); // Set Index Buffer for Rendering
}
//--Begin Batch--//
// D: signal the start of a batch. set the texture and clear buffer
// NOTE: the overloaded (non-texture) version assumes that the texture is already bound!
// A: textureId - the ID of the texture to use for the batch
// R: [none]
public void beginBatch(int textureId) {
gl.glBindTexture( GL10.GL_TEXTURE_2D, textureId ); // Bind the Texture
numSprites = 0; // Empty Sprite Counter
bufferIndex = 0; // Reset Buffer Index (Empty)
}
public void beginBatch() {
numSprites = 0; // Empty Sprite Counter
bufferIndex = 0; // Reset Buffer Index (Empty)
}
//--End Batch--//
// D: signal the end of a batch. render the batched sprites
// A: [none]
// R: [none]
public void endBatch() {
if ( numSprites > 0 ) { // IF Any Sprites to Render
vertices.setVertices( vertexBuffer, 0, bufferIndex ); // Set Vertices from Buffer
vertices.bind(); // Bind Vertices
vertices.draw( GL10.GL_TRIANGLES, 0, numSprites * INDICES_PER_SPRITE ); // Render Batched Sprites
vertices.unbind(); // Unbind Vertices
}
}
//--Draw Sprite to Batch--//
// D: batch specified sprite to batch. adds vertices for sprite to vertex buffer
// NOTE: MUST be called after beginBatch(), and before endBatch()!
// NOTE: if the batch overflows, this will render the current batch, restart it,
// and then batch this sprite.
// A: x, y - the x,y position of the sprite (center)
// width, height - the width and height of the sprite
// region - the texture region to use for sprite
// R: [none]
public void drawSprite(float x, float y, float width, float height, TextureRegion region) {
if ( numSprites == maxSprites ) { // IF Sprite Buffer is Full
endBatch(); // End Batch
// NOTE: leave current texture bound!!
numSprites = 0; // Empty Sprite Counter
bufferIndex = 0; // Reset Buffer Index (Empty)
}
float halfWidth = width / 2.0f; // Calculate Half Width
float halfHeight = height / 2.0f; // Calculate Half Height
float x1 = x - halfWidth; // Calculate Left X
float y1 = y - halfHeight; // Calculate Bottom Y
float x2 = x + halfWidth; // Calculate Right X
float y2 = y + halfHeight; // Calculate Top Y
vertexBuffer[bufferIndex++] = x1; // Add X for Vertex 0
vertexBuffer[bufferIndex++] = y1; // Add Y for Vertex 0
vertexBuffer[bufferIndex++] = region.u1; // Add U for Vertex 0
vertexBuffer[bufferIndex++] = region.v2; // Add V for Vertex 0
vertexBuffer[bufferIndex++] = x2; // Add X for Vertex 1
vertexBuffer[bufferIndex++] = y1; // Add Y for Vertex 1
vertexBuffer[bufferIndex++] = region.u2; // Add U for Vertex 1
vertexBuffer[bufferIndex++] = region.v2; // Add V for Vertex 1
vertexBuffer[bufferIndex++] = x2; // Add X for Vertex 2
vertexBuffer[bufferIndex++] = y2; // Add Y for Vertex 2
vertexBuffer[bufferIndex++] = region.u2; // Add U for Vertex 2
vertexBuffer[bufferIndex++] = region.v1; // Add V for Vertex 2
vertexBuffer[bufferIndex++] = x1; // Add X for Vertex 3
vertexBuffer[bufferIndex++] = y2; // Add Y for Vertex 3
vertexBuffer[bufferIndex++] = region.u1; // Add U for Vertex 3
vertexBuffer[bufferIndex++] = region.v1; // Add V for Vertex 3
numSprites++; // Increment Sprite Count
}
}

View File

@@ -0,0 +1,23 @@
// taken from Texample,
// http://fractiousg.blogspot.com/201/4/rendering-text-in-opengl-on-android.html
package com.android.texample;
class TextureRegion {
//--Members--//
public float u1, v1; // Top/Left U,V Coordinates
public float u2, v2; // Bottom/Right U,V Coordinates
//--Constructor--//
// D: calculate U,V coordinates from specified texture coordinates
// A: texWidth, texHeight - the width and height of the texture the region is for
// x, y - the top/left (x,y) of the region on the texture (in pixels)
// width, height - the width and height of the region on the texture (in pixels)
public TextureRegion(float texWidth, float texHeight, float x, float y, float width, float height) {
this.u1 = x / texWidth; // Calculate U1
this.v1 = y / texHeight; // Calculate V1
this.u2 = this.u1 + ( width / texWidth ); // Calculate U2
this.v2 = this.v1 + ( height / texHeight ); // Calculate V2
}
}

View File

@@ -0,0 +1,264 @@
// taken from Texample,
// http://fractiousg.blogspot.com/201/4/rendering-text-in-opengl-on-android.html
package com.android.texample;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.opengles.GL10;
public class Vertices {
//--Constants--//
final static int POSITION_CNT_2D = 2; // Number of Components in Vertex Position for 2D
final static int POSITION_CNT_3D = 3; // Number of Components in Vertex Position for 3D
final static int COLOR_CNT = 4; // Number of Components in Vertex Color
final static int TEXCOORD_CNT = 2; // Number of Components in Vertex Texture Coords
final static int NORMAL_CNT = 3; // Number of Components in Vertex Normal
final static int INDEX_SIZE = Short.SIZE / 8; // Index Byte Size (Short.SIZE = bits)
//--Members--//
// NOTE: all members are constant, and initialized in constructor!
final GL10 gl; // GL Instance
final boolean hasColor; // Use Color in Vertices
final boolean hasTexCoords; // Use Texture Coords in Vertices
final boolean hasNormals; // Use Normals in Vertices
public final int positionCnt; // Number of Position Components (2=2D, 3=3D)
public final int vertexStride; // Vertex Stride (Element Size of a Single Vertex)
public final int vertexSize; // Bytesize of a Single Vertex
final IntBuffer vertices; // Vertex Buffer
final ShortBuffer indices; // Index Buffer
public int numVertices; // Number of Vertices in Buffer
public int numIndices; // Number of Indices in Buffer
final int[] tmpBuffer; // Temp Buffer for Vertex Conversion
//--Constructor--//
// D: create the vertices/indices as specified (for 2d/3d)
// A: gl - the gl instance to use
// maxVertices - maximum vertices allowed in buffer
// maxIndices - maximum indices allowed in buffer
// hasColor - use color values in vertices
// hasTexCoords - use texture coordinates in vertices
// hasNormals - use normals in vertices
// use3D - (false, default) use 2d positions (ie. x/y only)
// (true) use 3d positions (ie. x/y/z)
public Vertices(GL10 gl, int maxVertices, int maxIndices, boolean hasColor, boolean hasTexCoords, boolean hasNormals) {
this( gl, maxVertices, maxIndices, hasColor, hasTexCoords, hasNormals, false ); // Call Overloaded Constructor
}
public Vertices(GL10 gl, int maxVertices, int maxIndices, boolean hasColor, boolean hasTexCoords, boolean hasNormals, boolean use3D) {
this.gl = gl; // Save GL Instance
this.hasColor = hasColor; // Save Color Flag
this.hasTexCoords = hasTexCoords; // Save Texture Coords Flag
this.hasNormals = hasNormals; // Save Normals Flag
this.positionCnt = use3D ? POSITION_CNT_3D : POSITION_CNT_2D; // Set Position Component Count
this.vertexStride = this.positionCnt + ( hasColor ? COLOR_CNT : 0 ) + ( hasTexCoords ? TEXCOORD_CNT : 0 ) + ( hasNormals ? NORMAL_CNT : 0 ); // Calculate Vertex Stride
this.vertexSize = this.vertexStride * 4; // Calculate Vertex Byte Size
ByteBuffer buffer = ByteBuffer.allocateDirect( maxVertices * vertexSize ); // Allocate Buffer for Vertices (Max)
buffer.order( ByteOrder.nativeOrder() ); // Set Native Byte Order
this.vertices = buffer.asIntBuffer(); // Save Vertex Buffer
if ( maxIndices > 0 ) { // IF Indices Required
buffer = ByteBuffer.allocateDirect( maxIndices * INDEX_SIZE ); // Allocate Buffer for Indices (MAX)
buffer.order( ByteOrder.nativeOrder() ); // Set Native Byte Order
this.indices = buffer.asShortBuffer(); // Save Index Buffer
}
else // ELSE Indices Not Required
indices = null; // No Index Buffer
numVertices = 0; // Zero Vertices in Buffer
numIndices = 0; // Zero Indices in Buffer
this.tmpBuffer = new int[maxVertices * vertexSize / 4]; // Create Temp Buffer
}
//--Set Vertices--//
// D: set the specified vertices in the vertex buffer
// NOTE: optimized to use integer buffer!
// A: vertices - array of vertices (floats) to set
// offset - offset to first vertex in array
// length - number of floats in the vertex array (total)
// for easy setting use: vtx_cnt * (this.vertexSize / 4)
// R: [none]
public void setVertices(float[] vertices, int offset, int length) {
this.vertices.clear(); // Remove Existing Vertices
int last = offset + length; // Calculate Last Element
for ( int i = offset, j = 0; i < last; i++, j++ ) // FOR Each Specified Vertex
tmpBuffer[j] = Float.floatToRawIntBits( vertices[i] ); // Set Vertex as Raw Integer Bits in Buffer
this.vertices.put( tmpBuffer, 0, length ); // Set New Vertices
this.vertices.flip(); // Flip Vertex Buffer
this.numVertices = length / this.vertexStride; // Save Number of Vertices
//this.numVertices = length / ( this.vertexSize / 4 ); // Save Number of Vertices
}
//--Set Indices--//
// D: set the specified indices in the index buffer
// A: indices - array of indices (shorts) to set
// offset - offset to first index in array
// length - number of indices in array (from offset)
// R: [none]
public void setIndices(short[] indices, int offset, int length) {
this.indices.clear(); // Clear Existing Indices
this.indices.put( indices, offset, length ); // Set New Indices
this.indices.flip(); // Flip Index Buffer
this.numIndices = length; // Save Number of Indices
}
//--Bind--//
// D: perform all required binding/state changes before rendering batches.
// USAGE: call once before calling draw() multiple times for this buffer.
// A: [none]
// R: [none]
public void bind() {
gl.glEnableClientState( GL10.GL_VERTEX_ARRAY ); // Enable Position in Vertices
vertices.position( 0 ); // Set Vertex Buffer to Position
gl.glVertexPointer( positionCnt, GL10.GL_FLOAT, vertexSize, vertices ); // Set Vertex Pointer
if ( hasColor ) { // IF Vertices Have Color
gl.glEnableClientState( GL10.GL_COLOR_ARRAY ); // Enable Color in Vertices
vertices.position( positionCnt ); // Set Vertex Buffer to Color
gl.glColorPointer( COLOR_CNT, GL10.GL_FLOAT, vertexSize, vertices ); // Set Color Pointer
}
if ( hasTexCoords ) { // IF Vertices Have Texture Coords
gl.glEnableClientState( GL10.GL_TEXTURE_COORD_ARRAY ); // Enable Texture Coords in Vertices
vertices.position( positionCnt + ( hasColor ? COLOR_CNT : 0 ) ); // Set Vertex Buffer to Texture Coords (NOTE: position based on whether color is also specified)
gl.glTexCoordPointer( TEXCOORD_CNT, GL10.GL_FLOAT, vertexSize, vertices ); // Set Texture Coords Pointer
}
if ( hasNormals ) {
gl.glEnableClientState( GL10.GL_NORMAL_ARRAY ); // Enable Normals in Vertices
vertices.position( positionCnt + ( hasColor ? COLOR_CNT : 0 ) + ( hasTexCoords ? TEXCOORD_CNT : 0 ) ); // Set Vertex Buffer to Normals (NOTE: position based on whether color/texcoords is also specified)
gl.glNormalPointer( GL10.GL_FLOAT, vertexSize, vertices ); // Set Normals Pointer
}
}
//--Draw--//
// D: draw the currently bound vertices in the vertex/index buffers
// USAGE: can only be called after calling bind() for this buffer.
// A: primitiveType - the type of primitive to draw
// offset - the offset in the vertex/index buffer to start at
// numVertices - the number of vertices (indices) to draw
// R: [none]
public void draw(int primitiveType, int offset, int numVertices) {
if ( indices != null ) { // IF Indices Exist
indices.position( offset ); // Set Index Buffer to Specified Offset
gl.glDrawElements( primitiveType, numVertices, GL10.GL_UNSIGNED_SHORT, indices ); // Draw Indexed
}
else { // ELSE No Indices Exist
gl.glDrawArrays( primitiveType, offset, numVertices ); // Draw Direct (Array)
}
}
//--Unbind--//
// D: clear binding states when done rendering batches.
// USAGE: call once before calling draw() multiple times for this buffer.
// A: [none]
// R: [none]
public void unbind() {
gl.glDisableClientState( GL10.GL_VERTEX_ARRAY ); // Clear Vertex Array State
if ( hasColor ) // IF Vertices Have Color
gl.glDisableClientState( GL10.GL_COLOR_ARRAY ); // Clear Color State
if ( hasTexCoords ) // IF Vertices Have Texture Coords
gl.glDisableClientState( GL10.GL_TEXTURE_COORD_ARRAY ); // Clear Texture Coords State
if ( hasNormals ) // IF Vertices Have Normals
gl.glDisableClientState( GL10.GL_NORMAL_ARRAY ); // Clear Normals State
}
//--Draw Full--//
// D: draw the vertices in the vertex/index buffers
// NOTE: unoptimized version! use bind()/draw()/unbind() for batches
// A: primitiveType - the type of primitive to draw
// offset - the offset in the vertex/index buffer to start at
// numVertices - the number of vertices (indices) to draw
// R: [none]
public void drawFull(int primitiveType, int offset, int numVertices) {
gl.glEnableClientState( GL10.GL_VERTEX_ARRAY ); // Enable Position in Vertices
vertices.position( 0 ); // Set Vertex Buffer to Position
gl.glVertexPointer( positionCnt, GL10.GL_FLOAT, vertexSize, vertices ); // Set Vertex Pointer
if ( hasColor ) { // IF Vertices Have Color
gl.glEnableClientState( GL10.GL_COLOR_ARRAY ); // Enable Color in Vertices
vertices.position( positionCnt ); // Set Vertex Buffer to Color
gl.glColorPointer( COLOR_CNT, GL10.GL_FLOAT, vertexSize, vertices ); // Set Color Pointer
}
if ( hasTexCoords ) { // IF Vertices Have Texture Coords
gl.glEnableClientState( GL10.GL_TEXTURE_COORD_ARRAY ); // Enable Texture Coords in Vertices
vertices.position( positionCnt + ( hasColor ? COLOR_CNT : 0 ) ); // Set Vertex Buffer to Texture Coords (NOTE: position based on whether color is also specified)
gl.glTexCoordPointer( TEXCOORD_CNT, GL10.GL_FLOAT, vertexSize, vertices ); // Set Texture Coords Pointer
}
if ( indices != null ) { // IF Indices Exist
indices.position( offset ); // Set Index Buffer to Specified Offset
gl.glDrawElements( primitiveType, numVertices, GL10.GL_UNSIGNED_SHORT, indices ); // Draw Indexed
}
else { // ELSE No Indices Exist
gl.glDrawArrays( primitiveType, offset, numVertices ); // Draw Direct (Array)
}
if ( hasTexCoords ) // IF Vertices Have Texture Coords
gl.glDisableClientState( GL10.GL_TEXTURE_COORD_ARRAY ); // Clear Texture Coords State
if ( hasColor ) // IF Vertices Have Color
gl.glDisableClientState( GL10.GL_COLOR_ARRAY ); // Clear Color State
gl.glDisableClientState( GL10.GL_VERTEX_ARRAY ); // Clear Vertex Array State
}
//--Set Vertex Elements--//
// D: use these methods to alter the values (position, color, textcoords, normals) for vertices
// WARNING: these do NOT validate any values, ensure that the index AND specified
// elements EXIST before using!!
// A: x, y, z - the x,y,z position to set in buffer
// r, g, b, a - the r,g,b,a color to set in buffer
// u, v - the u,v texture coords to set in buffer
// nx, ny, nz - the x,y,z normal to set in buffer
// R: [none]
void setVtxPosition(int vtxIdx, float x, float y) {
int index = vtxIdx * vertexStride; // Calculate Actual Index
vertices.put( index + 0, Float.floatToRawIntBits( x ) ); // Set X
vertices.put( index + 1, Float.floatToRawIntBits( y ) ); // Set Y
}
void setVtxPosition(int vtxIdx, float x, float y, float z) {
int index = vtxIdx * vertexStride; // Calculate Actual Index
vertices.put( index + 0, Float.floatToRawIntBits( x ) ); // Set X
vertices.put( index + 1, Float.floatToRawIntBits( y ) ); // Set Y
vertices.put( index + 2, Float.floatToRawIntBits( z ) ); // Set Z
}
void setVtxColor(int vtxIdx, float r, float g, float b, float a) {
int index = ( vtxIdx * vertexStride ) + positionCnt; // Calculate Actual Index
vertices.put( index + 0, Float.floatToRawIntBits( r ) ); // Set Red
vertices.put( index + 1, Float.floatToRawIntBits( g ) ); // Set Green
vertices.put( index + 2, Float.floatToRawIntBits( b ) ); // Set Blue
vertices.put( index + 3, Float.floatToRawIntBits( a ) ); // Set Alpha
}
void setVtxColor(int vtxIdx, float r, float g, float b) {
int index = ( vtxIdx * vertexStride ) + positionCnt; // Calculate Actual Index
vertices.put( index + 0, Float.floatToRawIntBits( r ) ); // Set Red
vertices.put( index + 1, Float.floatToRawIntBits( g ) ); // Set Green
vertices.put( index + 2, Float.floatToRawIntBits( b ) ); // Set Blue
}
void setVtxColor(int vtxIdx, float a) {
int index = ( vtxIdx * vertexStride ) + positionCnt; // Calculate Actual Index
vertices.put( index + 3, Float.floatToRawIntBits( a ) ); // Set Alpha
}
void setVtxTexCoords(int vtxIdx, float u, float v) {
int index = ( vtxIdx * vertexStride ) + positionCnt + ( hasColor ? COLOR_CNT : 0 ); // Calculate Actual Index
vertices.put( index + 0, Float.floatToRawIntBits( u ) ); // Set U
vertices.put( index + 1, Float.floatToRawIntBits( v ) ); // Set V
}
void setVtxNormal(int vtxIdx, float x, float y, float z) {
int index = ( vtxIdx * vertexStride ) + positionCnt + ( hasColor ? COLOR_CNT : 0 ) + ( hasTexCoords ? TEXCOORD_CNT : 0 ); // Calculate Actual Index
vertices.put( index + 0, Float.floatToRawIntBits( x ) ); // Set X
vertices.put( index + 1, Float.floatToRawIntBits( y ) ); // Set Y
vertices.put( index + 2, Float.floatToRawIntBits( z ) ); // Set Z
}
}

View File

@@ -0,0 +1,59 @@
package com.roguetemple.hyperroid;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
public class ForegroundService extends Service {
public static String MAIN_ACTION = "com.roguetemple.hyperroid.action.main";
public static String STARTFOREGROUND_ACTION = "com.roguetemple.hyperroid.action.startforeground";
public static String STOPFOREGROUND_ACTION = "com.roguetemple.hyperroid.action.stopforeground";
public static int FOREGROUND_SERVICE = 101;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(STARTFOREGROUND_ACTION)) {
Intent notificationIntent = new Intent(this, HyperRogue.class);
notificationIntent.setAction(MAIN_ACTION);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("HyperRogue")
.setContentText("Game in progress.")
.setTicker("Game in progress. Game in progress. Game in progress.")
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.icon)
.setOngoing(true)
.build();
startForeground(FOREGROUND_SERVICE, notification);
}
else if (intent.getAction().equals(STOPFOREGROUND_ACTION)) {
stopForeground(true);
stopSelf();
}
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// Used only in case of bound services.
return null;
}
}

View File

@@ -0,0 +1,69 @@
package com.roguetemple.hyperroid;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
public class HyperProvider extends ContentProvider {
public static final Uri CONTENT_URI=Uri.parse("content://com.roguetemple.hyperroid/");
@Override
public boolean onCreate() {
File f=new File(getContext().getCacheDir(), "cache.jpg");
return f.exists();
}
@Override
public String getType(Uri uri) {
return "image/jpeg";
}
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
File f=new File(getContext().getCacheDir(), "cache.jpg");
return ParcelFileDescriptor.open(f,
ParcelFileDescriptor.MODE_READ_ONLY);
}
@Override
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sort) {
throw new RuntimeException("Operation not supported");
}
@Override
public Uri insert(Uri uri, ContentValues initialValues) {
throw new RuntimeException("Operation not supported");
}
@Override
public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
throw new RuntimeException("Operation not supported");
}
@Override
public int delete(Uri uri, String where, String[] whereArgs) {
throw new RuntimeException("Operation not supported");
}
static public void copy(InputStream in, File dst) throws IOException {
FileOutputStream out=new FileOutputStream(dst);
byte[] buf=new byte[1024];
int len;
while((len=in.read(buf))>0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
}

View File

@@ -0,0 +1,120 @@
package com.roguetemple.hyperroid;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
// import android.graphics.Paint;
// import android.graphics.Path;
import android.graphics.Typeface;
import android.opengl.GLSurfaceView;
// bimport android.widget.Toast;
import com.android.texample.GLText;
public class HyperRenderer implements GLSurfaceView.Renderer {
int width, height;
HyperRogue game;
private GLText glText; // A GLText Instance
int [] graphdata;
int gdpos;
int gdpop() { return graphdata[gdpos++]; }
public void onDrawFrame(GL10 gl) {
if(game.forceCanvas) return;
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
synchronized(game) {
game.hv.updateGame();
game.draw();
graphdata = game.loadMap();
}
if(graphdata == null) return;
// Set to ModelView mode
gl.glMatrixMode( GL10.GL_MODELVIEW ); // Activate Model View Matrix
gl.glLoadIdentity(); // Load Identity Matrix
// enable texture + alpha blending
// NOTE: this is required for text rendering! we could incorporate it into
// the GLText class, but then it would be called multiple times (which impacts performance).
gl.glEnable( GL10.GL_TEXTURE_2D ); // Enable Texture Mapping
gl.glEnable( GL10.GL_BLEND ); // Enable Alpha Blend
gl.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA ); // Set Alpha Blend Function
gl.glMatrixMode( GL10.GL_PROJECTION ); // Activate Projection Matrix
gl.glLoadIdentity(); // Load Identity Matrix
gl.glOrthof( // Set Ortho Projection (Left,Right,Bottom,Top,Front,Back)
0, width,
0, height,
1.0f, -1.0f
);
gdpos = 0;
while(gdpos < graphdata.length) {
switch(gdpop()) {
case 2: {
int x = gdpop();
int y = gdpop();
int al = gdpop();
int col = gdpop() + 0xFF000000;
int size = gdpop();
int b = gdpop();
int n = gdpop();
StringBuffer ss = new StringBuffer();
for(int i=0; i<n; i++) {
char c = (char) gdpop();
ss.append(c);
}
String s = ss.toString();
y = height - y;
glText.setScale(size / 48.0f);
if(b > 0) {
glText.begin(0f, 0f, 0f, 1f);
glText.drawAlign(s, (float)(x-1), (float)y, al);
glText.drawAlign(s, (float)(x+1), (float)y, al);
glText.drawAlign(s, (float)x, (float)(y-1), al);
glText.drawAlign(s, (float)x, (float)(y+1), al);
glText.end();
}
glText.begin(
(col & 0xFF0000) / (float)0xFF0000,
(col & 0xFF00) / (float)0xFF00,
(col & 0xFF) / (float)0xFF,
1.0f );
glText.drawAlign(s, (float) x, (float) y, al);
glText.end();
}
break;
}}
// disable texture + alpha
gl.glDisable( GL10.GL_BLEND ); // Disable Alpha Blend
gl.glDisable( GL10.GL_TEXTURE_2D ); // Disable Texture Mapping
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
// Save width and height
this.width = width; // Save Current Width
this.height = height; // Save Current Height
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
glText = new GLText( gl );
glText.load(Typeface.DEFAULT_BOLD, 48, 2, 2 ); // Create Font (Height: 48 Pixels / X+Y Padding 2 Pixels)
}
}

View File

@@ -0,0 +1,649 @@
package com.roguetemple.hyperroid;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Locale;
import java.util.StringTokenizer;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.AssetFileDescriptor;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.media.MediaPlayer;
import android.net.Uri;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.EGLConfigChooser;
import android.os.Bundle;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.text.ClipboardManager;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
import android.widget.Toast;
import android.util.Log;
public class HyperRogue extends Activity {
private static final int RESULT_SETTINGS = 1;
private static final boolean isGold = false;
final int SAVESIZE = 261;
private static final int YENDOR_SIZE = 30;
static final int NUMLEADER = 57;
int yendor[];
int scoretable[];
int savedgame[];
HyperView hv;
GLSurfaceView glview;
FrameLayout fl;
public void showHelp(String s) {
final HyperRogue game = this;
final String helptext = s;
if(Looper.myLooper() != Looper.getMainLooper()) {
runOnUiThread(new Runnable() { public void run() { game.showHelp(helptext); }});
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog ad = builder.create();
ad.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
/* builder.setNeutralButton("Share", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// (HyperRogue)(getApplicationContext())
game.shareScore(helptext);
dialog.dismiss();
}
}); */
ad.setMessage(s);
ad.setOwnerActivity(this);
ad.show();
// help = s;
// showDialog(1);
}
String sharescore;
public void shareScore(String s) {
final HyperRogue game = this;
sharescore = s;
String[] items = {
getResources().getString(R.string.sharesam),
getResources().getString(R.string.sharemsg),
getResources().getString(R.string.copymsg)
};
if(Looper.myLooper() != Looper.getMainLooper()) {
runOnUiThread(
new Runnable() {
public void run() {
game.shareScore(sharescore);
}
}
);
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getResources().getText(R.string.sharehow));
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
if(item == 2) {
ClipboardManager man = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
if(man != null) man.setText(sharescore);
Toast.makeText(getApplicationContext(), getResources().getText(R.string.copied), Toast.LENGTH_SHORT).show();
}
else {
Intent intent=new Intent(android.content.Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, "HyperRogue");
intent.putExtra(Intent.EXTRA_TEXT, sharescore);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
if(item == 0) {
try {
String path = getCacheDir().toString() + "/cache.jpg";
FileOutputStream fout = new FileOutputStream(path);
Bitmap bitmap = hv.screenshot();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
fout.flush();
fout.close();
intent.setType("image/jpeg");
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse(HyperProvider.CONTENT_URI + "hyperrogue.jpg"));
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "Error with the image file", Toast.LENGTH_SHORT).show();
}
}
startActivity(Intent.createChooser(intent, getResources().getText(R.string.sharevia)));
}
}
});
AlertDialog ad = builder.create();
ad.setOwnerActivity(this);
ad.show();
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
File f = getFilesDir();
setFilesDir(f.getAbsolutePath());
initGame();
immersive = getImmersive();
if(immersive) requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
forceCanvas = false;
hv = (HyperView) findViewById(R.id.ascv);
hv.game = this;
hv.invalidate();
fl = (FrameLayout) findViewById(R.id.framelayout);
applyUserSettings();
UiChangeListener();
}
public native int initGame();
public native int getland();
public native void update(int xres, int yres, int ticks, int mousex, int mousey, boolean clicked);
public native void draw();
public native void drawScreenshot();
public native int[] loadMap();
public native boolean captureBack();
public native boolean keepinmemory();
public native boolean getImmersive();
public native boolean getGL();
public native int getMusicVolume();
public native int getEffVolume();
public native int getLanguage();
public native void syncScore(int id, int val);
public native void setFilesDir(String s);
public native boolean getGoogleConnection();
public native void setGoogleSignin(boolean issigned, boolean isconnecting);
public native void handleKey(int keyCode);
static {
System.loadLibrary("hyper");
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
synchronized(this) { if(captureBack()) return true; }
}
int unicode = 0;
if(keyCode == KeyEvent.KEYCODE_F1) unicode = (123001);
else if(keyCode == KeyEvent.KEYCODE_F2) unicode = (123002);
else if(keyCode == KeyEvent.KEYCODE_F3) unicode = (123003);
else if(keyCode == KeyEvent.KEYCODE_F4) unicode = (123004);
else if(keyCode == KeyEvent.KEYCODE_F5) unicode = (123005);
else if(keyCode == KeyEvent.KEYCODE_F6) unicode = (123006);
else if(keyCode == KeyEvent.KEYCODE_F7) unicode = (123007);
else if(keyCode == KeyEvent.KEYCODE_F10) unicode = (123010);
else if(keyCode == KeyEvent.KEYCODE_ESCAPE) unicode = (123099);
else if(keyCode == KeyEvent.KEYCODE_F12) unicode = (123012);
else if(keyCode == KeyEvent.KEYCODE_HOME) unicode = (123013);
else if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT) unicode = (123014);
else if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) unicode = (123015);
else if(keyCode == KeyEvent.KEYCODE_DPAD_UP) unicode = (123021);
else if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN) unicode = (123022);
else if(keyCode == KeyEvent.KEYCODE_PAGE_UP) unicode = (123023);
else if(keyCode == KeyEvent.KEYCODE_PAGE_DOWN) unicode = (123024);
else if(keyCode == KeyEvent.KEYCODE_ENTER) unicode = (123025);
else if(keyCode == KeyEvent.KEYCODE_NUMPAD_1) unicode = (123031);
else if(keyCode == KeyEvent.KEYCODE_NUMPAD_2) unicode = (123032);
else if(keyCode == KeyEvent.KEYCODE_NUMPAD_3) unicode = (123033);
else if(keyCode == KeyEvent.KEYCODE_NUMPAD_4) unicode = (123034);
else if(keyCode == KeyEvent.KEYCODE_NUMPAD_5) unicode = (123035);
else if(keyCode == KeyEvent.KEYCODE_NUMPAD_6) unicode = (123036);
else if(keyCode == KeyEvent.KEYCODE_NUMPAD_7) unicode = (123037);
else if(keyCode == KeyEvent.KEYCODE_NUMPAD_8) unicode = (123038);
else if(keyCode == KeyEvent.KEYCODE_NUMPAD_9) unicode = (123039);
else if(keyCode == KeyEvent.KEYCODE_NUMPAD_DOT) unicode = (123051);
else if(keyCode == KeyEvent.KEYCODE_DEL) unicode = (123052);
else unicode = event.getUnicodeChar();
if(unicode != 0) synchronized(this) { handleKey(unicode); }
return super.onKeyDown(keyCode, event);
}
void openWebsite() {
Runnable r = new Runnable() {
public void run() {
String url = "http://roguetemple.com/z/hyper.php";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
};
runOnUiThread(r);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == RESULT_SETTINGS)
applyUserSettings();
}
public boolean forceCanvas;
int musicvolume, effvolume;
// returns 'true' iff the activity is refreshed
public boolean setLocale(String lang) {
Locale myLocale = new Locale(lang);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
String oldlang = conf.locale.getLanguage();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
if(lang != oldlang) {
// Intent refresh = new Intent(this, HyperRogue.class);
// startActivity(refresh);
// return true;
return false;
}
return false;
}
boolean immersive;
void applyUserSettings() {
if (Looper.myLooper() != Looper.getMainLooper()) {
runOnUiThread(new Runnable() {
public void run() {
applyUserSettings();
}
});
return;
}
int lang = getLanguage();
boolean usegl = getGL();
musicvolume = getMusicVolume();
changevol = true;
effvolume = getEffVolume();
immersive = getImmersive();
boolean reset = false;
if(lang == 0) reset = setLocale("en");
if(lang == 1) reset = setLocale("pl");
if(lang == 2) reset = setLocale("tr");
if(lang == 3) reset = setLocale("cz");
if(lang == 4) reset = setLocale("ru");
if(reset) return; // no point in doing the following twice
if(glview != null && !usegl) {
fl.removeView(glview);
glview = null;
hv.invalidate();
}
if(usegl && glview == null) {
glview = new GLSurfaceView(this);
HyperRenderer hr =new HyperRenderer();
hr.game = this;
glview.setEGLConfigChooser(new HRConfigChooser());
glview.setRenderer(hr);
glview.setZOrderMediaOverlay(true);
LayoutParams lp =new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
fl.addView(glview, lp);
}
}
MediaPlayer backgroundmusic;
boolean changevol = false;
int lastland;
int curpos[];
float curvol;
@Override
protected void onPause() {
super.onPause();
boolean keep;
synchronized (this) {
// recordscore();
keep = keepinmemory();
}
if (keep) {
Intent startIntent = new Intent(HyperRogue.this, ForegroundService.class);
startIntent.setAction(ForegroundService.STARTFOREGROUND_ACTION);
startService(startIntent);
} else {
Intent stopIntent = new Intent(HyperRogue.this, ForegroundService.class);
stopIntent.setAction(ForegroundService.STOPFOREGROUND_ACTION);
startService(stopIntent);
}
if (backgroundmusic != null) backgroundmusic.stop();
}
// remove for the lite version START
public void UiChangeListener()
{
int currentApiVersion = android.os.Build.VERSION.SDK_INT;
if(currentApiVersion >= 19) {
final View decorView = getWindow().getDecorView();
final int flags =
immersive ?
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION :
0;
decorView.setSystemUiVisibility(flags);
decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
decorView.setSystemUiVisibility(flags);
}
}
});
}
}
protected void onResume() {
super.onResume();
if(backgroundmusic != null) {
try {backgroundmusic.prepare(); } catch(Exception e) {}
backgroundmusic.start();
}
UiChangeListener();
}
long lastclock;
MediaPlayer sounds[];
private static final int CHANNELS = 4;
protected void playSound(String s, int vol) {
if(effvolume == 0) return;
if (Looper.myLooper() != Looper.getMainLooper()) {
final String final_s = s;
final int final_vol = vol;
runOnUiThread(new Runnable() {
public void run() {
playSound(final_s, final_vol);
}
});
return;
}
try {
if(sounds == null) sounds = new MediaPlayer[CHANNELS];
AssetFileDescriptor afd = getAssets().openFd("sounds/" + s + ".ogg");
int i;
for(i=0; i<CHANNELS; i++)
if(sounds[i] == null || !sounds[i].isPlaying())
break;
if(i == CHANNELS) return;
if(sounds[i] == null) {
sounds[i] = new MediaPlayer();
sounds[i].setOnErrorListener(new MediaPlayer.OnErrorListener()
{
@Override
public boolean onError(MediaPlayer mp, int what, int extra)
{
/* Toast.makeText(getApplicationContext(), String.format("Error(%s%s)", what, extra),
Toast.LENGTH_SHORT).show(); */
return true;
}
});
/* sounds[i].setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
};
}); */
} else sounds[i].reset();
sounds[i].setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
sounds[i].prepare();
sounds[i].setVolume((float)(vol * effvolume / 12800.), (float)(vol * effvolume / 12800.));
sounds[i].start();
/* Toast.makeText(getApplicationContext(), "playing " + s
+ " on "+Integer.toString(i)+ " vol "+Integer.toString(vol), Toast.LENGTH_SHORT).show(); */
}
catch(IOException ex) {
}
}
protected void checkMusic() {
if(musicvolume == 0) {
if(backgroundmusic != null) {
backgroundmusic.stop();
backgroundmusic.release();
backgroundmusic = null;
curvol = 0; changevol = true;
lastland = -1;
}
return;
}
int curland = getland();
long curclock = System.currentTimeMillis();
float delta = (curclock - lastclock) / 1000.0f;
lastclock = curclock;
if(lastland == curland) {
if(curvol < 1 || changevol) {
curvol += delta;
if(curvol > 1) curvol = 1;
if(backgroundmusic != null)
backgroundmusic.setVolume(curvol * musicvolume / 128, curvol * musicvolume / 128);
}
}
else if(backgroundmusic == null) {
int id = R.raw.crossroads;
if(curland == 2) id = R.raw.crossroads; // Crossroads
if(curland == 3) id = R.raw.desert; // Desert
if(curland == 4) id = R.raw.icyland; // Icy Land
if(curland == 5) id = R.raw.caves; // Living Cave
if(curland == 6) id = R.raw.jungle; // Jungle
if(curland == 7) id = R.raw.laboratory; // Alchemist Lab
if(curland == 8) id = R.raw.mirror; // Mirror Land
if(curland == 9) id = R.raw.graveyard; // Graveyard
if(curland == 10) id = R.raw.rlyeh; // R'Lyeh
if(curland == 11) id = R.raw.hell; // Hell
if(curland == 12) id = R.raw.icyland; // Cocytus
if(curland == 13) id = R.raw.motion; // Land of Eternal Motion
if(curland == 14) id = R.raw.jungle; // Dry Forest
if(curland == 15) id = R.raw.caves; // Emerald Mine
if(curland == 16) id = R.raw.laboratory; // Vineyard
if(curland == 17) id = R.raw.graveyard; // Dead Cave
if(curland == 18) id = R.raw.motion; // Hive
if(curland == 19) id = R.raw.mirror; // Land of Power
if(curland == 20) id = R.raw.hell; // Camelot
if(curland == 21) id = R.raw.rlyeh; // Temple of Cthulhu
if(curland == 22) id = R.raw.crossroads; // Crossroads II
if(curland == 23) id = R.raw.crossroads; // Caribbean
if(curland == 24) id = R.raw.desert; // Red Rock Valley
if(curland == 25) id = R.raw.hell; // Minefield
if(curland == 26) id = R.raw.caves; // Ocean
if(curland == 27) id = R.raw.rlyeh; // Whirlpool
if(curland == 28) id = R.raw.crossroads; // Palace
if(curland == 29) id = R.raw.caves; // Living Fjord
if(curland == 30) id = R.raw.hell; // Ivory Tower
if(curland == 31) id = R.raw.motion; // Zebra
if(curland == 32) id = R.raw.hell; // Plane of Fire
if(curland == 33) id = R.raw.motion; // Plane of Air
if(curland == 34) id = R.raw.caves; // Plane of Earth
if(curland == 35) id = R.raw.crossroads; // Plane of Water
if(curland == 36) id = R.raw.crossroads; // Crossroads III
if(curland == 39) id = R.raw.laboratory; // Canvas
if(curland == 41) id = R.raw.caves; // Wild West
if(curland == 42) id = R.raw.laboratory; // Land of Storms
if(curland == 43) id = R.raw.jungle; // Overgrown Woods
if(curland == 44) id = R.raw.jungle; // Clearing
if(curland == 45) id = R.raw.graveyard; // Haunted Woods
if(curland == 48) id = R.raw.laboratory; // Windy Plains
if(curland == 49) id = R.raw.hell; // Rose Garden
if(curland == 50) id = R.raw.caves; // Warped Coast
if(curland == 52) id = R.raw.crossroads; // Crossroads IV
if(curland == 53) id = R.raw.laboratory; // Yendorian Forest
if(curland == 54) id = R.raw.crossroads; // Gal<61>pagos
if(curland == 55) id = R.raw.caves; // Dragon Chasms
if(curland == 56) id = R.raw.rlyeh; // Kraken Depths
if(curland == 57) id = R.raw.graveyard; // Burial Grounds
if(curland == 58) id = R.raw.desert; // Trollheim
if(curland == 56) id = R.raw.rlyeh; // Kraken Depths
if(curland == 57) id = R.raw.graveyard; // Burial Grounds
if(curland == 58) id = R.raw.desert; // Trollheim
if(curland == 59) id = R.raw.graveyard; // Halloween
if(curland == 60) id = R.raw.desert; // Dungeon
if(curland == 61) id = R.raw.rlyeh; // Lost Mountain
if(curland == 62) id = R.raw.mirror; // Reptiles
if(curland == 63) id = R.raw.rlyeh; // Prairie
if(curland == 64) id = R.raw.mirror; // Bull Dash
if(curland == 65) id = R.raw.mirror; // Crossroads V
if(curland == 66) id = R.raw.laboratory; // CA land
if(id > 0) backgroundmusic = MediaPlayer.create(this, id);
if(backgroundmusic != null) {
backgroundmusic.setLooping(true);
curvol = 0;
backgroundmusic.setVolume(curvol, curvol);
if(curpos != null)
backgroundmusic.seekTo(curpos[curland]);
backgroundmusic.start();
lastland = curland;
}
else curland = 0;
}
else if(curvol <= delta) {
if(curpos == null) curpos = new int[128];
curpos[lastland] = backgroundmusic.getCurrentPosition();
if(backgroundmusic != null) backgroundmusic.stop();
backgroundmusic = null;
}
else {
curvol -= delta;
backgroundmusic.setVolume(curvol * musicvolume / 128, curvol * musicvolume / 128);
}
}
public int getTextWidth(String s, int size) {
Rect bounds = new Rect();
Paint pon = new Paint();
pon.setAntiAlias(true);
pon.setTextSize(size);
pon.setTextAlign(Paint.Align.LEFT);
pon.setTypeface(Typeface.DEFAULT_BOLD);
pon.getTextBounds(s,0,s.length(),bounds);
return bounds.width();
}
}
class HRConfigChooser implements EGLConfigChooser {
private int getValue(EGL10 egl, EGLDisplay display, EGLConfig config, int attr) {
int[] mValue = new int[1];
if (egl.eglGetConfigAttrib(display, config, attr, mValue))
return mValue[0];
return 0;
}
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
int[] num_config = new int[1];
int[] basic = new int[]{
EGL10.EGL_RED_SIZE, 5,
EGL10.EGL_GREEN_SIZE, 6,
EGL10.EGL_BLUE_SIZE, 5,
EGL10.EGL_STENCIL_SIZE, 1,
EGL10.EGL_NONE
};
egl.eglChooseConfig(display, basic, null, 0, num_config);
if (num_config[0] <= 0) {
basic = new int[]{EGL10.EGL_NONE};
egl.eglChooseConfig(display, basic, null, 0, num_config);
}
if (num_config[0] <= 0) throw new IllegalArgumentException("no config available");
EGLConfig[] configs = new EGLConfig[num_config[0]];
egl.eglChooseConfig(display, basic, configs, num_config[0], num_config);
EGLConfig best = null;
int bestscore = 0;
for (EGLConfig config : configs) {
int d = getValue(egl, display, config, EGL10.EGL_DEPTH_SIZE);
int s = getValue(egl, display, config, EGL10.EGL_STENCIL_SIZE);
int r = getValue(egl, display, config, EGL10.EGL_RED_SIZE);
int g = getValue(egl, display, config, EGL10.EGL_GREEN_SIZE);
int b = getValue(egl, display, config, EGL10.EGL_BLUE_SIZE);
int a = getValue(egl, display, config, EGL10.EGL_ALPHA_SIZE);
int score = 10000;
if (s == 0) score -= 1000;
score -= s;
score -= d;
score -= a;
int all = r + g + b;
if (all < 24) score -= 10 * (24 - all);
score -= 10 * (all - 24);
if (score > bestscore) {
bestscore = score;
best = config;
}
}
return best;
}
}

View File

@@ -0,0 +1,12 @@
package com.roguetemple.hyperroid;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class HyperSettings extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}

View File

@@ -0,0 +1,247 @@
package com.roguetemple.hyperroid;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Typeface;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class HyperView extends View {
HyperRogue game;
public HyperView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
public HyperView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
int width, height, mousex, mousey;
boolean clicked;
int clickcnt = 0;
Canvas dc;
int[] graphdata;
int gdpos;
int gdpop() { return graphdata[gdpos++]; }
int lasttick, curtick;
int realpha(int col) {
return ((col >> 8) & 0xFFFFFF) + ((col & 0xFF) << 24);
}
public void drawScreen(PorterDuff.Mode mode) {
Paint pon = new Paint();
pon.setXfermode(new PorterDuffXfermode(mode));
pon.setColor(0xC0C0C0C0);
pon.setAntiAlias(true);
pon.setTextSize(8);
pon.setTextAlign(Paint.Align.RIGHT);
pon.setTypeface(Typeface.DEFAULT_BOLD);
// String s = "D " + Integer.toString(graphdata.length) + " T " + Integer.toString(curtick-lasttick);
// dc.drawText(s, width*11/12, height*1/12, pon);
gdpos = 0;
while(gdpos < graphdata.length) {
switch(gdpop()) {
case 2: {
int x = gdpop();
int y = gdpop();
int al = gdpop();
int col = gdpop() + 0xFF000000;
int size = gdpop();
y = y + size/2;
int b = gdpop();
int n = gdpop();
StringBuffer ss = new StringBuffer();
for(int i=0; i<n; i++) {
char c = (char)gdpop();
ss.append(c);
}
pon.setStyle(Paint.Style.FILL);
pon.setColor(col);
pon.setTextSize(size);
pon.setTextAlign(
al == 0 ? Paint.Align.LEFT :
al == 8 ? Paint.Align.CENTER :
Paint.Align.RIGHT);
if(b>0) {
pon.setColor(0xFF000000);
dc.drawText(ss.toString(), x-b, y, pon);
dc.drawText(ss.toString(), x+b, y, pon);
dc.drawText(ss.toString(), x, y-b, pon);
dc.drawText(ss.toString(), x, y+b, pon);
}
pon.setColor(col);
dc.drawText(ss.toString(), x, y, pon);
}
break;
case 1: {
int col = gdpop();
int otl = gdpop();
int num = gdpop();
pon.setColor(realpha(col));
/* for(int i=0; i<num; i++) {
int x2 = gdpop();
int y2 = gdpop();
dc.drawText("x", x2, y2, pon);
} */
Path p = new Path();
int x = gdpop();
int y = gdpop();
p.moveTo(x, y);
for(int i=1; i<num; i++) {
int x2 = gdpop();
int y2 = gdpop();
p.lineTo(x2, y2);
}
p.lineTo(x, y);
pon.setStyle(Paint.Style.FILL);
dc.drawPath(p, pon);
pon.setStyle(Paint.Style.STROKE);
pon.setColor(realpha(otl));
dc.drawPath(p, pon);
break;
}
case 3: {
int col = gdpop();
int num = gdpop();
pon.setColor(realpha(col));
int x = gdpop();
int y = gdpop();
for(int i=1; i<num; i++) {
int x2 = gdpop();
int y2 = gdpop();
dc.drawLine(x, y, x2, y2, pon);
x = x2; y = y2;
}
break;
}
case 4: {
int col = gdpop();
int x = gdpop();
int y = gdpop();
int rad = gdpop();
col += 0xFF000000;
pon.setColor(col);
pon.setStyle(Paint.Style.STROKE);
dc.drawCircle(x, y, rad, pon);
break;
}
}}
}
public void updateGame() {
lasttick = curtick;
curtick = (int)SystemClock.elapsedRealtime();
if(clickcnt > 0) clickcnt--;
game.update(width, height, curtick, mousex, mousey, clicked | ((clickcnt & 1) > 0));
final HyperRogue fgame = game;
game.runOnUiThread(new Runnable() { public void run() { fgame.checkMusic(); }});
}
@Override
public void onDraw(final Canvas canvas) {
super.onDraw(canvas);
PowerManager pm = (PowerManager) game.getSystemService(Context.POWER_SERVICE);
boolean isScreenOn = pm.isScreenOn();
if(!isScreenOn) return;
dc = canvas;
width = getWidth();
height = getHeight();
if(game != null && game.glview == null) {
updateGame();
game.draw();
graphdata = game.loadMap();
drawScreen(PorterDuff.Mode.SRC_ATOP);
invalidate();
}
}
public Bitmap screenshot() {
Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas old = dc;
dc = new Canvas(b);
synchronized(game) {
game.forceCanvas = true;
game.drawScreenshot();
graphdata = game.loadMap();
game.forceCanvas = false;
}
dc.setDensity(old.getDensity());
drawScreen(PorterDuff.Mode.SRC_OVER);
return b;
}
@Override
public boolean onTouchEvent (MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
mousex = (int) event.getX();
mousey = (int) event.getY();
clickcnt += 2;
clicked = true;
}
if(event.getAction() == MotionEvent.ACTION_UP) {
clicked = false;
}
if(event.getAction() == MotionEvent.ACTION_MOVE) {
mousex = (int) event.getX();
mousey = (int) event.getY();
}
return true;
}
public void initView() {
setFocusable(true);
setFocusableInTouchMode(true);
mousex = 0; mousey = 0; clicked = false;
}
}