Converted ShatteredPD to Build from Gradle
Major Changes: - Shattered now builds effortlessly either from gradle CLI or android studio - Much better dependency management through gradle (although it's not really used atm) - Separate PD-classes repo is now SPD-classes module within main repo
15
.gitignore
vendored
|
@ -1,11 +1,5 @@
|
|||
.classpath
|
||||
.project
|
||||
project.properties
|
||||
proguard.cfg
|
||||
|
||||
# Built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
|
||||
# Files for the Dalvik VM
|
||||
*.dex
|
||||
|
@ -13,10 +7,6 @@ proguard.cfg
|
|||
# Java class files
|
||||
*.class
|
||||
|
||||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
|
||||
# Gradle files
|
||||
.gradle/
|
||||
build/
|
||||
|
@ -24,9 +14,6 @@ build/
|
|||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
proguard/
|
||||
|
||||
#intellij project files
|
||||
*.iml
|
||||
*.idea
|
||||
*.idea
|
||||
|
|
6
SPD-classes/build.gradle
Normal file
|
@ -0,0 +1,6 @@
|
|||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "24.0.0"
|
||||
}
|
9
SPD-classes/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.watabou">
|
||||
|
||||
<application
|
||||
android:label="@string/app_name"
|
||||
>
|
||||
</application>
|
||||
|
||||
</manifest>
|
86
SPD-classes/src/main/java/com/watabou/glscripts/Script.java
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.glscripts;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.watabou.glwrap.Program;
|
||||
import com.watabou.glwrap.Shader;
|
||||
|
||||
public class Script extends Program {
|
||||
|
||||
private static final HashMap<Class<? extends Script>,Script> all =
|
||||
new HashMap<Class<? extends Script>, Script>();
|
||||
|
||||
private static Script curScript = null;
|
||||
private static Class<? extends Script> curScriptClass = null;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static<T extends Script> T use( Class<T> c ) {
|
||||
|
||||
if (c != curScriptClass) {
|
||||
|
||||
Script script = all.get( c );
|
||||
if (script == null) {
|
||||
try {
|
||||
script = c.newInstance();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
all.put( c, script );
|
||||
}
|
||||
|
||||
if (curScript != null) {
|
||||
curScript.unuse();
|
||||
}
|
||||
|
||||
curScript = script;
|
||||
curScriptClass = c;
|
||||
curScript.use();
|
||||
|
||||
}
|
||||
|
||||
return (T)curScript;
|
||||
}
|
||||
|
||||
public static void reset() {
|
||||
for (Script script:all.values()) {
|
||||
script.delete();
|
||||
}
|
||||
all.clear();
|
||||
|
||||
curScript = null;
|
||||
curScriptClass = null;
|
||||
}
|
||||
|
||||
public void compile( String src ) {
|
||||
|
||||
String[] srcShaders = src.split( "//\n" );
|
||||
attach( Shader.createCompiled( Shader.VERTEX, srcShaders[0] ) );
|
||||
attach( Shader.createCompiled( Shader.FRAGMENT, srcShaders[1] ) );
|
||||
link();
|
||||
|
||||
}
|
||||
|
||||
public void unuse() {
|
||||
}
|
||||
}
|
99
SPD-classes/src/main/java/com/watabou/gltextures/Atlas.java
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.gltextures;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.graphics.RectF;
|
||||
|
||||
public class Atlas {
|
||||
|
||||
public SmartTexture tx;
|
||||
|
||||
protected HashMap<Object,RectF> namedFrames;
|
||||
|
||||
protected float uvLeft;
|
||||
protected float uvTop;
|
||||
protected float uvWidth;
|
||||
protected float uvHeight;
|
||||
protected int cols;
|
||||
|
||||
public Atlas( SmartTexture tx ) {
|
||||
|
||||
this.tx = tx;
|
||||
tx.atlas = this;
|
||||
|
||||
namedFrames = new HashMap<Object, RectF>();
|
||||
}
|
||||
|
||||
public void add( Object key, int left, int top, int right, int bottom ) {
|
||||
add( key, uvRect( tx, left, top, right, bottom ) );
|
||||
}
|
||||
|
||||
public void add( Object key, RectF rect ) {
|
||||
namedFrames.put( key, rect );
|
||||
}
|
||||
|
||||
public void grid( int width ) {
|
||||
grid( width, tx.height );
|
||||
}
|
||||
|
||||
public void grid( int width, int height ) {
|
||||
grid( 0, 0, width, height, tx.width / width );
|
||||
}
|
||||
|
||||
public void grid( int left, int top, int width, int height, int cols ) {
|
||||
uvLeft = (float)left / tx.width;
|
||||
uvTop = (float)top / tx.height;
|
||||
uvWidth = (float)width / tx.width;
|
||||
uvHeight= (float)height / tx.height;
|
||||
this.cols = cols;
|
||||
}
|
||||
|
||||
public RectF get( int index ) {
|
||||
float x = index % cols;
|
||||
float y = index / cols;
|
||||
float l = uvLeft + x * uvWidth;
|
||||
float t = uvTop + y * uvHeight;
|
||||
return new RectF( l, t, l + uvWidth, t + uvHeight );
|
||||
}
|
||||
|
||||
public RectF get( Object key ) {
|
||||
return namedFrames.get( key );
|
||||
}
|
||||
|
||||
public float width( RectF rect ) {
|
||||
return rect.width() * tx.width;
|
||||
}
|
||||
|
||||
public float height( RectF rect ) {
|
||||
return rect.height() * tx.height;
|
||||
}
|
||||
|
||||
public static RectF uvRect( SmartTexture tx, int left, int top, int right, int bottom ) {
|
||||
return new RectF(
|
||||
(float)left / tx.width,
|
||||
(float)top / tx.height,
|
||||
(float)right / tx.width,
|
||||
(float)bottom / tx.height );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.gltextures;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
public class Gradient extends SmartTexture {
|
||||
|
||||
public Gradient( int colors[] ) {
|
||||
|
||||
super( Bitmap.createBitmap( colors.length, 1, Bitmap.Config.ARGB_8888 ) );
|
||||
|
||||
for (int i=0; i < colors.length; i++) {
|
||||
bitmap.setPixel( i, 0, colors[i] );
|
||||
}
|
||||
bitmap( bitmap );
|
||||
|
||||
filter( LINEAR, LINEAR );
|
||||
wrap( CLAMP, CLAMP );
|
||||
|
||||
TextureCache.add( Gradient.class, this );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.gltextures;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.watabou.glwrap.Texture;
|
||||
|
||||
public class SmartTexture extends Texture {
|
||||
|
||||
public int width;
|
||||
public int height;
|
||||
|
||||
public int fModeMin;
|
||||
public int fModeMax;
|
||||
|
||||
public int wModeH;
|
||||
public int wModeV;
|
||||
|
||||
public Bitmap bitmap;
|
||||
|
||||
public Atlas atlas;
|
||||
|
||||
public SmartTexture( Bitmap bitmap ) {
|
||||
this( bitmap, NEAREST, CLAMP, false );
|
||||
}
|
||||
|
||||
public SmartTexture( Bitmap bitmap, int filtering, int wrapping, boolean premultiplied ) {
|
||||
|
||||
super();
|
||||
|
||||
bitmap( bitmap, premultiplied );
|
||||
filter( filtering, filtering );
|
||||
wrap( wrapping, wrapping );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(int minMode, int maxMode) {
|
||||
super.filter( fModeMin = minMode, fModeMax = maxMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wrap( int s, int t ) {
|
||||
super.wrap( wModeH = s, wModeV = t );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bitmap( Bitmap bitmap ) {
|
||||
bitmap( bitmap, false );
|
||||
}
|
||||
|
||||
public void bitmap( Bitmap bitmap, boolean premultiplied ) {
|
||||
if (premultiplied) {
|
||||
super.bitmap( bitmap );
|
||||
} else {
|
||||
handMade( bitmap, true );
|
||||
}
|
||||
|
||||
this.bitmap = bitmap;
|
||||
width = bitmap.getWidth();
|
||||
height = bitmap.getHeight();
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
id = new SmartTexture( bitmap, NEAREST, CLAMP, premultiplied ).id;
|
||||
filter( fModeMin, fModeMax );
|
||||
wrap( wModeH, wModeV );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
|
||||
super.delete();
|
||||
|
||||
bitmap.recycle();
|
||||
bitmap = null;
|
||||
}
|
||||
|
||||
public RectF uvRect( int left, int top, int right, int bottom ) {
|
||||
return new RectF(
|
||||
(float)left / width,
|
||||
(float)top / height,
|
||||
(float)right / width,
|
||||
(float)bottom / height );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.gltextures;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Shader.TileMode;
|
||||
|
||||
import com.watabou.glwrap.Texture;
|
||||
|
||||
public class TextureCache {
|
||||
|
||||
public static Context context;
|
||||
|
||||
private static HashMap<Object,SmartTexture> all = new HashMap<>();
|
||||
|
||||
// No dithering, no scaling, 32 bits per pixel
|
||||
private static BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
|
||||
static {
|
||||
bitmapOptions.inScaled = false;
|
||||
bitmapOptions.inDither = false;
|
||||
bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
|
||||
}
|
||||
|
||||
public static SmartTexture createSolid( int color ) {
|
||||
final String key = "1x1:" + color;
|
||||
|
||||
if (all.containsKey( key )) {
|
||||
|
||||
return all.get( key );
|
||||
|
||||
} else {
|
||||
|
||||
Bitmap bmp = Bitmap.createBitmap( 1, 1, Bitmap.Config.ARGB_8888 );
|
||||
bmp.eraseColor( color );
|
||||
|
||||
SmartTexture tx = new SmartTexture( bmp );
|
||||
all.put( key, tx );
|
||||
|
||||
return tx;
|
||||
}
|
||||
}
|
||||
|
||||
public static SmartTexture createGradient( int width, int height, int... colors ) {
|
||||
|
||||
final String key = "" + width + "x" + height + ":" + colors;
|
||||
|
||||
if (all.containsKey( key )) {
|
||||
|
||||
return all.get( key );
|
||||
|
||||
} else {
|
||||
|
||||
Bitmap bmp = Bitmap.createBitmap( width, height, Bitmap.Config.ARGB_8888 );
|
||||
Canvas canvas = new Canvas( bmp );
|
||||
Paint paint = new Paint();
|
||||
paint.setShader( new LinearGradient( 0, 0, 0, height, colors, null, TileMode.CLAMP ) );
|
||||
canvas.drawPaint( paint );
|
||||
|
||||
SmartTexture tx = new SmartTexture( bmp );
|
||||
all.put( key, tx );
|
||||
return tx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void add( Object key, SmartTexture tx ) {
|
||||
all.put( key, tx );
|
||||
}
|
||||
|
||||
public static SmartTexture get( Object src ) {
|
||||
|
||||
if (all.containsKey( src )) {
|
||||
|
||||
return all.get( src );
|
||||
|
||||
} else if (src instanceof SmartTexture) {
|
||||
|
||||
return (SmartTexture)src;
|
||||
|
||||
} else {
|
||||
|
||||
SmartTexture tx = new SmartTexture( getBitmap( src ) );
|
||||
all.put( src, tx );
|
||||
return tx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
|
||||
for (Texture txt:all.values()) {
|
||||
txt.delete();
|
||||
}
|
||||
all.clear();
|
||||
|
||||
}
|
||||
|
||||
public static void reload() {
|
||||
for (SmartTexture tx:all.values()) {
|
||||
tx.reload();
|
||||
}
|
||||
}
|
||||
|
||||
public static Bitmap getBitmap( Object src ) {
|
||||
|
||||
try {
|
||||
if (src instanceof Integer){
|
||||
|
||||
return BitmapFactory.decodeResource(
|
||||
context.getResources(), (Integer)src, bitmapOptions );
|
||||
|
||||
} else if (src instanceof String) {
|
||||
|
||||
return BitmapFactory.decodeStream(
|
||||
context.getAssets().open( (String)src ), null, bitmapOptions );
|
||||
|
||||
} else if (src instanceof Bitmap) {
|
||||
|
||||
return (Bitmap)src;
|
||||
|
||||
} else {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean contains( Object key ) {
|
||||
return all.containsKey( key );
|
||||
}
|
||||
|
||||
}
|
51
SPD-classes/src/main/java/com/watabou/glwrap/Attribute.java
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.glwrap;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
public class Attribute {
|
||||
|
||||
private int location;
|
||||
|
||||
public Attribute( int location ) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public int location() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
GLES20.glEnableVertexAttribArray( location );
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
GLES20.glDisableVertexAttribArray( location );
|
||||
}
|
||||
|
||||
public void vertexPointer( int size, int stride, FloatBuffer ptr ) {
|
||||
GLES20.glVertexAttribPointer( location, size, GLES20.GL_FLOAT, false, stride * Float.SIZE / 8, ptr );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.glwrap;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
public class Framebuffer {
|
||||
|
||||
public static final int COLOR = GLES20.GL_COLOR_ATTACHMENT0;
|
||||
public static final int DEPTH = GLES20.GL_DEPTH_ATTACHMENT;
|
||||
public static final int STENCIL = GLES20.GL_STENCIL_ATTACHMENT;
|
||||
|
||||
public static final Framebuffer system = new Framebuffer( 0 );
|
||||
|
||||
private int id;
|
||||
|
||||
public Framebuffer() {
|
||||
int[] buffers = new int[1];
|
||||
GLES20.glGenBuffers( 1, buffers, 0 );
|
||||
id = buffers[0];
|
||||
}
|
||||
|
||||
private Framebuffer( int n ) {
|
||||
|
||||
}
|
||||
|
||||
public void bind() {
|
||||
GLES20.glBindFramebuffer( GLES20.GL_FRAMEBUFFER, id );
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
int[] buffers = {id};
|
||||
GLES20.glDeleteFramebuffers( 1, buffers, 0 );
|
||||
}
|
||||
|
||||
public void attach( int point, Texture tex ) {
|
||||
bind();
|
||||
GLES20.glFramebufferTexture2D( GLES20.GL_FRAMEBUFFER, point, GLES20.GL_TEXTURE_2D, tex.id, 0 );
|
||||
}
|
||||
|
||||
public void attach( int point, Renderbuffer buffer ) {
|
||||
bind();
|
||||
GLES20.glFramebufferRenderbuffer( GLES20.GL_RENDERBUFFER, point, GLES20.GL_TEXTURE_2D, buffer.id() );
|
||||
}
|
||||
|
||||
public boolean status() {
|
||||
bind();
|
||||
return GLES20.glCheckFramebufferStatus( GLES20.GL_FRAMEBUFFER ) == GLES20.GL_FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
}
|
103
SPD-classes/src/main/java/com/watabou/glwrap/Matrix.java
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.glwrap;
|
||||
|
||||
public class Matrix {
|
||||
|
||||
public static final float G2RAD = 0.01745329251994329576923690768489f;
|
||||
|
||||
public static float[] clone( float[] m ) {
|
||||
|
||||
int n = m.length;
|
||||
float[] res = new float[n];
|
||||
do {
|
||||
res[--n] = m[n];
|
||||
} while (n > 0);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static void copy( float[] src, float[] dst ) {
|
||||
|
||||
int n = src.length;
|
||||
do {
|
||||
dst[--n] = src[n];
|
||||
} while (n > 0);
|
||||
|
||||
}
|
||||
|
||||
public static void setIdentity( float[] m ) {
|
||||
for (int i=0 ; i < 16 ; i++) {
|
||||
m[i] = 0f;
|
||||
}
|
||||
for (int i = 0; i < 16; i += 5) {
|
||||
m[i] = 1f;
|
||||
}
|
||||
}
|
||||
|
||||
public static void rotate( float[] m, float a ) {
|
||||
a *= G2RAD;
|
||||
float sin = (float)Math.sin( a );
|
||||
float cos = (float)Math.cos( a );
|
||||
float m0 = m[0];
|
||||
float m1 = m[1];
|
||||
float m4 = m[4];
|
||||
float m5 = m[5];
|
||||
m[0] = m0 * cos + m4 * sin;
|
||||
m[1] = m1 * cos + m5 * sin;
|
||||
m[4] = -m0 * sin + m4 * cos;
|
||||
m[5] = -m1 * sin + m5 * cos;
|
||||
}
|
||||
|
||||
public static void skewX( float[] m, float a ) {
|
||||
double t = Math.tan( a * G2RAD );
|
||||
m[4] += -m[0] * t;
|
||||
m[5] += -m[1] * t;
|
||||
}
|
||||
|
||||
public static void skewY( float[] m, float a ) {
|
||||
double t = Math.tan( a * G2RAD );
|
||||
m[0] += m[4] * t;
|
||||
m[1] += m[5] * t;
|
||||
}
|
||||
|
||||
public static void scale( float[] m, float x, float y ) {
|
||||
m[0] *= x;
|
||||
m[1] *= x;
|
||||
m[2] *= x;
|
||||
m[3] *= x;
|
||||
m[4] *= y;
|
||||
m[5] *= y;
|
||||
m[6] *= y;
|
||||
m[7] *= y;
|
||||
// android.opengl.Matrix.scaleM( m, 0, x, y, 1 );
|
||||
}
|
||||
|
||||
public static void translate( float[] m, float x, float y ) {
|
||||
m[12] += m[0] * x + m[4] * y;
|
||||
m[13] += m[1] * x + m[5] * y;
|
||||
}
|
||||
|
||||
public static void multiply( float[] left, float right[], float[] result ) {
|
||||
android.opengl.Matrix.multiplyMM( result, 0, left, 0, right, 0 );
|
||||
}
|
||||
}
|
76
SPD-classes/src/main/java/com/watabou/glwrap/Program.java
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.glwrap;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
public class Program {
|
||||
|
||||
private int handle;
|
||||
|
||||
public Program() {
|
||||
handle = GLES20.glCreateProgram();
|
||||
}
|
||||
|
||||
public int handle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
public void attach( Shader shader ) {
|
||||
GLES20.glAttachShader( handle, shader.handle() );
|
||||
}
|
||||
|
||||
public void link() {
|
||||
GLES20.glLinkProgram( handle );
|
||||
|
||||
int[] status = new int[1];
|
||||
GLES20.glGetProgramiv( handle, GLES20.GL_LINK_STATUS, status, 0 );
|
||||
if (status[0] == GLES20.GL_FALSE) {
|
||||
throw new Error( GLES20.glGetProgramInfoLog( handle ) );
|
||||
}
|
||||
}
|
||||
|
||||
public Attribute attribute( String name ) {
|
||||
return new Attribute( GLES20.glGetAttribLocation( handle, name ) );
|
||||
}
|
||||
|
||||
public Uniform uniform( String name ) {
|
||||
return new Uniform( GLES20.glGetUniformLocation( handle, name ) );
|
||||
}
|
||||
|
||||
public void use() {
|
||||
GLES20.glUseProgram( handle );
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
GLES20.glDeleteProgram( handle );
|
||||
}
|
||||
|
||||
public static Program create( Shader ...shaders ) {
|
||||
Program program = new Program();
|
||||
for (int i=0; i < shaders.length; i++) {
|
||||
program.attach( shaders[i] );
|
||||
}
|
||||
program.link();
|
||||
return program;
|
||||
}
|
||||
}
|
140
SPD-classes/src/main/java/com/watabou/glwrap/Quad.java
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.glwrap;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
public class Quad {
|
||||
|
||||
// 0---1
|
||||
// | \ |
|
||||
// 3---2
|
||||
public static final short[] VALUES = {0, 1, 2, 0, 2, 3};
|
||||
|
||||
public static final int SIZE = VALUES.length;
|
||||
|
||||
private static ShortBuffer indices;
|
||||
private static int indexSize = 0;
|
||||
|
||||
public static FloatBuffer create() {
|
||||
return ByteBuffer.
|
||||
allocateDirect( 16 * Float.SIZE / 8 ).
|
||||
order( ByteOrder.nativeOrder() ).
|
||||
asFloatBuffer();
|
||||
}
|
||||
|
||||
public static FloatBuffer createSet( int size ) {
|
||||
return ByteBuffer.
|
||||
allocateDirect( size * 16 * Float.SIZE / 8 ).
|
||||
order( ByteOrder.nativeOrder() ).
|
||||
asFloatBuffer();
|
||||
}
|
||||
|
||||
public static ShortBuffer getIndices( int size ) {
|
||||
|
||||
if (size > indexSize) {
|
||||
|
||||
// TODO: Optimize it!
|
||||
|
||||
indexSize = size;
|
||||
indices = ByteBuffer.
|
||||
allocateDirect( size * SIZE * Short.SIZE / 8 ).
|
||||
order( ByteOrder.nativeOrder() ).
|
||||
asShortBuffer();
|
||||
|
||||
short[] values = new short[size * 6];
|
||||
int pos = 0;
|
||||
int limit = size * 4;
|
||||
for (int ofs=0; ofs < limit; ofs += 4) {
|
||||
values[pos++] = (short)(ofs + 0);
|
||||
values[pos++] = (short)(ofs + 1);
|
||||
values[pos++] = (short)(ofs + 2);
|
||||
values[pos++] = (short)(ofs + 0);
|
||||
values[pos++] = (short)(ofs + 2);
|
||||
values[pos++] = (short)(ofs + 3);
|
||||
}
|
||||
|
||||
indices.put( values );
|
||||
indices.position( 0 );
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
public static void fill( float[] v,
|
||||
float x1, float x2, float y1, float y2,
|
||||
float u1, float u2, float v1, float v2 ) {
|
||||
|
||||
v[0] = x1;
|
||||
v[1] = y1;
|
||||
v[2] = u1;
|
||||
v[3] = v1;
|
||||
|
||||
v[4] = x2;
|
||||
v[5] = y1;
|
||||
v[6] = u2;
|
||||
v[7] = v1;
|
||||
|
||||
v[8] = x2;
|
||||
v[9] = y2;
|
||||
v[10]= u2;
|
||||
v[11]= v2;
|
||||
|
||||
v[12]= x1;
|
||||
v[13]= y2;
|
||||
v[14]= u1;
|
||||
v[15]= v2;
|
||||
}
|
||||
|
||||
public static void fillXY( float[] v, float x1, float x2, float y1, float y2 ) {
|
||||
|
||||
v[0] = x1;
|
||||
v[1] = y1;
|
||||
|
||||
v[4] = x2;
|
||||
v[5] = y1;
|
||||
|
||||
v[8] = x2;
|
||||
v[9] = y2;
|
||||
|
||||
v[12]= x1;
|
||||
v[13]= y2;
|
||||
}
|
||||
|
||||
public static void fillUV( float[] v, float u1, float u2, float v1, float v2 ) {
|
||||
|
||||
v[2] = u1;
|
||||
v[3] = v1;
|
||||
|
||||
v[6] = u2;
|
||||
v[7] = v1;
|
||||
|
||||
v[10]= u2;
|
||||
v[11]= v2;
|
||||
|
||||
v[14]= u1;
|
||||
v[15]= v2;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.glwrap;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
public class Renderbuffer {
|
||||
|
||||
public static final int RGBA8 = GLES20.GL_RGBA; // ?
|
||||
public static final int DEPTH16 = GLES20.GL_DEPTH_COMPONENT16;
|
||||
public static final int STENCIL8 = GLES20.GL_STENCIL_INDEX8;
|
||||
|
||||
private int id;
|
||||
|
||||
public Renderbuffer() {
|
||||
int[] buffers = new int[1];
|
||||
GLES20.glGenRenderbuffers( 1, buffers, 0 );
|
||||
id = buffers[0];
|
||||
}
|
||||
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void bind() {
|
||||
GLES20.glBindRenderbuffer( GLES20.GL_RENDERBUFFER, id );
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
int[] buffers = {id};
|
||||
GLES20.glDeleteRenderbuffers( 1, buffers, 0 );
|
||||
}
|
||||
|
||||
public void storage( int format, int width, int height ) {
|
||||
GLES20.glRenderbufferStorage( GLES20.GL_RENDERBUFFER, format , width, height );
|
||||
}
|
||||
}
|
65
SPD-classes/src/main/java/com/watabou/glwrap/Shader.java
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.glwrap;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
public class Shader {
|
||||
|
||||
public static final int VERTEX = GLES20.GL_VERTEX_SHADER;
|
||||
public static final int FRAGMENT = GLES20.GL_FRAGMENT_SHADER;
|
||||
|
||||
private int handle;
|
||||
|
||||
public Shader( int type ) {
|
||||
handle = GLES20.glCreateShader( type );
|
||||
}
|
||||
|
||||
public int handle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
public void source( String src ) {
|
||||
GLES20.glShaderSource( handle, src );
|
||||
}
|
||||
|
||||
public void compile() {
|
||||
GLES20.glCompileShader( handle );
|
||||
|
||||
int[] status = new int[1];
|
||||
GLES20.glGetShaderiv( handle, GLES20.GL_COMPILE_STATUS, status, 0 );
|
||||
if (status[0] == GLES20.GL_FALSE) {
|
||||
throw new Error( GLES20.glGetShaderInfoLog( handle ) );
|
||||
}
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
GLES20.glDeleteShader( handle );
|
||||
}
|
||||
|
||||
public static Shader createCompiled( int type, String src ) {
|
||||
Shader shader = new Shader( type );
|
||||
shader.source( src );
|
||||
shader.compile();
|
||||
return shader;
|
||||
}
|
||||
}
|
183
SPD-classes/src/main/java/com/watabou/glwrap/Texture.java
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.glwrap;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.opengl.GLES20;
|
||||
import android.opengl.GLUtils;
|
||||
|
||||
public class Texture {
|
||||
|
||||
public static final int NEAREST = GLES20.GL_NEAREST;
|
||||
public static final int LINEAR = GLES20.GL_LINEAR;
|
||||
|
||||
public static final int REPEAT = GLES20.GL_REPEAT;
|
||||
public static final int MIRROR = GLES20.GL_MIRRORED_REPEAT;
|
||||
public static final int CLAMP = GLES20.GL_CLAMP_TO_EDGE;
|
||||
|
||||
public int id;
|
||||
private static int bound_id = 0; //id of the currently bound texture
|
||||
|
||||
public boolean premultiplied = false;
|
||||
|
||||
public Texture() {
|
||||
int[] ids = new int[1];
|
||||
GLES20.glGenTextures( 1, ids, 0 );
|
||||
id = ids[0];
|
||||
|
||||
bind();
|
||||
}
|
||||
|
||||
public static void activate( int index ) {
|
||||
GLES20.glActiveTexture( GLES20.GL_TEXTURE0 + index );
|
||||
}
|
||||
|
||||
public void bind() {
|
||||
if (id != bound_id) {
|
||||
GLES20.glBindTexture( GLES20.GL_TEXTURE_2D, id );
|
||||
bound_id = id;
|
||||
}
|
||||
}
|
||||
|
||||
public void filter( int minMode, int maxMode ) {
|
||||
bind();
|
||||
GLES20.glTexParameterf( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, minMode );
|
||||
GLES20.glTexParameterf( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, maxMode );
|
||||
}
|
||||
|
||||
public void wrap( int s, int t ) {
|
||||
bind();
|
||||
GLES20.glTexParameterf( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, s );
|
||||
GLES20.glTexParameterf( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, t );
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
if (bound_id == id) bound_id = 0;
|
||||
int[] ids = {id};
|
||||
GLES20.glDeleteTextures( 1, ids, 0 );
|
||||
}
|
||||
|
||||
public void bitmap( Bitmap bitmap ) {
|
||||
bind();
|
||||
GLUtils.texImage2D( GLES20.GL_TEXTURE_2D, 0, bitmap, 0 );
|
||||
|
||||
premultiplied = true;
|
||||
}
|
||||
|
||||
public void pixels( int w, int h, int[] pixels ) {
|
||||
|
||||
bind();
|
||||
|
||||
IntBuffer imageBuffer = ByteBuffer.
|
||||
allocateDirect( w * h * 4 ).
|
||||
order( ByteOrder.nativeOrder() ).
|
||||
asIntBuffer();
|
||||
imageBuffer.put( pixels );
|
||||
imageBuffer.position( 0 );
|
||||
|
||||
GLES20.glTexImage2D(
|
||||
GLES20.GL_TEXTURE_2D,
|
||||
0,
|
||||
GLES20.GL_RGBA,
|
||||
w,
|
||||
h,
|
||||
0,
|
||||
GLES20.GL_RGBA,
|
||||
GLES20.GL_UNSIGNED_BYTE,
|
||||
imageBuffer );
|
||||
}
|
||||
|
||||
public void pixels( int w, int h, byte[] pixels ) {
|
||||
|
||||
bind();
|
||||
|
||||
ByteBuffer imageBuffer = ByteBuffer.
|
||||
allocateDirect( w * h ).
|
||||
order( ByteOrder.nativeOrder() );
|
||||
imageBuffer.put( pixels );
|
||||
imageBuffer.position( 0 );
|
||||
|
||||
GLES20.glPixelStorei( GLES20.GL_UNPACK_ALIGNMENT, 1 );
|
||||
|
||||
GLES20.glTexImage2D(
|
||||
GLES20.GL_TEXTURE_2D,
|
||||
0,
|
||||
GLES20.GL_ALPHA,
|
||||
w,
|
||||
h,
|
||||
0,
|
||||
GLES20.GL_ALPHA,
|
||||
GLES20.GL_UNSIGNED_BYTE,
|
||||
imageBuffer );
|
||||
}
|
||||
|
||||
// If getConfig returns null (unsupported format?), GLUtils.texImage2D works
|
||||
// incorrectly. In this case we need to load pixels manually
|
||||
public void handMade( Bitmap bitmap, boolean recode ) {
|
||||
|
||||
int w = bitmap.getWidth();
|
||||
int h = bitmap.getHeight();
|
||||
|
||||
int[] pixels = new int[w * h];
|
||||
bitmap.getPixels( pixels, 0, w, 0, 0, w, h );
|
||||
|
||||
// recode - components reordering is needed
|
||||
if (recode) {
|
||||
for (int i=0; i < pixels.length; i++) {
|
||||
int color = pixels[i];
|
||||
int ag = color & 0xFF00FF00;
|
||||
int r = (color >> 16) & 0xFF;
|
||||
int b = color & 0xFF;
|
||||
pixels[i] = ag | (b << 16) | r;
|
||||
}
|
||||
}
|
||||
|
||||
pixels( w, h, pixels );
|
||||
|
||||
premultiplied = false;
|
||||
}
|
||||
|
||||
public static Texture create( Bitmap bmp ) {
|
||||
Texture tex = new Texture();
|
||||
tex.bitmap( bmp );
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
public static Texture create( int width, int height, int[] pixels ) {
|
||||
Texture tex = new Texture();
|
||||
tex.pixels( width, height, pixels );
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
public static Texture create( int width, int height, byte[] pixels ) {
|
||||
Texture tex = new Texture();
|
||||
tex.pixels( width, height, pixels );
|
||||
|
||||
return tex;
|
||||
}
|
||||
}
|
69
SPD-classes/src/main/java/com/watabou/glwrap/Uniform.java
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.glwrap;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
public class Uniform {
|
||||
|
||||
private int location;
|
||||
|
||||
public Uniform( int location ) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public int location() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
GLES20.glEnableVertexAttribArray( location );
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
GLES20.glDisableVertexAttribArray( location );
|
||||
}
|
||||
|
||||
public void value( int value ) {
|
||||
GLES20.glUniform1i( location, value );
|
||||
}
|
||||
|
||||
public void value1f( float value ) {
|
||||
GLES20.glUniform1f( location, value );
|
||||
}
|
||||
|
||||
public void value2f( float v1, float v2 ) {
|
||||
GLES20.glUniform2f( location, v1, v2 );
|
||||
}
|
||||
|
||||
public void value4f( float v1, float v2, float v3, float v4 ) {
|
||||
GLES20.glUniform4f( location, v1, v2, v3, v4 );
|
||||
}
|
||||
|
||||
public void valueM3( float[] value ) {
|
||||
GLES20.glUniformMatrix3fv( location, 1, false, value, 0 );
|
||||
}
|
||||
|
||||
public void valueM4( float[] value ) {
|
||||
GLES20.glUniformMatrix4fv( location, 1, false, value, 0 );
|
||||
}
|
||||
}
|
65
SPD-classes/src/main/java/com/watabou/input/Keys.java
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.input;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.watabou.utils.Signal;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
public class Keys {
|
||||
|
||||
public static final int BACK = KeyEvent.KEYCODE_BACK;
|
||||
public static final int MENU = KeyEvent.KEYCODE_MENU;
|
||||
|
||||
public static Signal<Key> event = new Signal<Key>( true );
|
||||
|
||||
public static void processTouchEvents( ArrayList<KeyEvent> events ) {
|
||||
|
||||
int size = events.size();
|
||||
for (int i=0; i < size; i++) {
|
||||
|
||||
KeyEvent e = events.get( i );
|
||||
|
||||
switch (e.getAction()) {
|
||||
case KeyEvent.ACTION_DOWN:
|
||||
event.dispatch( new Key( e.getKeyCode(), true ) );
|
||||
break;
|
||||
case KeyEvent.ACTION_UP:
|
||||
event.dispatch( new Key( e.getKeyCode(), false ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Key {
|
||||
|
||||
public int code;
|
||||
public boolean pressed;
|
||||
|
||||
public Key( int code, boolean pressed ) {
|
||||
this.code = code;
|
||||
this.pressed = pressed;
|
||||
}
|
||||
}
|
||||
}
|
116
SPD-classes/src/main/java/com/watabou/input/Touchscreen.java
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.input;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.watabou.utils.PointF;
|
||||
import com.watabou.utils.Signal;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class Touchscreen {
|
||||
|
||||
public static Signal<Touch> event = new Signal<Touch>( true );
|
||||
|
||||
public static HashMap<Integer,Touch> pointers = new HashMap<Integer, Touch>();
|
||||
|
||||
public static float x;
|
||||
public static float y;
|
||||
public static boolean touched;
|
||||
|
||||
public static void processTouchEvents( ArrayList<MotionEvent> events ) {
|
||||
|
||||
int size = events.size();
|
||||
for (int i=0; i < size; i++) {
|
||||
|
||||
MotionEvent e = events.get( i );
|
||||
Touch touch;
|
||||
|
||||
switch (e.getAction() & MotionEvent.ACTION_MASK) {
|
||||
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
touched = true;
|
||||
touch = new Touch( e, 0 );
|
||||
pointers.put( e.getPointerId( 0 ), touch );
|
||||
event.dispatch( touch );
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
int index = e.getActionIndex();
|
||||
touch = new Touch( e, index );
|
||||
pointers.put( e.getPointerId( index ), touch );
|
||||
event.dispatch( touch );
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
int count = e.getPointerCount();
|
||||
for (int j=0; j < count; j++) {
|
||||
pointers.get( e.getPointerId( j ) ).update( e, j );
|
||||
}
|
||||
event.dispatch( null );
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
event.dispatch( pointers.remove( e.getPointerId( e.getActionIndex() ) ).up() );
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
touched = false;
|
||||
event.dispatch( pointers.remove( e.getPointerId( 0 ) ).up() );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
e.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Touch {
|
||||
|
||||
public PointF start;
|
||||
public PointF current;
|
||||
public boolean down;
|
||||
|
||||
public Touch( MotionEvent e, int index ) {
|
||||
|
||||
float x = e.getX( index );
|
||||
float y = e.getY( index );
|
||||
|
||||
start = new PointF( x, y );
|
||||
current = new PointF( x, y );
|
||||
|
||||
down = true;
|
||||
}
|
||||
|
||||
public void update( MotionEvent e, int index ) {
|
||||
current.set( e.getX( index ), e.getY( index ) );
|
||||
}
|
||||
|
||||
public Touch up() {
|
||||
down = false;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
353
SPD-classes/src/main/java/com/watabou/noosa/BitmapText.java
Normal file
|
@ -0,0 +1,353 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import com.watabou.gltextures.SmartTexture;
|
||||
import com.watabou.gltextures.TextureCache;
|
||||
import com.watabou.glwrap.Matrix;
|
||||
import com.watabou.glwrap.Quad;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.RectF;
|
||||
|
||||
public class BitmapText extends Visual {
|
||||
|
||||
protected String text;
|
||||
protected Font font;
|
||||
|
||||
protected float[] vertices = new float[16];
|
||||
protected FloatBuffer quads;
|
||||
|
||||
public int realLength;
|
||||
|
||||
protected boolean dirty = true;
|
||||
|
||||
public BitmapText() {
|
||||
this( "", null );
|
||||
}
|
||||
|
||||
public BitmapText( Font font ) {
|
||||
this( "", font );
|
||||
}
|
||||
|
||||
public BitmapText( String text, Font font ) {
|
||||
super( 0, 0, 0, 0 );
|
||||
|
||||
this.text = text;
|
||||
this.font = font;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
text = null;
|
||||
font = null;
|
||||
vertices = null;
|
||||
quads = null;
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateMatrix() {
|
||||
// "origin" field is ignored
|
||||
Matrix.setIdentity( matrix );
|
||||
Matrix.translate( matrix, x, y );
|
||||
Matrix.scale( matrix, scale.x, scale.y );
|
||||
Matrix.rotate( matrix, angle );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
|
||||
super.draw();
|
||||
|
||||
NoosaScript script = NoosaScript.get();
|
||||
|
||||
font.texture.bind();
|
||||
|
||||
if (dirty) {
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
script.camera( camera() );
|
||||
|
||||
script.uModel.valueM4( matrix );
|
||||
script.lighting(
|
||||
rm, gm, bm, am,
|
||||
ra, ga, ba, aa );
|
||||
script.drawQuadSet( quads, realLength );
|
||||
|
||||
}
|
||||
|
||||
protected void updateVertices() {
|
||||
|
||||
width = 0;
|
||||
height = 0;
|
||||
|
||||
if (text == null) {
|
||||
text = "";
|
||||
}
|
||||
|
||||
quads = Quad.createSet( text.length() );
|
||||
realLength = 0;
|
||||
|
||||
int length = text.length();
|
||||
for (int i=0; i < length; i++) {
|
||||
RectF rect = font.get( text.charAt( i ) );
|
||||
|
||||
if (rect == null) {
|
||||
rect=null;
|
||||
}
|
||||
float w = font.width( rect );
|
||||
float h = font.height( rect );
|
||||
|
||||
vertices[0] = width;
|
||||
vertices[1] = 0;
|
||||
|
||||
vertices[2] = rect.left;
|
||||
vertices[3] = rect.top;
|
||||
|
||||
vertices[4] = width + w;
|
||||
vertices[5] = 0;
|
||||
|
||||
vertices[6] = rect.right;
|
||||
vertices[7] = rect.top;
|
||||
|
||||
vertices[8] = width + w;
|
||||
vertices[9] = h;
|
||||
|
||||
vertices[10] = rect.right;
|
||||
vertices[11] = rect.bottom;
|
||||
|
||||
vertices[12] = width;
|
||||
vertices[13] = h;
|
||||
|
||||
vertices[14] = rect.left;
|
||||
vertices[15] = rect.bottom;
|
||||
|
||||
quads.put( vertices );
|
||||
realLength++;
|
||||
|
||||
width += w + font.tracking;
|
||||
if (h > height) {
|
||||
height = h;
|
||||
}
|
||||
}
|
||||
|
||||
if (length > 0) {
|
||||
width -= font.tracking;
|
||||
}
|
||||
|
||||
dirty = false;
|
||||
|
||||
}
|
||||
|
||||
public void measure() {
|
||||
|
||||
width = 0;
|
||||
height = 0;
|
||||
|
||||
if (text == null) {
|
||||
text = "";
|
||||
}
|
||||
|
||||
int length = text.length();
|
||||
for (int i=0; i < length; i++) {
|
||||
RectF rect = font.get( text.charAt( i ) );
|
||||
|
||||
float w = font.width( rect );
|
||||
float h = font.height( rect );
|
||||
|
||||
width += w + font.tracking;
|
||||
if (h > height) {
|
||||
height = h;
|
||||
}
|
||||
}
|
||||
|
||||
if (length > 0) {
|
||||
width -= font.tracking;
|
||||
}
|
||||
}
|
||||
|
||||
public float baseLine() {
|
||||
return font.baseLine * scale.y;
|
||||
}
|
||||
|
||||
public Font font() {
|
||||
return font;
|
||||
}
|
||||
|
||||
public void font( Font value ) {
|
||||
font = value;
|
||||
}
|
||||
|
||||
public String text() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void text( String str ) {
|
||||
text = str;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public static class Font extends TextureFilm {
|
||||
|
||||
public static final String LATIN_FULL =
|
||||
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u007F";
|
||||
|
||||
public SmartTexture texture;
|
||||
|
||||
public float tracking = 0;
|
||||
public float baseLine;
|
||||
|
||||
public float lineHeight;
|
||||
|
||||
protected Font( SmartTexture tx ) {
|
||||
super( tx );
|
||||
|
||||
texture = tx;
|
||||
}
|
||||
|
||||
public Font( SmartTexture tx, int width, String chars ) {
|
||||
this( tx, width, tx.height, chars );
|
||||
}
|
||||
|
||||
public Font( SmartTexture tx, int width, int height, String chars ) {
|
||||
super( tx );
|
||||
|
||||
texture = tx;
|
||||
|
||||
int length = chars.length();
|
||||
|
||||
float uw = (float)width / tx.width;
|
||||
float vh = (float)height / tx.height;
|
||||
|
||||
float left = 0;
|
||||
float top = 0;
|
||||
float bottom = vh;
|
||||
|
||||
for (int i=0; i < length; i++) {
|
||||
RectF rect = new RectF( left, top, left += uw, bottom );
|
||||
add( chars.charAt( i ), rect );
|
||||
if (left >= 1) {
|
||||
left = 0;
|
||||
top = bottom;
|
||||
bottom += vh;
|
||||
}
|
||||
}
|
||||
|
||||
lineHeight = baseLine = height;
|
||||
}
|
||||
|
||||
protected void splitBy( Bitmap bitmap, int height, int color, String chars ) {
|
||||
|
||||
int length = chars.length();
|
||||
|
||||
int width = bitmap.getWidth();
|
||||
float vHeight = (float)height / bitmap.getHeight();
|
||||
|
||||
int pos;
|
||||
int line = 0;
|
||||
|
||||
spaceMeasuring:
|
||||
for (pos=0; pos < width; pos++) {
|
||||
for (int j=0; j < height; j++) {
|
||||
if (bitmap.getPixel( pos, j ) != color) {
|
||||
break spaceMeasuring;
|
||||
}
|
||||
}
|
||||
}
|
||||
add( ' ', new RectF( 0, 0, (float)pos / width, vHeight-0.01f ) );
|
||||
|
||||
int separator = pos;
|
||||
|
||||
for (int i=0; i < length; i++) {
|
||||
|
||||
char ch = chars.charAt( i );
|
||||
if (ch == ' ') {
|
||||
continue;
|
||||
} else {
|
||||
|
||||
boolean found;
|
||||
|
||||
do{
|
||||
if (separator >= width) {
|
||||
line += height;
|
||||
separator = 0;
|
||||
}
|
||||
found = false;
|
||||
for (int j=line; j < line + height; j++) {
|
||||
if (bitmap.getPixel( separator, j ) != color) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) separator++;
|
||||
} while (!found);
|
||||
int start = separator;
|
||||
|
||||
do {
|
||||
if (++separator >= width) {
|
||||
line += height;
|
||||
separator = start = 0;
|
||||
if (line + height >= bitmap.getHeight())
|
||||
break;
|
||||
}
|
||||
found = true;
|
||||
for (int j=line; j < line + height; j++) {
|
||||
if (bitmap.getPixel( separator, j ) != color) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!found);
|
||||
|
||||
add( ch, new RectF( (float)start / width, (float)line / bitmap.getHeight(), (float)separator / width, (float)line / bitmap.getHeight() + vHeight) );
|
||||
separator++;
|
||||
}
|
||||
}
|
||||
|
||||
lineHeight = baseLine = height( frames.get( chars.charAt( 0 ) ) );
|
||||
}
|
||||
|
||||
public static Font colorMarked( Bitmap bmp, int color, String chars ) {
|
||||
Font font = new Font( TextureCache.get( bmp ) );
|
||||
font.splitBy( bmp, bmp.getHeight(), color, chars );
|
||||
return font;
|
||||
}
|
||||
|
||||
public static Font colorMarked( Bitmap bmp, int height, int color, String chars ) {
|
||||
Font font = new Font( TextureCache.get( bmp ) );
|
||||
font.splitBy( bmp, height, color, chars );
|
||||
return font;
|
||||
}
|
||||
|
||||
public RectF get( char ch ) {
|
||||
if (frames.containsKey( ch )){
|
||||
return super.get( ch );
|
||||
} else {
|
||||
return super.get( '?' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.watabou.glwrap.Quad;
|
||||
import com.watabou.utils.PointF;
|
||||
|
||||
public class BitmapTextMultiline extends BitmapText {
|
||||
|
||||
public int maxWidth = Integer.MAX_VALUE;
|
||||
|
||||
protected static final Pattern PARAGRAPH = Pattern.compile( "\n" );
|
||||
protected static final Pattern WORD = Pattern.compile( "\\s+" );
|
||||
|
||||
protected float spaceSize;
|
||||
|
||||
public int nLines = 0;
|
||||
|
||||
public boolean[] mask;
|
||||
|
||||
public BitmapTextMultiline( Font font ) {
|
||||
this( "", font );
|
||||
}
|
||||
|
||||
public BitmapTextMultiline( String text, Font font ) {
|
||||
super( text, font );
|
||||
spaceSize = font.width( font.get( ' ' ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateVertices() {
|
||||
|
||||
if (text == null) {
|
||||
text = "";
|
||||
}
|
||||
|
||||
quads = Quad.createSet( text.length() );
|
||||
realLength = 0;
|
||||
|
||||
// This object controls lines breaking
|
||||
SymbolWriter writer = new SymbolWriter();
|
||||
|
||||
// Word size
|
||||
PointF metrics = new PointF();
|
||||
|
||||
String paragraphs[] = PARAGRAPH.split( text );
|
||||
|
||||
// Current character (used in masking)
|
||||
int pos = 0;
|
||||
|
||||
for (int i=0; i < paragraphs.length; i++) {
|
||||
|
||||
String[] words = WORD.split( paragraphs[i] );
|
||||
|
||||
for (int j=0; j < words.length; j++) {
|
||||
|
||||
String word = words[j];
|
||||
if (word.length() == 0) {
|
||||
// This case is possible when there are
|
||||
// several spaces coming along
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
getWordMetrics( word, metrics );
|
||||
writer.addSymbol( metrics.x, metrics.y );
|
||||
|
||||
int length = word.length();
|
||||
float shift = 0; // Position in pixels relative to the beginning of the word
|
||||
|
||||
for (int k=0; k < length; k++) {
|
||||
RectF rect = font.get( word.charAt( k ) );
|
||||
|
||||
float w = font.width( rect );
|
||||
float h = font.height( rect );
|
||||
|
||||
if (mask == null || mask[pos]) {
|
||||
vertices[0] = writer.x + shift;
|
||||
vertices[1] = writer.y;
|
||||
|
||||
vertices[2] = rect.left;
|
||||
vertices[3] = rect.top;
|
||||
|
||||
vertices[4] = writer.x + shift + w;
|
||||
vertices[5] = writer.y;
|
||||
|
||||
vertices[6] = rect.right;
|
||||
vertices[7] = rect.top;
|
||||
|
||||
vertices[8] = writer.x + shift + w;
|
||||
vertices[9] = writer.y + h;
|
||||
|
||||
vertices[10] = rect.right;
|
||||
vertices[11] = rect.bottom;
|
||||
|
||||
vertices[12] = writer.x + shift;
|
||||
vertices[13] = writer.y + h;
|
||||
|
||||
vertices[14] = rect.left;
|
||||
vertices[15] = rect.bottom;
|
||||
|
||||
quads.put( vertices );
|
||||
realLength++;
|
||||
}
|
||||
|
||||
shift += w + font.tracking;
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
writer.addSpace( spaceSize );
|
||||
}
|
||||
|
||||
writer.newLine( 0, font.lineHeight );
|
||||
}
|
||||
|
||||
nLines = writer.nLines();
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
private void getWordMetrics( String word, PointF metrics ) {
|
||||
|
||||
float w = 0;
|
||||
float h = 0;
|
||||
|
||||
int length = word.length();
|
||||
for (int i=0; i < length; i++) {
|
||||
|
||||
RectF rect = font.get( word.charAt( i ) );
|
||||
w += font.width( rect ) + (w > 0 ? font.tracking : 0);
|
||||
h = Math.max( h, font.height( rect ) );
|
||||
}
|
||||
|
||||
metrics.set( w, h );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void measure() {
|
||||
|
||||
SymbolWriter writer = new SymbolWriter();
|
||||
|
||||
PointF metrics = new PointF();
|
||||
|
||||
String paragraphs[] = PARAGRAPH.split( text );
|
||||
|
||||
for (int i=0; i < paragraphs.length; i++) {
|
||||
|
||||
String[] words = WORD.split( paragraphs[i] );
|
||||
|
||||
for (int j=0; j < words.length; j++) {
|
||||
|
||||
if (j > 0) {
|
||||
writer.addSpace( spaceSize );
|
||||
}
|
||||
String word = words[j];
|
||||
if (word.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
getWordMetrics( word, metrics );
|
||||
writer.addSymbol( metrics.x, metrics.y );
|
||||
}
|
||||
|
||||
writer.newLine( 0, font.lineHeight );
|
||||
}
|
||||
|
||||
width = writer.width;
|
||||
height = writer.height;
|
||||
|
||||
nLines = writer.nLines();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float baseLine() {
|
||||
return (height - font.lineHeight + font.baseLine) * scale.y;
|
||||
}
|
||||
|
||||
private class SymbolWriter {
|
||||
|
||||
public float width = 0;
|
||||
public float height = 0;
|
||||
|
||||
public int nLines = 0;
|
||||
|
||||
public float lineWidth = 0;
|
||||
public float lineHeight = 0;
|
||||
|
||||
public float x = 0;
|
||||
public float y = 0;
|
||||
|
||||
public void addSymbol( float w, float h ) {
|
||||
if (lineWidth > 0 && lineWidth + font.tracking + w > maxWidth / scale.x) {
|
||||
newLine( w, h );
|
||||
} else {
|
||||
|
||||
x = lineWidth;
|
||||
|
||||
lineWidth += (lineWidth > 0 ? font.tracking : 0) + w;
|
||||
if (h > lineHeight) {
|
||||
lineHeight = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addSpace( float w ) {
|
||||
if (lineWidth > 0 && lineWidth + font.tracking + w > maxWidth / scale.x) {
|
||||
newLine( 0, 0 );
|
||||
} else {
|
||||
|
||||
x = lineWidth;
|
||||
lineWidth += (lineWidth > 0 ? font.tracking : 0) + w;
|
||||
}
|
||||
}
|
||||
|
||||
public void newLine( float w, float h ) {
|
||||
|
||||
height += lineHeight;
|
||||
if (width < lineWidth) {
|
||||
width = lineWidth;
|
||||
}
|
||||
|
||||
lineWidth = w;
|
||||
lineHeight = h;
|
||||
|
||||
x = 0;
|
||||
y = height;
|
||||
|
||||
nLines++;
|
||||
}
|
||||
|
||||
public int nLines() {
|
||||
return x == 0 ? nLines : nLines+1;
|
||||
}
|
||||
}
|
||||
|
||||
public class LineSplitter {
|
||||
|
||||
private ArrayList<BitmapText> lines;
|
||||
|
||||
private StringBuilder curLine;
|
||||
private float curLineWidth;
|
||||
|
||||
private PointF metrics = new PointF();
|
||||
|
||||
private void newLine( String str, float width ) {
|
||||
BitmapText txt = new BitmapText( curLine.toString(), font );
|
||||
txt.scale.set( scale.x );
|
||||
lines.add( txt );
|
||||
|
||||
curLine = new StringBuilder( str );
|
||||
curLineWidth = width;
|
||||
}
|
||||
|
||||
private void append( String str, float width ) {
|
||||
curLineWidth += (curLineWidth > 0 ? font.tracking : 0) + width;
|
||||
curLine.append( str );
|
||||
}
|
||||
|
||||
public ArrayList<BitmapText> split() {
|
||||
|
||||
lines = new ArrayList<>();
|
||||
|
||||
curLine = new StringBuilder();
|
||||
curLineWidth = 0;
|
||||
|
||||
String paragraphs[] = PARAGRAPH.split( text );
|
||||
|
||||
for (int i=0; i < paragraphs.length; i++) {
|
||||
|
||||
String[] words = WORD.split( paragraphs[i] );
|
||||
|
||||
for (int j=0; j < words.length; j++) {
|
||||
|
||||
String word = words[j];
|
||||
if (word.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
getWordMetrics( word, metrics );
|
||||
|
||||
if (curLineWidth > 0 && curLineWidth + font.tracking + metrics.x > maxWidth / scale.x) {
|
||||
newLine( word, metrics.x );
|
||||
} else {
|
||||
append( word, metrics.x );
|
||||
}
|
||||
|
||||
if (curLineWidth > 0 && curLineWidth + font.tracking + spaceSize > maxWidth / scale.x) {
|
||||
newLine( "", 0 );
|
||||
} else {
|
||||
append( " ", spaceSize );
|
||||
}
|
||||
}
|
||||
|
||||
newLine( "", 0 );
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
}
|
236
SPD-classes/src/main/java/com/watabou/noosa/Camera.java
Normal file
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.watabou.glwrap.Matrix;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.PointF;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Camera extends Gizmo {
|
||||
|
||||
protected static ArrayList<Camera> all = new ArrayList<Camera>();
|
||||
|
||||
protected static float invW2;
|
||||
protected static float invH2;
|
||||
|
||||
public static Camera main;
|
||||
|
||||
public float zoom;
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
public int width;
|
||||
public int height;
|
||||
|
||||
int screenWidth;
|
||||
int screenHeight;
|
||||
|
||||
public float[] matrix;
|
||||
|
||||
public PointF scroll;
|
||||
public Visual target;
|
||||
|
||||
private float shakeMagX = 10f;
|
||||
private float shakeMagY = 10f;
|
||||
private float shakeTime = 0f;
|
||||
private float shakeDuration = 1f;
|
||||
|
||||
protected float shakeX;
|
||||
protected float shakeY;
|
||||
|
||||
public static Camera reset() {
|
||||
return reset( createFullscreen( 1 ) );
|
||||
}
|
||||
|
||||
public static Camera reset( Camera newCamera ) {
|
||||
|
||||
invW2 = 2f / Game.width;
|
||||
invH2 = 2f / Game.height;
|
||||
|
||||
int length = all.size();
|
||||
for (int i=0; i < length; i++) {
|
||||
all.get( i ).destroy();
|
||||
}
|
||||
all.clear();
|
||||
|
||||
return main = add( newCamera );
|
||||
}
|
||||
|
||||
public static Camera add( Camera camera ) {
|
||||
all.add( camera );
|
||||
return camera;
|
||||
}
|
||||
|
||||
public static Camera remove( Camera camera ) {
|
||||
all.remove( camera );
|
||||
return camera;
|
||||
}
|
||||
|
||||
public static void updateAll() {
|
||||
int length = all.size();
|
||||
for (int i=0; i < length; i++) {
|
||||
Camera c = all.get( i );
|
||||
if (c.exists && c.active) {
|
||||
c.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Camera createFullscreen( float zoom ) {
|
||||
int w = (int)Math.ceil( Game.width / zoom );
|
||||
int h = (int)Math.ceil( Game.height / zoom );
|
||||
return new Camera(
|
||||
(int)(Game.width - w * zoom) / 2,
|
||||
(int)(Game.height - h * zoom) / 2,
|
||||
w, h, zoom );
|
||||
}
|
||||
|
||||
public Camera( int x, int y, int width, int height, float zoom ) {
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.zoom = zoom;
|
||||
|
||||
screenWidth = (int)(width * zoom);
|
||||
screenHeight = (int)(height * zoom);
|
||||
|
||||
scroll = new PointF();
|
||||
|
||||
matrix = new float[16];
|
||||
Matrix.setIdentity( matrix );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
target = null;
|
||||
matrix = null;
|
||||
}
|
||||
|
||||
public void zoom( float value ) {
|
||||
zoom( value,
|
||||
scroll.x + width / 2,
|
||||
scroll.y + height / 2 );
|
||||
}
|
||||
|
||||
public void zoom( float value, float fx, float fy ) {
|
||||
|
||||
zoom = value;
|
||||
width = (int)(screenWidth / zoom);
|
||||
height = (int)(screenHeight / zoom);
|
||||
|
||||
focusOn( fx, fy );
|
||||
}
|
||||
|
||||
public void resize( int width, int height ) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
screenWidth = (int)(width * zoom);
|
||||
screenHeight = (int)(height * zoom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
|
||||
if (target != null) {
|
||||
focusOn( target );
|
||||
}
|
||||
|
||||
if ((shakeTime -= Game.elapsed) > 0) {
|
||||
float damping = shakeTime / shakeDuration;
|
||||
shakeX = Random.Float( -shakeMagX, +shakeMagX ) * damping;
|
||||
shakeY = Random.Float( -shakeMagY, +shakeMagY ) * damping;
|
||||
} else {
|
||||
shakeX = 0;
|
||||
shakeY = 0;
|
||||
}
|
||||
|
||||
updateMatrix();
|
||||
}
|
||||
|
||||
public PointF center() {
|
||||
return new PointF( width / 2, height / 2 );
|
||||
}
|
||||
|
||||
public boolean hitTest( float x, float y ) {
|
||||
return x >= this.x && y >= this.y && x < this.x + screenWidth && y < this.y + screenHeight;
|
||||
}
|
||||
|
||||
public void focusOn( float x, float y ) {
|
||||
scroll.set( x - width / 2, y - height / 2 );
|
||||
}
|
||||
|
||||
public void focusOn( PointF point ) {
|
||||
focusOn( point.x, point.y );
|
||||
}
|
||||
|
||||
public void focusOn( Visual visual ) {
|
||||
focusOn( visual.center() );
|
||||
}
|
||||
|
||||
public PointF screenToCamera( int x, int y ) {
|
||||
return new PointF(
|
||||
(x - this.x) / zoom + scroll.x,
|
||||
(y - this.y) / zoom + scroll.y );
|
||||
}
|
||||
|
||||
public Point cameraToScreen( float x, float y ) {
|
||||
return new Point(
|
||||
(int)((x - scroll.x) * zoom + this.x),
|
||||
(int)((y - scroll.y) * zoom + this.y));
|
||||
}
|
||||
|
||||
public float screenWidth() {
|
||||
return width * zoom;
|
||||
}
|
||||
|
||||
public float screenHeight() {
|
||||
return height * zoom;
|
||||
}
|
||||
|
||||
protected void updateMatrix() {
|
||||
|
||||
/* Matrix.setIdentity( matrix );
|
||||
Matrix.translate( matrix, -1, +1 );
|
||||
Matrix.scale( matrix, 2f / G.width, -2f / G.height );
|
||||
Matrix.translate( matrix, x, y );
|
||||
Matrix.scale( matrix, zoom, zoom );
|
||||
Matrix.translate( matrix, scroll.x, scroll.y );*/
|
||||
|
||||
matrix[0] = +zoom * invW2;
|
||||
matrix[5] = -zoom * invH2;
|
||||
|
||||
matrix[12] = -1 + x * invW2 - (scroll.x + shakeX) * matrix[0];
|
||||
matrix[13] = +1 - y * invH2 - (scroll.y + shakeY) * matrix[5];
|
||||
|
||||
}
|
||||
|
||||
public void shake( float magnitude, float duration ) {
|
||||
shakeMagX = shakeMagY = magnitude;
|
||||
shakeTime = shakeDuration = duration;
|
||||
}
|
||||
}
|
48
SPD-classes/src/main/java/com/watabou/noosa/ColorBlock.java
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import com.watabou.gltextures.TextureCache;
|
||||
|
||||
public class ColorBlock extends Image implements Resizable {
|
||||
|
||||
public ColorBlock( float width, float height, int color ) {
|
||||
super( TextureCache.createSolid( color ) );
|
||||
scale.set( width, height );
|
||||
origin.set( 0, 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void size( float width, float height ) {
|
||||
scale.set( width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public float width() {
|
||||
return scale.x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float height() {
|
||||
return scale.y;
|
||||
}
|
||||
}
|
342
SPD-classes/src/main/java/com/watabou/noosa/Game.java
Normal file
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
import com.watabou.glscripts.Script;
|
||||
import com.watabou.gltextures.TextureCache;
|
||||
import com.watabou.input.Keys;
|
||||
import com.watabou.input.Touchscreen;
|
||||
import com.watabou.noosa.audio.Music;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.watabou.utils.BitmapCache;
|
||||
import com.watabou.utils.SystemTime;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.media.AudioManager;
|
||||
import android.opengl.GLES20;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.os.Bundle;
|
||||
import android.os.Vibrator;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.View;
|
||||
|
||||
public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTouchListener {
|
||||
|
||||
public static Game instance;
|
||||
|
||||
// Actual size of the screen
|
||||
public static int width;
|
||||
public static int height;
|
||||
|
||||
// Density: mdpi=1, hdpi=1.5, xhdpi=2...
|
||||
public static float density = 1;
|
||||
|
||||
public static String version;
|
||||
public static int versionCode;
|
||||
|
||||
// Current scene
|
||||
protected Scene scene;
|
||||
// New scene we are going to switch to
|
||||
protected Scene requestedScene;
|
||||
// true if scene switch is requested
|
||||
protected boolean requestedReset = true;
|
||||
// callback to perform logic during scene change
|
||||
protected SceneChangeCallback onChange;
|
||||
// New scene class
|
||||
protected Class<? extends Scene> sceneClass;
|
||||
|
||||
// Current time in milliseconds
|
||||
protected long now;
|
||||
// Milliseconds passed since previous update
|
||||
protected long step;
|
||||
|
||||
public static float timeScale = 1f;
|
||||
public static float elapsed = 0f;
|
||||
public static float timeTotal = 0f;
|
||||
|
||||
protected GLSurfaceView view;
|
||||
protected SurfaceHolder holder;
|
||||
|
||||
// Accumulated touch events
|
||||
protected ArrayList<MotionEvent> motionEvents = new ArrayList<MotionEvent>();
|
||||
|
||||
// Accumulated key events
|
||||
protected ArrayList<KeyEvent> keysEvents = new ArrayList<KeyEvent>();
|
||||
|
||||
public Game( Class<? extends Scene> c ) {
|
||||
super();
|
||||
sceneClass = c;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate( Bundle savedInstanceState ) {
|
||||
super.onCreate( savedInstanceState );
|
||||
|
||||
BitmapCache.context = TextureCache.context = instance = this;
|
||||
|
||||
DisplayMetrics m = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics( m );
|
||||
density = m.density;
|
||||
|
||||
try {
|
||||
version = getPackageManager().getPackageInfo( getPackageName(), 0 ).versionName;
|
||||
} catch (NameNotFoundException e) {
|
||||
version = "???";
|
||||
}
|
||||
try {
|
||||
versionCode = getPackageManager().getPackageInfo( getPackageName(), 0 ).versionCode;
|
||||
} catch (NameNotFoundException e) {
|
||||
versionCode = 0;
|
||||
}
|
||||
|
||||
setVolumeControlStream( AudioManager.STREAM_MUSIC );
|
||||
|
||||
view = new GLSurfaceView( this );
|
||||
view.setEGLContextClientVersion( 2 );
|
||||
view.setEGLConfigChooser( 5, 6, 5, 0, 0, 0 );
|
||||
view.setRenderer( this );
|
||||
view.setOnTouchListener( this );
|
||||
setContentView( view );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
now = 0;
|
||||
view.onResume();
|
||||
|
||||
Music.INSTANCE.resume();
|
||||
Sample.INSTANCE.resume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (scene != null) {
|
||||
scene.pause();
|
||||
}
|
||||
|
||||
view.onPause();
|
||||
Script.reset();
|
||||
|
||||
Music.INSTANCE.pause();
|
||||
Sample.INSTANCE.pause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
destroyGame();
|
||||
|
||||
Music.INSTANCE.mute();
|
||||
Sample.INSTANCE.reset();
|
||||
}
|
||||
|
||||
@SuppressLint({ "Recycle", "ClickableViewAccessibility" })
|
||||
@Override
|
||||
public boolean onTouch( View view, MotionEvent event ) {
|
||||
synchronized (motionEvents) {
|
||||
motionEvents.add( MotionEvent.obtain( event ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown( int keyCode, KeyEvent event ) {
|
||||
|
||||
if (keyCode != Keys.BACK &&
|
||||
keyCode != Keys.MENU) {
|
||||
return false;
|
||||
}
|
||||
|
||||
synchronized (motionEvents) {
|
||||
keysEvents.add( event );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp( int keyCode, KeyEvent event ) {
|
||||
|
||||
if (keyCode != Keys.BACK &&
|
||||
keyCode != Keys.MENU) {
|
||||
return false;
|
||||
}
|
||||
|
||||
synchronized (motionEvents) {
|
||||
keysEvents.add( event );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawFrame( GL10 gl ) {
|
||||
|
||||
if (width == 0 || height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
SystemTime.tick();
|
||||
long rightNow = SystemTime.now;
|
||||
step = (now == 0 ? 0 : rightNow - now);
|
||||
now = rightNow;
|
||||
|
||||
step();
|
||||
|
||||
NoosaScript.get().resetCamera();
|
||||
GLES20.glScissor( 0, 0, width, height );
|
||||
GLES20.glClear( GLES20.GL_COLOR_BUFFER_BIT );
|
||||
draw();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceChanged( GL10 gl, int width, int height ) {
|
||||
|
||||
GLES20.glViewport(0, 0, width, height);
|
||||
|
||||
if (height != Game.height || width != Game.width) {
|
||||
|
||||
Game.width = width;
|
||||
Game.height = height;
|
||||
|
||||
resetScene();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceCreated( GL10 gl, EGLConfig config ) {
|
||||
GLES20.glEnable( GL10.GL_BLEND );
|
||||
// For premultiplied alpha:
|
||||
// GLES20.glBlendFunc( GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA );
|
||||
GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
GLES20.glEnable( GL10.GL_SCISSOR_TEST );
|
||||
|
||||
TextureCache.reload();
|
||||
RenderedText.reloadCache();
|
||||
}
|
||||
|
||||
protected void destroyGame() {
|
||||
if (scene != null) {
|
||||
scene.destroy();
|
||||
scene = null;
|
||||
}
|
||||
|
||||
//instance = null;
|
||||
}
|
||||
|
||||
public static void resetScene() {
|
||||
switchScene( instance.sceneClass );
|
||||
}
|
||||
|
||||
public static void switchScene(Class<? extends Scene> c) {
|
||||
switchScene(c, null);
|
||||
}
|
||||
|
||||
public static void switchScene(Class<? extends Scene> c, SceneChangeCallback callback) {
|
||||
instance.sceneClass = c;
|
||||
instance.requestedReset = true;
|
||||
instance.onChange = callback;
|
||||
}
|
||||
|
||||
public static Scene scene() {
|
||||
return instance.scene;
|
||||
}
|
||||
|
||||
protected void step() {
|
||||
|
||||
if (requestedReset) {
|
||||
requestedReset = false;
|
||||
|
||||
try {
|
||||
requestedScene = sceneClass.newInstance();
|
||||
switchScene();
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
protected void draw() {
|
||||
scene.draw();
|
||||
}
|
||||
|
||||
protected void switchScene() {
|
||||
|
||||
Camera.reset();
|
||||
|
||||
if (scene != null) {
|
||||
scene.destroy();
|
||||
}
|
||||
scene = requestedScene;
|
||||
if (onChange != null) onChange.beforeCreate();
|
||||
scene.create();
|
||||
if (onChange != null) onChange.afterCreate();
|
||||
onChange = null;
|
||||
|
||||
Game.elapsed = 0f;
|
||||
Game.timeScale = 1f;
|
||||
Game.timeTotal = 0f;
|
||||
}
|
||||
|
||||
protected void update() {
|
||||
Game.elapsed = Game.timeScale * step * 0.001f;
|
||||
Game.timeTotal += Game.elapsed;
|
||||
|
||||
synchronized (motionEvents) {
|
||||
Touchscreen.processTouchEvents( motionEvents );
|
||||
motionEvents.clear();
|
||||
}
|
||||
synchronized (keysEvents) {
|
||||
Keys.processTouchEvents( keysEvents );
|
||||
keysEvents.clear();
|
||||
}
|
||||
|
||||
scene.update();
|
||||
Camera.updateAll();
|
||||
}
|
||||
|
||||
public static void vibrate( int milliseconds ) {
|
||||
((Vibrator)instance.getSystemService( VIBRATOR_SERVICE )).vibrate( milliseconds );
|
||||
}
|
||||
|
||||
public interface SceneChangeCallback{
|
||||
void beforeCreate();
|
||||
void afterCreate();
|
||||
}
|
||||
}
|
101
SPD-classes/src/main/java/com/watabou/noosa/Gizmo.java
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
public class Gizmo {
|
||||
|
||||
public boolean exists;
|
||||
public boolean alive;
|
||||
public boolean active;
|
||||
public boolean visible;
|
||||
|
||||
public Group parent;
|
||||
|
||||
public Camera camera;
|
||||
|
||||
public Gizmo() {
|
||||
exists = true;
|
||||
alive = true;
|
||||
active = true;
|
||||
visible = true;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
parent = null;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
}
|
||||
|
||||
public void kill() {
|
||||
alive = false;
|
||||
exists = false;
|
||||
}
|
||||
|
||||
// Not exactly opposite to "kill" method
|
||||
public void revive() {
|
||||
alive = true;
|
||||
exists = true;
|
||||
}
|
||||
|
||||
public Camera camera() {
|
||||
if (camera != null) {
|
||||
return camera;
|
||||
} else if (parent != null) {
|
||||
return parent.camera();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
if (parent == null) {
|
||||
return visible;
|
||||
} else {
|
||||
return visible && parent.isVisible();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
if (parent == null) {
|
||||
return active;
|
||||
} else {
|
||||
return active && parent.isActive();
|
||||
}
|
||||
}
|
||||
|
||||
public void killAndErase() {
|
||||
kill();
|
||||
if (parent != null) {
|
||||
parent.erase( this );
|
||||
}
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if (parent != null) {
|
||||
parent.remove( this );
|
||||
}
|
||||
}
|
||||
}
|
314
SPD-classes/src/main/java/com/watabou/noosa/Group.java
Normal file
|
@ -0,0 +1,314 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import com.watabou.noosa.particles.Emitter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Group extends Gizmo {
|
||||
|
||||
protected ArrayList<Gizmo> members;
|
||||
|
||||
// Accessing it is a little faster,
|
||||
// than calling members.getSize()
|
||||
public int length;
|
||||
|
||||
public static boolean freezeEmitters = false;
|
||||
|
||||
public Group() {
|
||||
members = new ArrayList<Gizmo>();
|
||||
length = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
for (int i=0; i < length; i++) {
|
||||
Gizmo g = members.get( i );
|
||||
if (g != null) {
|
||||
g.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
members.clear();
|
||||
members = null;
|
||||
length = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
for (int i=0; i < length; i++) {
|
||||
Gizmo g = members.get( i );
|
||||
if (g != null && g.exists && g.active
|
||||
//functionality for the freezing of emitters(particle effects), effects are given a second
|
||||
//from load to get started so they aren't frozen before anything is generated.
|
||||
&& !(freezeEmitters && Game.timeTotal > 1f && g instanceof Emitter)) {
|
||||
g.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
for (int i=0; i < length; i++) {
|
||||
Gizmo g = members.get( i );
|
||||
if (g != null && g.exists && g.visible) {
|
||||
g.draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void kill() {
|
||||
// A killed group keeps all its members,
|
||||
// but they get killed too
|
||||
for (int i=0; i < length; i++) {
|
||||
Gizmo g = members.get( i );
|
||||
if (g != null && g.exists) {
|
||||
g.kill();
|
||||
}
|
||||
}
|
||||
|
||||
super.kill();
|
||||
}
|
||||
|
||||
public int indexOf( Gizmo g ) {
|
||||
return members.indexOf( g );
|
||||
}
|
||||
|
||||
public Gizmo add( Gizmo g ) {
|
||||
|
||||
if (g.parent == this) {
|
||||
return g;
|
||||
}
|
||||
|
||||
if (g.parent != null) {
|
||||
g.parent.remove( g );
|
||||
}
|
||||
|
||||
// Trying to find an empty space for a new member
|
||||
for (int i=0; i < length; i++) {
|
||||
if (members.get( i ) == null) {
|
||||
members.set( i, g );
|
||||
g.parent = this;
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
members.add( g );
|
||||
g.parent = this;
|
||||
length++;
|
||||
return g;
|
||||
}
|
||||
|
||||
public Gizmo addToFront( Gizmo g){
|
||||
|
||||
if (g.parent == this) {
|
||||
return g;
|
||||
}
|
||||
|
||||
if (g.parent != null) {
|
||||
g.parent.remove( g );
|
||||
}
|
||||
|
||||
// Trying to find an empty space for a new member
|
||||
// starts from the front and never goes over a none-null element
|
||||
for (int i=length-1; i >= 0; i--) {
|
||||
if (members.get( i ) == null) {
|
||||
if (i == 0 || members.get(i - 1) != null) {
|
||||
members.set(i, g);
|
||||
g.parent = this;
|
||||
return g;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
members.add( g );
|
||||
g.parent = this;
|
||||
length++;
|
||||
return g;
|
||||
}
|
||||
|
||||
public Gizmo addToBack( Gizmo g ) {
|
||||
|
||||
if (g.parent == this) {
|
||||
sendToBack( g );
|
||||
return g;
|
||||
}
|
||||
|
||||
if (g.parent != null) {
|
||||
g.parent.remove( g );
|
||||
}
|
||||
|
||||
if (members.get( 0 ) == null) {
|
||||
members.set( 0, g );
|
||||
g.parent = this;
|
||||
return g;
|
||||
}
|
||||
|
||||
members.add( 0, g );
|
||||
g.parent = this;
|
||||
length++;
|
||||
return g;
|
||||
}
|
||||
|
||||
public Gizmo recycle( Class<? extends Gizmo> c ) {
|
||||
|
||||
Gizmo g = getFirstAvailable( c );
|
||||
if (g != null) {
|
||||
|
||||
return g;
|
||||
|
||||
} else if (c == null) {
|
||||
|
||||
return null;
|
||||
|
||||
} else {
|
||||
|
||||
try {
|
||||
return add( c.newInstance() );
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Fast removal - replacing with null
|
||||
public Gizmo erase( Gizmo g ) {
|
||||
int index = members.indexOf( g );
|
||||
|
||||
if (index != -1) {
|
||||
members.set( index, null );
|
||||
g.parent = null;
|
||||
return g;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Real removal
|
||||
public Gizmo remove( Gizmo g ) {
|
||||
if (members.remove( g )) {
|
||||
length--;
|
||||
g.parent = null;
|
||||
return g;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Gizmo replace( Gizmo oldOne, Gizmo newOne ) {
|
||||
int index = members.indexOf( oldOne );
|
||||
if (index != -1) {
|
||||
members.set( index, newOne );
|
||||
newOne.parent = this;
|
||||
oldOne.parent = null;
|
||||
return newOne;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Gizmo getFirstAvailable( Class<? extends Gizmo> c ) {
|
||||
|
||||
for (int i=0; i < length; i++) {
|
||||
Gizmo g = members.get( i );
|
||||
if (g != null && !g.exists && ((c == null) || g.getClass() == c)) {
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int countLiving() {
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (int i=0; i < length; i++) {
|
||||
Gizmo g = members.get( i );
|
||||
if (g != null && g.exists && g.alive) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public int countDead() {
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (int i=0; i < length; i++) {
|
||||
Gizmo g = members.get( i );
|
||||
if (g != null && !g.alive) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public Gizmo random() {
|
||||
if (length > 0) {
|
||||
return members.get( (int)(Math.random() * length) );
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
for (int i=0; i < length; i++) {
|
||||
Gizmo g = members.get( i );
|
||||
if (g != null) {
|
||||
g.parent = null;
|
||||
}
|
||||
}
|
||||
members.clear();
|
||||
length = 0;
|
||||
}
|
||||
|
||||
public Gizmo bringToFront( Gizmo g ) {
|
||||
if (members.contains( g )) {
|
||||
members.remove( g );
|
||||
members.add( g );
|
||||
return g;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Gizmo sendToBack( Gizmo g ) {
|
||||
if (members.contains( g )) {
|
||||
members.remove( g );
|
||||
members.add( 0, g );
|
||||
return g;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
171
SPD-classes/src/main/java/com/watabou/noosa/Image.java
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.watabou.gltextures.TextureCache;
|
||||
import com.watabou.gltextures.SmartTexture;
|
||||
import com.watabou.glwrap.Quad;
|
||||
|
||||
public class Image extends Visual {
|
||||
|
||||
public SmartTexture texture;
|
||||
protected RectF frame;
|
||||
|
||||
public boolean flipHorizontal;
|
||||
public boolean flipVertical;
|
||||
|
||||
protected float[] vertices;
|
||||
protected FloatBuffer verticesBuffer;
|
||||
|
||||
protected boolean dirty;
|
||||
|
||||
public Image() {
|
||||
super( 0, 0, 0, 0 );
|
||||
|
||||
vertices = new float[16];
|
||||
verticesBuffer = Quad.create();
|
||||
}
|
||||
|
||||
public Image( Image src ) {
|
||||
this();
|
||||
copy( src );
|
||||
}
|
||||
|
||||
public Image( Object tx ) {
|
||||
this();
|
||||
texture( tx );
|
||||
}
|
||||
|
||||
public Image( Object tx, int left, int top, int width, int height ) {
|
||||
this( tx );
|
||||
frame( texture.uvRect( left, top, left + width, top + height ) );
|
||||
}
|
||||
|
||||
public void texture( Object tx ) {
|
||||
texture = tx instanceof SmartTexture ? (SmartTexture)tx : TextureCache.get( tx );
|
||||
frame( new RectF( 0, 0, 1, 1 ) );
|
||||
}
|
||||
|
||||
public void frame( RectF frame ) {
|
||||
this.frame = frame;
|
||||
|
||||
width = frame.width() * texture.width;
|
||||
height = frame.height() * texture.height;
|
||||
|
||||
updateFrame();
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
public void frame( int left, int top, int width, int height ) {
|
||||
frame( texture.uvRect( left, top, left + width, top + height ) );
|
||||
}
|
||||
|
||||
public RectF frame() {
|
||||
return new RectF( frame );
|
||||
}
|
||||
|
||||
public void copy( Image other ) {
|
||||
texture = other.texture;
|
||||
frame = new RectF( other.frame );
|
||||
|
||||
width = other.width;
|
||||
height = other.height;
|
||||
|
||||
updateFrame();
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
protected void updateFrame() {
|
||||
|
||||
if (flipHorizontal) {
|
||||
vertices[2] = frame.right;
|
||||
vertices[6] = frame.left;
|
||||
vertices[10] = frame.left;
|
||||
vertices[14] = frame.right;
|
||||
} else {
|
||||
vertices[2] = frame.left;
|
||||
vertices[6] = frame.right;
|
||||
vertices[10] = frame.right;
|
||||
vertices[14] = frame.left;
|
||||
}
|
||||
|
||||
if (flipVertical) {
|
||||
vertices[3] = frame.bottom;
|
||||
vertices[7] = frame.bottom;
|
||||
vertices[11] = frame.top;
|
||||
vertices[15] = frame.top;
|
||||
} else {
|
||||
vertices[3] = frame.top;
|
||||
vertices[7] = frame.top;
|
||||
vertices[11] = frame.bottom;
|
||||
vertices[15] = frame.bottom;
|
||||
}
|
||||
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
protected void updateVertices() {
|
||||
|
||||
vertices[0] = 0;
|
||||
vertices[1] = 0;
|
||||
|
||||
vertices[4] = width;
|
||||
vertices[5] = 0;
|
||||
|
||||
vertices[8] = width;
|
||||
vertices[9] = height;
|
||||
|
||||
vertices[12] = 0;
|
||||
vertices[13] = height;
|
||||
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
|
||||
super.draw();
|
||||
|
||||
NoosaScript script = NoosaScript.get();
|
||||
|
||||
texture.bind();
|
||||
|
||||
script.camera( camera() );
|
||||
|
||||
script.uModel.valueM4( matrix );
|
||||
script.lighting(
|
||||
rm, gm, bm, am,
|
||||
ra, ga, ba, aa );
|
||||
|
||||
if (dirty) {
|
||||
verticesBuffer.position( 0 );
|
||||
verticesBuffer.put( vertices );
|
||||
dirty = false;
|
||||
}
|
||||
script.drawQuad( verticesBuffer );
|
||||
|
||||
}
|
||||
}
|
143
SPD-classes/src/main/java/com/watabou/noosa/MovieClip.java
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import android.graphics.RectF;
|
||||
|
||||
public class MovieClip extends Image {
|
||||
|
||||
protected Animation curAnim;
|
||||
protected int curFrame;
|
||||
protected float frameTimer;
|
||||
protected boolean finished;
|
||||
|
||||
public boolean paused = false;
|
||||
|
||||
public Listener listener;
|
||||
|
||||
public MovieClip() {
|
||||
super();
|
||||
}
|
||||
|
||||
public MovieClip( Object tx ) {
|
||||
super( tx );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
if (!paused) {
|
||||
updateAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean looping(){
|
||||
return curAnim != null && curAnim.looped;
|
||||
}
|
||||
|
||||
protected void updateAnimation() {
|
||||
if (curAnim != null && curAnim.delay > 0 && (curAnim.looped || !finished)) {
|
||||
|
||||
int lastFrame = curFrame;
|
||||
|
||||
frameTimer += Game.elapsed;
|
||||
while (frameTimer > curAnim.delay) {
|
||||
frameTimer -= curAnim.delay;
|
||||
if (curFrame == curAnim.frames.length - 1) {
|
||||
if (curAnim.looped) {
|
||||
curFrame = 0;
|
||||
}
|
||||
finished = true;
|
||||
if (listener != null) {
|
||||
listener.onComplete( curAnim );
|
||||
// This check can probably be removed
|
||||
if (curAnim == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
curFrame++;
|
||||
}
|
||||
}
|
||||
|
||||
if (curFrame != lastFrame) {
|
||||
frame( curAnim.frames[curFrame] );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void play( Animation anim ) {
|
||||
play( anim, false );
|
||||
}
|
||||
|
||||
public void play( Animation anim, boolean force ) {
|
||||
|
||||
if (!force && (curAnim != null) && (curAnim == anim) && (curAnim.looped || !finished)) {
|
||||
return;
|
||||
}
|
||||
|
||||
curAnim = anim;
|
||||
curFrame = 0;
|
||||
finished = false;
|
||||
|
||||
frameTimer = 0;
|
||||
|
||||
if (anim != null) {
|
||||
frame( anim.frames[curFrame] );
|
||||
}
|
||||
}
|
||||
|
||||
public static class Animation {
|
||||
|
||||
public float delay;
|
||||
public RectF[] frames;
|
||||
public boolean looped;
|
||||
|
||||
public Animation( int fps, boolean looped ) {
|
||||
this.delay = 1f / fps;
|
||||
this.looped = looped;
|
||||
}
|
||||
|
||||
public Animation frames( RectF... frames ) {
|
||||
this.frames = frames;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Animation frames( TextureFilm film, Object... frames ) {
|
||||
this.frames = new RectF[frames.length];
|
||||
for (int i=0; i < frames.length; i++) {
|
||||
this.frames[i] = film.get( frames[i] );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Animation clone() {
|
||||
return new Animation( Math.round( 1 / delay ), looped ).frames( frames );
|
||||
}
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void onComplete( Animation anim );
|
||||
}
|
||||
}
|
212
SPD-classes/src/main/java/com/watabou/noosa/NinePatch.java
Normal file
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import com.watabou.gltextures.SmartTexture;
|
||||
import com.watabou.gltextures.TextureCache;
|
||||
import com.watabou.glwrap.Quad;
|
||||
|
||||
import android.graphics.RectF;
|
||||
|
||||
public class NinePatch extends Visual {
|
||||
|
||||
public SmartTexture texture;
|
||||
|
||||
protected float[] vertices;
|
||||
protected FloatBuffer verticesBuffer;
|
||||
|
||||
protected RectF outterF;
|
||||
protected RectF innerF;
|
||||
|
||||
protected int marginLeft;
|
||||
protected int marginRight;
|
||||
protected int marginTop;
|
||||
protected int marginBottom;
|
||||
|
||||
protected float nWidth;
|
||||
protected float nHeight;
|
||||
|
||||
protected boolean flipHorizontal;
|
||||
protected boolean flipVertical;
|
||||
|
||||
public NinePatch( Object tx, int margin ) {
|
||||
this( tx, margin, margin, margin, margin );
|
||||
}
|
||||
|
||||
public NinePatch( Object tx, int left, int top, int right, int bottom ) {
|
||||
this( tx, 0, 0, 0, 0, left, top, right, bottom );
|
||||
}
|
||||
|
||||
public NinePatch( Object tx, int x, int y, int w, int h, int margin ) {
|
||||
this( tx, x, y, w, h, margin, margin, margin, margin );
|
||||
}
|
||||
|
||||
public NinePatch( Object tx, int x, int y, int w, int h, int left, int top, int right, int bottom ) {
|
||||
super( 0, 0, 0, 0 );
|
||||
|
||||
texture = TextureCache.get( tx );
|
||||
w = w == 0 ? texture.width : w;
|
||||
h = h == 0 ? texture.height : h;
|
||||
|
||||
nWidth = width = w;
|
||||
nHeight = height = h;
|
||||
|
||||
vertices = new float[16];
|
||||
verticesBuffer = Quad.createSet( 9 );
|
||||
|
||||
marginLeft = left;
|
||||
marginRight = right;
|
||||
marginTop = top;
|
||||
marginBottom= bottom;
|
||||
|
||||
outterF = texture.uvRect( x, y, x + w, y + h );
|
||||
innerF = texture.uvRect( x + left, y + top, x + w - right, y + h - bottom );
|
||||
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
protected void updateVertices() {
|
||||
|
||||
verticesBuffer.position( 0 );
|
||||
|
||||
float right = width - marginRight;
|
||||
float bottom = height - marginBottom;
|
||||
|
||||
float outleft = flipHorizontal ? outterF.right : outterF.left;
|
||||
float outright = flipHorizontal ? outterF.left : outterF.right;
|
||||
float outtop = flipVertical ? outterF.bottom : outterF.top;
|
||||
float outbottom = flipVertical ? outterF.top : outterF.bottom;
|
||||
|
||||
float inleft = flipHorizontal ? innerF.right : innerF.left;
|
||||
float inright = flipHorizontal ? innerF.left : innerF.right;
|
||||
float intop = flipVertical ? innerF.bottom : innerF.top;
|
||||
float inbottom = flipVertical ? innerF.top : innerF.bottom;
|
||||
|
||||
Quad.fill( vertices,
|
||||
0, marginLeft, 0, marginTop, outleft, inleft, outtop, intop );
|
||||
verticesBuffer.put( vertices );
|
||||
Quad.fill( vertices,
|
||||
marginLeft, right, 0, marginTop, inleft, inright, outtop, intop );
|
||||
verticesBuffer.put( vertices );
|
||||
Quad.fill( vertices,
|
||||
right, width, 0, marginTop, inright, outright, outtop, intop );
|
||||
verticesBuffer.put( vertices );
|
||||
|
||||
Quad.fill( vertices,
|
||||
0, marginLeft, marginTop, bottom, outleft, inleft, intop, inbottom );
|
||||
verticesBuffer.put( vertices );
|
||||
Quad.fill( vertices,
|
||||
marginLeft, right, marginTop, bottom, inleft, inright, intop, inbottom );
|
||||
verticesBuffer.put( vertices );
|
||||
Quad.fill( vertices,
|
||||
right, width, marginTop, bottom, inright, outright, intop, inbottom );
|
||||
verticesBuffer.put( vertices );
|
||||
|
||||
Quad.fill( vertices,
|
||||
0, marginLeft, bottom, height, outleft, inleft, inbottom, outbottom );
|
||||
verticesBuffer.put( vertices );
|
||||
Quad.fill( vertices,
|
||||
marginLeft, right, bottom, height, inleft, inright, inbottom, outbottom );
|
||||
verticesBuffer.put( vertices );
|
||||
Quad.fill( vertices,
|
||||
right, width, bottom, height, inright, outright, inbottom, outbottom );
|
||||
verticesBuffer.put( vertices );
|
||||
}
|
||||
|
||||
public int marginLeft() {
|
||||
return marginLeft;
|
||||
}
|
||||
|
||||
public int marginRight() {
|
||||
return marginRight;
|
||||
}
|
||||
|
||||
public int marginTop() {
|
||||
return marginTop;
|
||||
}
|
||||
|
||||
public int marginBottom() {
|
||||
return marginBottom;
|
||||
}
|
||||
|
||||
public int marginHor() {
|
||||
return marginLeft + marginRight;
|
||||
}
|
||||
|
||||
public int marginVer() {
|
||||
return marginTop + marginBottom;
|
||||
}
|
||||
|
||||
public float innerWidth() {
|
||||
return width - marginLeft - marginRight;
|
||||
}
|
||||
|
||||
public float innerHeight() {
|
||||
return height - marginTop - marginBottom;
|
||||
}
|
||||
|
||||
public float innerRight() {
|
||||
return width - marginRight;
|
||||
}
|
||||
|
||||
public float innerBottom() {
|
||||
return height - marginBottom;
|
||||
}
|
||||
|
||||
public void flipHorizontal(boolean value) {
|
||||
flipHorizontal = value;
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
public void flipVertical(boolean value) {
|
||||
flipVertical = value;
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
public void size( float width, float height ) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
|
||||
super.draw();
|
||||
|
||||
NoosaScript script = NoosaScript.get();
|
||||
|
||||
texture.bind();
|
||||
|
||||
script.camera( camera() );
|
||||
|
||||
script.uModel.valueM4( matrix );
|
||||
script.lighting(
|
||||
rm, gm, bm, am,
|
||||
ra, ga, ba, aa );
|
||||
|
||||
script.drawQuadSet( verticesBuffer, 9 );
|
||||
|
||||
}
|
||||
}
|
171
SPD-classes/src/main/java/com/watabou/noosa/NoosaScript.java
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
import com.watabou.glscripts.Script;
|
||||
import com.watabou.glwrap.Attribute;
|
||||
import com.watabou.glwrap.Quad;
|
||||
import com.watabou.glwrap.Uniform;
|
||||
|
||||
public class NoosaScript extends Script {
|
||||
|
||||
public Uniform uCamera;
|
||||
public Uniform uModel;
|
||||
public Uniform uTex;
|
||||
public Uniform uColorM;
|
||||
public Uniform uColorA;
|
||||
public Attribute aXY;
|
||||
public Attribute aUV;
|
||||
|
||||
private Camera lastCamera;
|
||||
|
||||
public NoosaScript() {
|
||||
|
||||
super();
|
||||
compile( shader() );
|
||||
|
||||
uCamera = uniform( "uCamera" );
|
||||
uModel = uniform( "uModel" );
|
||||
uTex = uniform( "uTex" );
|
||||
uColorM = uniform( "uColorM" );
|
||||
uColorA = uniform( "uColorA" );
|
||||
aXY = attribute( "aXYZW" );
|
||||
aUV = attribute( "aUV" );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void use() {
|
||||
|
||||
super.use();
|
||||
|
||||
aXY.enable();
|
||||
aUV.enable();
|
||||
|
||||
}
|
||||
|
||||
public void drawElements( FloatBuffer vertices, ShortBuffer indices, int size ) {
|
||||
|
||||
vertices.position( 0 );
|
||||
aXY.vertexPointer( 2, 4, vertices );
|
||||
|
||||
vertices.position( 2 );
|
||||
aUV.vertexPointer( 2, 4, vertices );
|
||||
|
||||
GLES20.glDrawElements( GLES20.GL_TRIANGLES, size, GLES20.GL_UNSIGNED_SHORT, indices );
|
||||
|
||||
}
|
||||
|
||||
public void drawQuad( FloatBuffer vertices ) {
|
||||
|
||||
vertices.position( 0 );
|
||||
aXY.vertexPointer( 2, 4, vertices );
|
||||
|
||||
vertices.position( 2 );
|
||||
aUV.vertexPointer( 2, 4, vertices );
|
||||
|
||||
GLES20.glDrawElements( GLES20.GL_TRIANGLES, Quad.SIZE, GLES20.GL_UNSIGNED_SHORT, Quad.getIndices( 1 ) );
|
||||
|
||||
}
|
||||
|
||||
public void drawQuadSet( FloatBuffer vertices, int size ) {
|
||||
|
||||
if (size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
vertices.position( 0 );
|
||||
aXY.vertexPointer( 2, 4, vertices );
|
||||
|
||||
vertices.position( 2 );
|
||||
aUV.vertexPointer( 2, 4, vertices );
|
||||
|
||||
GLES20.glDrawElements(
|
||||
GLES20.GL_TRIANGLES,
|
||||
Quad.SIZE * size,
|
||||
GLES20.GL_UNSIGNED_SHORT,
|
||||
Quad.getIndices( size ) );
|
||||
|
||||
}
|
||||
|
||||
public void lighting( float rm, float gm, float bm, float am, float ra, float ga, float ba, float aa ) {
|
||||
uColorM.value4f( rm, gm, bm, am );
|
||||
uColorA.value4f( ra, ga, ba, aa );
|
||||
}
|
||||
|
||||
public void resetCamera() {
|
||||
lastCamera = null;
|
||||
}
|
||||
|
||||
public void camera( Camera camera ) {
|
||||
if (camera == null) {
|
||||
camera = Camera.main;
|
||||
}
|
||||
if (camera != lastCamera && camera.matrix != null) {
|
||||
lastCamera = camera;
|
||||
uCamera.valueM4( camera.matrix );
|
||||
|
||||
GLES20.glScissor(
|
||||
camera.x,
|
||||
Game.height - camera.screenHeight - camera.y,
|
||||
camera.screenWidth,
|
||||
camera.screenHeight );
|
||||
}
|
||||
}
|
||||
|
||||
public static NoosaScript get() {
|
||||
return Script.use( NoosaScript.class );
|
||||
}
|
||||
|
||||
|
||||
protected String shader() {
|
||||
return SHADER;
|
||||
}
|
||||
|
||||
private static final String SHADER =
|
||||
|
||||
"uniform mat4 uCamera;" +
|
||||
"uniform mat4 uModel;" +
|
||||
"attribute vec4 aXYZW;" +
|
||||
"attribute vec2 aUV;" +
|
||||
"varying vec2 vUV;" +
|
||||
"void main() {" +
|
||||
" gl_Position = uCamera * uModel * aXYZW;" +
|
||||
" vUV = aUV;" +
|
||||
"}" +
|
||||
|
||||
"//\n" +
|
||||
|
||||
"precision mediump float;" +
|
||||
"varying vec2 vUV;" +
|
||||
"uniform sampler2D uTex;" +
|
||||
"uniform vec4 uColorM;" +
|
||||
"uniform vec4 uColorA;" +
|
||||
"void main() {" +
|
||||
" gl_FragColor = texture2D( uTex, vUV ) * uColorM + uColorA;" +
|
||||
"}";
|
||||
}
|
48
SPD-classes/src/main/java/com/watabou/noosa/PseudoPixel.java
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import com.watabou.gltextures.TextureCache;
|
||||
|
||||
public class PseudoPixel extends Image {
|
||||
|
||||
public PseudoPixel() {
|
||||
super( TextureCache.createSolid( 0xFFFFFFFF ) );
|
||||
}
|
||||
|
||||
public PseudoPixel( float x, float y, int color ) {
|
||||
|
||||
this();
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
color( color );
|
||||
}
|
||||
|
||||
public void size( float w, float h ) {
|
||||
scale.set( w, h );
|
||||
}
|
||||
|
||||
public void size( float value ) {
|
||||
scale.set( value );
|
||||
}
|
||||
}
|
229
SPD-classes/src/main/java/com/watabou/noosa/RenderedText.java
Normal file
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Typeface;
|
||||
import com.watabou.gltextures.SmartTexture;
|
||||
import com.watabou.glwrap.Matrix;
|
||||
import com.watabou.glwrap.Texture;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class RenderedText extends Image {
|
||||
|
||||
private static Canvas canvas = new Canvas();
|
||||
private static Paint painter = new Paint();
|
||||
|
||||
private static Typeface font;
|
||||
|
||||
//this is basically a LRU cache. capacity is determined by character count, not entry count.
|
||||
//will attempt to clear oldest, not in use entires until there are 500 characters stored.
|
||||
//FIXME: Caching based on words is very inefficient for every language but chinese.
|
||||
private static LinkedHashMap<String, CachedText> textCache =
|
||||
new LinkedHashMap<String, CachedText>(700, 0.75f, true){
|
||||
private int cachedChars = 0;
|
||||
private final int MAX_CACHED = 500;
|
||||
|
||||
@Override
|
||||
public CachedText put(String key, CachedText value) {
|
||||
cachedChars += value.length;
|
||||
CachedText added = super.put(key, value);
|
||||
runGC();
|
||||
return added;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CachedText remove(Object key) {
|
||||
CachedText removed = super.remove(key);
|
||||
if (removed != null) {
|
||||
cachedChars-= removed.length;
|
||||
removed.texture.delete();
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
cachedChars = 0;
|
||||
}
|
||||
|
||||
private void runGC(){
|
||||
Iterator<Map.Entry<String, CachedText>> it = this.entrySet().iterator();
|
||||
while (cachedChars > MAX_CACHED && it.hasNext()){
|
||||
CachedText cached = it.next().getValue();
|
||||
if (cached.activeTexts.isEmpty()) it.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private int size;
|
||||
private String text;
|
||||
private CachedText cache;
|
||||
|
||||
public RenderedText( ){
|
||||
text = null;
|
||||
}
|
||||
|
||||
public RenderedText( int size ){
|
||||
text = null;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public RenderedText(String text, int size){
|
||||
this.text = text;
|
||||
this.size = size;
|
||||
|
||||
render();
|
||||
}
|
||||
|
||||
public void text( String text ){
|
||||
this.text = text;
|
||||
|
||||
render();
|
||||
}
|
||||
|
||||
public String text(){
|
||||
return text;
|
||||
}
|
||||
|
||||
public void size( int size ){
|
||||
this.size = size;
|
||||
render();
|
||||
}
|
||||
|
||||
public float baseLine(){
|
||||
return size * scale.y;
|
||||
}
|
||||
|
||||
private void render(){
|
||||
if ( text == null || text.equals("") ) {
|
||||
text = "";
|
||||
width=height=0;
|
||||
visible = false;
|
||||
return;
|
||||
} else {
|
||||
visible = true;
|
||||
}
|
||||
|
||||
if (cache != null)
|
||||
cache.activeTexts.remove(this);
|
||||
|
||||
String key = "text:" + size + " " + text;
|
||||
if (textCache.containsKey(key)){
|
||||
cache = textCache.get(key);
|
||||
texture = cache.texture;
|
||||
frame(cache.rect);
|
||||
cache.activeTexts.add(this);
|
||||
} else {
|
||||
|
||||
painter.setTextSize(size);
|
||||
painter.setAntiAlias(true);
|
||||
|
||||
if (font != null) {
|
||||
painter.setTypeface(font);
|
||||
} else {
|
||||
painter.setTypeface(Typeface.DEFAULT);
|
||||
}
|
||||
|
||||
//paint outer strokes
|
||||
painter.setARGB(0xff, 0, 0, 0);
|
||||
painter.setStyle(Paint.Style.STROKE);
|
||||
painter.setStrokeWidth(size / 5f);
|
||||
|
||||
int right = (int)(painter.measureText(text)+ (size/5f));
|
||||
int bottom = (int)(-painter.ascent() + painter.descent()+ (size/5f));
|
||||
|
||||
//bitmap has to be in a power of 2 for some devices (as we're using openGL methods to render to texture)
|
||||
Bitmap bitmap = Bitmap.createBitmap(Integer.highestOneBit(right)*2, Integer.highestOneBit(bottom)*2, Bitmap.Config.ARGB_4444);
|
||||
bitmap.eraseColor(0x00000000);
|
||||
|
||||
canvas.setBitmap(bitmap);
|
||||
canvas.drawText(text, (size/10f), size, painter);
|
||||
|
||||
//paint inner text
|
||||
painter.setARGB(0xff, 0xff, 0xff, 0xff);
|
||||
painter.setStyle(Paint.Style.FILL);
|
||||
|
||||
canvas.drawText(text, (size/10f), size, painter);
|
||||
|
||||
texture = new SmartTexture(bitmap, Texture.NEAREST, Texture.CLAMP, true);
|
||||
|
||||
RectF rect = texture.uvRect(0, 0, right, bottom);
|
||||
frame(rect);
|
||||
|
||||
cache = new CachedText();
|
||||
cache.rect = rect;
|
||||
cache.texture = texture;
|
||||
cache.length = text.length();
|
||||
cache.activeTexts = new HashSet<>();
|
||||
cache.activeTexts.add(this);
|
||||
textCache.put("text:" + size + " " + text, cache);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateMatrix() {
|
||||
super.updateMatrix();
|
||||
//the y value is set at the top of the character, not at the top of accents.
|
||||
Matrix.translate( matrix, 0, -Math.round((baseLine()*0.15f)/scale.y) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
if (cache != null)
|
||||
cache.activeTexts.remove(this);
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
public static void clearCache(){
|
||||
for (CachedText cached : textCache.values()){
|
||||
cached.texture.delete();
|
||||
}
|
||||
textCache.clear();
|
||||
}
|
||||
|
||||
public static void reloadCache(){
|
||||
for (CachedText txt : textCache.values()){
|
||||
txt.texture.reload();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setFont(String asset){
|
||||
font = Typeface.createFromAsset(Game.instance.getAssets(), asset);
|
||||
clearCache();
|
||||
}
|
||||
|
||||
private class CachedText{
|
||||
public SmartTexture texture;
|
||||
public RectF rect;
|
||||
public int length;
|
||||
public HashSet<RenderedText> activeTexts;
|
||||
}
|
||||
}
|
30
SPD-classes/src/main/java/com/watabou/noosa/Resizable.java
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
public interface Resizable {
|
||||
|
||||
public void size( float width, float height );
|
||||
public float width();
|
||||
public float height();
|
||||
|
||||
}
|
81
SPD-classes/src/main/java/com/watabou/noosa/Scene.java
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import com.watabou.input.Keys;
|
||||
import com.watabou.utils.Signal;
|
||||
|
||||
public class Scene extends Group {
|
||||
|
||||
private Signal.Listener<Keys.Key> keyListener;
|
||||
|
||||
public void create() {
|
||||
Keys.event.add( keyListener = new Signal.Listener<Keys.Key>() {
|
||||
@Override
|
||||
public void onSignal( Keys.Key key ) {
|
||||
if (Game.instance != null && key.pressed) {
|
||||
switch (key.code) {
|
||||
case Keys.BACK:
|
||||
onBackPressed();
|
||||
break;
|
||||
case Keys.MENU:
|
||||
onMenuPressed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
Keys.event.remove( keyListener );
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Camera camera() {
|
||||
return Camera.main;
|
||||
}
|
||||
|
||||
protected void onBackPressed() {
|
||||
Game.instance.finish();
|
||||
}
|
||||
|
||||
protected void onMenuPressed() {
|
||||
|
||||
}
|
||||
|
||||
}
|
130
SPD-classes/src/main/java/com/watabou/noosa/SkinnedBlock.java
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import com.watabou.glwrap.Texture;
|
||||
|
||||
import android.graphics.RectF;
|
||||
|
||||
public class SkinnedBlock extends Image {
|
||||
|
||||
protected float scaleX;
|
||||
protected float scaleY;
|
||||
|
||||
protected float offsetX;
|
||||
protected float offsetY;
|
||||
|
||||
public boolean autoAdjust = false;
|
||||
|
||||
public SkinnedBlock( float width, float height, Object tx ) {
|
||||
super( tx );
|
||||
|
||||
texture.wrap( Texture.REPEAT, Texture.REPEAT );
|
||||
|
||||
size( width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frame( RectF frame ) {
|
||||
scaleX = 1;
|
||||
scaleY = 1;
|
||||
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
|
||||
super.frame( new RectF( 0, 0, 1, 1 ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateFrame() {
|
||||
|
||||
if (autoAdjust) {
|
||||
while (offsetX > texture.width) {
|
||||
offsetX -= texture.width;
|
||||
}
|
||||
while (offsetX < -texture.width) {
|
||||
offsetX += texture.width;
|
||||
}
|
||||
while (offsetY > texture.height) {
|
||||
offsetY -= texture.height;
|
||||
}
|
||||
while (offsetY < -texture.height) {
|
||||
offsetY += texture.height;
|
||||
}
|
||||
}
|
||||
|
||||
float tw = 1f / texture.width;
|
||||
float th = 1f / texture.height;
|
||||
|
||||
float u0 = offsetX * tw;
|
||||
float v0 = offsetY * th;
|
||||
float u1 = u0 + width * tw / scaleX;
|
||||
float v1 = v0 + height * th / scaleY;
|
||||
|
||||
vertices[2] = u0;
|
||||
vertices[3] = v0;
|
||||
|
||||
vertices[6] = u1;
|
||||
vertices[7] = v0;
|
||||
|
||||
vertices[10] = u1;
|
||||
vertices[11] = v1;
|
||||
|
||||
vertices[14] = u0;
|
||||
vertices[15] = v1;
|
||||
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public void offsetTo( float x, float y ) {
|
||||
offsetX = x;
|
||||
offsetY = y;
|
||||
updateFrame();
|
||||
}
|
||||
|
||||
public void offset( float x, float y ) {
|
||||
offsetX += x;
|
||||
offsetY += y;
|
||||
updateFrame();
|
||||
}
|
||||
|
||||
public float offsetX() {
|
||||
return offsetX;
|
||||
}
|
||||
|
||||
public float offsetY() {
|
||||
return offsetY;
|
||||
}
|
||||
|
||||
public void scale( float x, float y ) {
|
||||
scaleX = x;
|
||||
scaleY = y;
|
||||
updateFrame();
|
||||
}
|
||||
|
||||
public void size( float w, float h ) {
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
updateFrame();
|
||||
updateVertices();
|
||||
}
|
||||
}
|
110
SPD-classes/src/main/java/com/watabou/noosa/TextureFilm.java
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.watabou.gltextures.SmartTexture;
|
||||
import com.watabou.gltextures.TextureCache;
|
||||
|
||||
import android.graphics.RectF;
|
||||
|
||||
public class TextureFilm {
|
||||
|
||||
private static final RectF FULL = new RectF( 0, 0, 1, 1 );
|
||||
|
||||
private int texWidth;
|
||||
private int texHeight;
|
||||
|
||||
protected HashMap<Object,RectF> frames = new HashMap<Object, RectF>();
|
||||
|
||||
public TextureFilm( Object tx ) {
|
||||
|
||||
SmartTexture texture = TextureCache.get( tx );
|
||||
|
||||
texWidth = texture.width;
|
||||
texHeight = texture.height;
|
||||
|
||||
add( null, FULL );
|
||||
}
|
||||
|
||||
public TextureFilm( SmartTexture texture, int width ) {
|
||||
this( texture, width, texture.height );
|
||||
}
|
||||
|
||||
public TextureFilm( Object tx, int width, int height ) {
|
||||
|
||||
SmartTexture texture = TextureCache.get( tx );
|
||||
|
||||
texWidth = texture.width;
|
||||
texHeight = texture.height;
|
||||
|
||||
float uw = (float)width / texWidth;
|
||||
float vh = (float)height / texHeight;
|
||||
int cols = texWidth / width;
|
||||
int rows = texHeight / height;
|
||||
|
||||
for (int i=0; i < rows; i++) {
|
||||
for (int j=0; j < cols; j++) {
|
||||
RectF rect = new RectF( j * uw, i * vh, (j+1) * uw, (i+1) * vh );
|
||||
add( i * cols + j, rect );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TextureFilm( TextureFilm atlas, Object key, int width, int height ) {
|
||||
|
||||
texWidth = atlas.texWidth;
|
||||
texHeight = atlas.texHeight;
|
||||
|
||||
RectF patch = atlas.get( key );
|
||||
|
||||
float uw = (float)width / texWidth;
|
||||
float vh = (float)height / texHeight;
|
||||
int cols = (int)(width( patch ) / width);
|
||||
int rows = (int)(height( patch ) / height);
|
||||
|
||||
for (int i=0; i < rows; i++) {
|
||||
for (int j=0; j < cols; j++) {
|
||||
RectF rect = new RectF( j * uw, i * vh, (j+1) * uw, (i+1) * vh );
|
||||
rect.offset( patch.left, patch.top );
|
||||
add( i * cols + j, rect );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void add( Object id, RectF rect ) {
|
||||
frames.put( id, rect );
|
||||
}
|
||||
|
||||
public RectF get( Object id ) {
|
||||
return frames.get( id );
|
||||
}
|
||||
|
||||
public float width( RectF frame ) {
|
||||
return frame.width() * texWidth;
|
||||
}
|
||||
|
||||
public float height( RectF frame ) {
|
||||
return frame.height() * texHeight;
|
||||
}
|
||||
}
|
160
SPD-classes/src/main/java/com/watabou/noosa/Tilemap.java
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import com.watabou.gltextures.SmartTexture;
|
||||
import com.watabou.gltextures.TextureCache;
|
||||
import com.watabou.glwrap.Quad;
|
||||
import com.watabou.utils.Rect;
|
||||
|
||||
import android.graphics.RectF;
|
||||
|
||||
public class Tilemap extends Visual {
|
||||
|
||||
protected SmartTexture texture;
|
||||
protected TextureFilm tileset;
|
||||
|
||||
protected int[] data;
|
||||
protected int mapWidth;
|
||||
protected int mapHeight;
|
||||
protected int size;
|
||||
|
||||
private float cellW;
|
||||
private float cellH;
|
||||
|
||||
protected float[] vertices;
|
||||
protected FloatBuffer quads;
|
||||
|
||||
public Rect updated;
|
||||
|
||||
public Tilemap( Object tx, TextureFilm tileset ) {
|
||||
|
||||
super( 0, 0, 0, 0 );
|
||||
|
||||
this.texture = TextureCache.get( tx );
|
||||
this.tileset = tileset;
|
||||
|
||||
RectF r = tileset.get( 0 );
|
||||
cellW = tileset.width( r );
|
||||
cellH = tileset.height( r );
|
||||
|
||||
vertices = new float[16];
|
||||
|
||||
updated = new Rect();
|
||||
}
|
||||
|
||||
public void map( int[] data, int cols ) {
|
||||
|
||||
this.data = data;
|
||||
|
||||
mapWidth = cols;
|
||||
mapHeight = data.length / cols;
|
||||
size = mapWidth * mapHeight;
|
||||
|
||||
width = cellW * mapWidth;
|
||||
height = cellH * mapHeight;
|
||||
|
||||
quads = Quad.createSet( size );
|
||||
|
||||
updated.set( 0, 0, mapWidth, mapHeight );
|
||||
}
|
||||
|
||||
protected void updateVertices() {
|
||||
|
||||
float y1 = cellH * updated.top;
|
||||
float y2 = y1 + cellH;
|
||||
|
||||
for (int i=updated.top; i < updated.bottom; i++) {
|
||||
|
||||
float x1 = cellW * updated.left;
|
||||
float x2 = x1 + cellW;
|
||||
|
||||
int pos = i * mapWidth + updated.left;
|
||||
quads.position( 16 * pos );
|
||||
|
||||
for (int j=updated.left; j < updated.right; j++) {
|
||||
|
||||
RectF uv = tileset.get( data[pos++] );
|
||||
|
||||
vertices[0] = x1;
|
||||
vertices[1] = y1;
|
||||
|
||||
vertices[2] = uv.left;
|
||||
vertices[3] = uv.top;
|
||||
|
||||
vertices[4] = x2;
|
||||
vertices[5] = y1;
|
||||
|
||||
vertices[6] = uv.right;
|
||||
vertices[7] = uv.top;
|
||||
|
||||
vertices[8] = x2;
|
||||
vertices[9] = y2;
|
||||
|
||||
vertices[10] = uv.right;
|
||||
vertices[11] = uv.bottom;
|
||||
|
||||
vertices[12] = x1;
|
||||
vertices[13] = y2;
|
||||
|
||||
vertices[14] = uv.left;
|
||||
vertices[15] = uv.bottom;
|
||||
|
||||
quads.put( vertices );
|
||||
|
||||
x1 = x2;
|
||||
x2 += cellW;
|
||||
|
||||
}
|
||||
|
||||
y1 = y2;
|
||||
y2 += cellH;
|
||||
}
|
||||
|
||||
updated.setEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
|
||||
super.draw();
|
||||
|
||||
NoosaScript script = NoosaScript.get();
|
||||
|
||||
texture.bind();
|
||||
|
||||
script.uModel.valueM4( matrix );
|
||||
script.lighting(
|
||||
rm, gm, bm, am,
|
||||
ra, ga, ba, aa );
|
||||
|
||||
if (!updated.isEmpty()) {
|
||||
updateVertices();
|
||||
}
|
||||
|
||||
script.camera( camera );
|
||||
script.drawQuadSet( quads, size );
|
||||
|
||||
}
|
||||
}
|
121
SPD-classes/src/main/java/com/watabou/noosa/TouchArea.java
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import com.watabou.input.Touchscreen;
|
||||
import com.watabou.input.Touchscreen.Touch;
|
||||
import com.watabou.utils.Signal;
|
||||
|
||||
public class TouchArea extends Visual implements Signal.Listener<Touchscreen.Touch> {
|
||||
|
||||
// Its target can be toucharea itself
|
||||
public Visual target;
|
||||
|
||||
protected Touchscreen.Touch touch = null;
|
||||
|
||||
//if true, this TouchArea will always block input, even when it is inactive
|
||||
public boolean blockWhenInactive = false;
|
||||
|
||||
public TouchArea( Visual target ) {
|
||||
super( 0, 0, 0, 0 );
|
||||
this.target = target;
|
||||
|
||||
Touchscreen.event.add( this );
|
||||
}
|
||||
|
||||
public TouchArea( float x, float y, float width, float height ) {
|
||||
super( x, y, width, height );
|
||||
this.target = this;
|
||||
|
||||
visible = false;
|
||||
|
||||
Touchscreen.event.add( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSignal( Touch touch ) {
|
||||
|
||||
boolean hit = touch != null && target.overlapsScreenPoint( (int)touch.current.x, (int)touch.current.y );
|
||||
|
||||
if (!isActive()) {
|
||||
if (hit && blockWhenInactive) Touchscreen.event.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (hit) {
|
||||
|
||||
if (touch.down || touch == this.touch) Touchscreen.event.cancel();
|
||||
|
||||
if (touch.down) {
|
||||
|
||||
if (this.touch == null) {
|
||||
this.touch = touch;
|
||||
}
|
||||
onTouchDown( touch );
|
||||
|
||||
} else {
|
||||
|
||||
onTouchUp( touch );
|
||||
|
||||
if (this.touch == touch) {
|
||||
this.touch = null;
|
||||
onClick( touch );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (touch == null && this.touch != null) {
|
||||
onDrag( this.touch );
|
||||
}
|
||||
|
||||
else if (this.touch != null && !touch.down) {
|
||||
onTouchUp( touch );
|
||||
this.touch = null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected void onTouchDown( Touch touch ) {
|
||||
}
|
||||
|
||||
protected void onTouchUp( Touch touch ) {
|
||||
}
|
||||
|
||||
protected void onClick( Touch touch ) {
|
||||
}
|
||||
|
||||
protected void onDrag( Touch touch ) {
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
touch = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
Touchscreen.event.remove( this );
|
||||
super.destroy();
|
||||
}
|
||||
}
|
246
SPD-classes/src/main/java/com/watabou/noosa/Visual.java
Normal file
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa;
|
||||
|
||||
import com.watabou.glwrap.Matrix;
|
||||
import com.watabou.utils.GameMath;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.PointF;
|
||||
|
||||
public class Visual extends Gizmo {
|
||||
|
||||
public float x;
|
||||
public float y;
|
||||
public float width;
|
||||
public float height;
|
||||
|
||||
public PointF scale;
|
||||
public PointF origin;
|
||||
|
||||
protected float[] matrix;
|
||||
|
||||
public float rm;
|
||||
public float gm;
|
||||
public float bm;
|
||||
public float am;
|
||||
public float ra;
|
||||
public float ga;
|
||||
public float ba;
|
||||
public float aa;
|
||||
|
||||
public PointF speed;
|
||||
public PointF acc;
|
||||
|
||||
public float angle;
|
||||
public float angularSpeed;
|
||||
|
||||
public Visual( float x, float y, float width, float height ) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
scale = new PointF( 1, 1 );
|
||||
origin = new PointF();
|
||||
|
||||
matrix = new float[16];
|
||||
|
||||
resetColor();
|
||||
|
||||
speed = new PointF();
|
||||
acc = new PointF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
updateMotion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
updateMatrix();
|
||||
}
|
||||
|
||||
protected void updateMatrix() {
|
||||
Matrix.setIdentity( matrix );
|
||||
Matrix.translate( matrix, x, y );
|
||||
Matrix.translate( matrix, origin.x, origin.y );
|
||||
if (angle != 0) {
|
||||
Matrix.rotate( matrix, angle );
|
||||
}
|
||||
if (scale.x != 1 || scale.y != 1) {
|
||||
Matrix.scale( matrix, scale.x, scale.y );
|
||||
}
|
||||
Matrix.translate( matrix, -origin.x, -origin.y );
|
||||
}
|
||||
|
||||
public PointF point() {
|
||||
return new PointF( x, y );
|
||||
}
|
||||
|
||||
public PointF point( PointF p ) {
|
||||
x = p.x;
|
||||
y = p.y;
|
||||
return p;
|
||||
}
|
||||
|
||||
public Point point( Point p ) {
|
||||
x = p.x;
|
||||
y = p.y;
|
||||
return p;
|
||||
}
|
||||
|
||||
public PointF center() {
|
||||
return new PointF( x + width / 2, y + height / 2 );
|
||||
}
|
||||
|
||||
public PointF center( PointF p ) {
|
||||
x = p.x - width / 2;
|
||||
y = p.y - height / 2;
|
||||
return p;
|
||||
}
|
||||
|
||||
public float width() {
|
||||
return width * scale.x;
|
||||
}
|
||||
|
||||
public float height() {
|
||||
return height * scale.y;
|
||||
}
|
||||
|
||||
protected void updateMotion() {
|
||||
|
||||
float elapsed = Game.elapsed;
|
||||
|
||||
float d = (GameMath.speed( speed.x, acc.x ) - speed.x) / 2;
|
||||
speed.x += d;
|
||||
x += speed.x * elapsed;
|
||||
speed.x += d;
|
||||
|
||||
d = (GameMath.speed( speed.y, acc.y ) - speed.y) / 2;
|
||||
speed.y += d;
|
||||
y += speed.y * elapsed;
|
||||
speed.y += d;
|
||||
|
||||
angle += angularSpeed * elapsed;
|
||||
}
|
||||
|
||||
public void alpha( float value ) {
|
||||
am = value;
|
||||
aa = 0;
|
||||
}
|
||||
|
||||
public float alpha() {
|
||||
return am + aa;
|
||||
}
|
||||
|
||||
public void invert() {
|
||||
rm = gm = bm = -1f;
|
||||
ra = ga = ba = +1f;
|
||||
}
|
||||
|
||||
public void lightness( float value ) {
|
||||
if (value < 0.5f) {
|
||||
rm = gm = bm = value * 2f;
|
||||
ra = ga = ba = 0;
|
||||
} else {
|
||||
rm = gm = bm = 2f - value * 2f;
|
||||
ra = ga = ba = value * 2f - 1f;
|
||||
}
|
||||
}
|
||||
|
||||
public void brightness( float value ) {
|
||||
rm = gm = bm = value;
|
||||
}
|
||||
|
||||
public void tint( float r, float g, float b, float strength ) {
|
||||
rm = gm = bm = 1f - strength;
|
||||
ra = r * strength;
|
||||
ga = g * strength;
|
||||
ba = b * strength;
|
||||
}
|
||||
|
||||
public void tint( int color, float strength ) {
|
||||
rm = gm = bm = 1f - strength;
|
||||
ra = ((color >> 16) & 0xFF) / 255f * strength;
|
||||
ga = ((color >> 8) & 0xFF) / 255f * strength;
|
||||
ba = (color & 0xFF) / 255f * strength;
|
||||
}
|
||||
|
||||
//color must include an alpha component (e.g. 0x80FF0000 for red at 0.5 strength)
|
||||
public void tint( int color ) {
|
||||
tint( color & 0xFFFFFF, ((color >> 24) & 0xFF) / (float)0xFF);
|
||||
}
|
||||
|
||||
public void color( float r, float g, float b ) {
|
||||
rm = gm = bm = 0;
|
||||
ra = r;
|
||||
ga = g;
|
||||
ba = b;
|
||||
}
|
||||
|
||||
public void color( int color ) {
|
||||
color( ((color >> 16) & 0xFF) / 255f, ((color >> 8) & 0xFF) / 255f, (color & 0xFF) / 255f );
|
||||
}
|
||||
|
||||
public void hardlight( float r, float g, float b ) {
|
||||
ra = ga = ba = 0;
|
||||
rm = r;
|
||||
gm = g;
|
||||
bm = b;
|
||||
}
|
||||
|
||||
public void hardlight( int color ) {
|
||||
hardlight( (color >> 16) / 255f, ((color >> 8) & 0xFF) / 255f, (color & 0xFF) / 255f );
|
||||
}
|
||||
|
||||
public void resetColor() {
|
||||
rm = gm = bm = am = 1;
|
||||
ra = ga = ba = aa = 0;
|
||||
}
|
||||
|
||||
public boolean overlapsPoint( float x, float y ) {
|
||||
return x >= this.x && x < this.x + width * scale.x && y >= this.y && y < this.y + height * scale.y;
|
||||
}
|
||||
|
||||
public boolean overlapsScreenPoint( int x, int y ) {
|
||||
Camera c = camera();
|
||||
|
||||
if (c == null) return false;
|
||||
|
||||
PointF p = c.screenToCamera( x, y );
|
||||
return overlapsPoint( p.x, p.y );
|
||||
}
|
||||
|
||||
// true if its bounding box intersects its camera's bounds
|
||||
public boolean isVisible() {
|
||||
Camera c = camera();
|
||||
|
||||
if (c == null) return false;
|
||||
|
||||
float cx = c.scroll.x;
|
||||
float cy = c.scroll.y;
|
||||
float w = width();
|
||||
float h = height();
|
||||
return x + w >= cx && y + h >= cy && x < cx + c.width && y < cy + c.height;
|
||||
}
|
||||
}
|
141
SPD-classes/src/main/java/com/watabou/noosa/audio/Music.java
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.audio;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
|
||||
public enum Music implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
private MediaPlayer player;
|
||||
|
||||
private String lastPlayed;
|
||||
private boolean looping;
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
public void play( String assetName, boolean looping ) {
|
||||
|
||||
if (isPlaying() && lastPlayed.equals( assetName )) {
|
||||
return;
|
||||
}
|
||||
|
||||
stop();
|
||||
|
||||
lastPlayed = assetName;
|
||||
this.looping = looping;
|
||||
|
||||
if (!enabled || assetName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
AssetFileDescriptor afd = Game.instance.getAssets().openFd( assetName );
|
||||
|
||||
player = new MediaPlayer();
|
||||
player.setAudioStreamType( AudioManager.STREAM_MUSIC );
|
||||
player.setDataSource( afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength() );
|
||||
player.setOnPreparedListener( this );
|
||||
player.setOnErrorListener( this );
|
||||
player.prepareAsync();
|
||||
|
||||
} catch (IOException e) {
|
||||
|
||||
player.release();
|
||||
player = null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void mute() {
|
||||
lastPlayed = null;
|
||||
stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepared( MediaPlayer player ) {
|
||||
player.start();
|
||||
player.setLooping(looping);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onError( MediaPlayer mp, int what, int extra ) {
|
||||
if (player != null) {
|
||||
player.release();
|
||||
player = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
if (player != null) {
|
||||
player.pause();
|
||||
}
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
if (player != null) {
|
||||
player.start();
|
||||
player.setLooping(looping);
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (player != null) {
|
||||
player.stop();
|
||||
player.release();
|
||||
player = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void volume( float value ) {
|
||||
if (player != null) {
|
||||
player.setVolume( value, value );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPlaying() {
|
||||
return player != null && player.isPlaying();
|
||||
}
|
||||
|
||||
public void enable( boolean value ) {
|
||||
enabled = value;
|
||||
if (isPlaying() && !value) {
|
||||
stop();
|
||||
} else
|
||||
if (!isPlaying() && value) {
|
||||
play( lastPlayed, looping );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
}
|
151
SPD-classes/src/main/java/com/watabou/noosa/audio/Sample.java
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.audio;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.content.res.AssetManager;
|
||||
import android.media.AudioManager;
|
||||
import android.media.SoundPool;
|
||||
|
||||
public enum Sample implements SoundPool.OnLoadCompleteListener {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
public static final int MAX_STREAMS = 8;
|
||||
|
||||
protected SoundPool pool =
|
||||
new SoundPool( MAX_STREAMS, AudioManager.STREAM_MUSIC, 0 );
|
||||
|
||||
protected HashMap<Object, Integer> ids =
|
||||
new HashMap<>();
|
||||
|
||||
private boolean enabled = true;
|
||||
private float volume = 1f;
|
||||
|
||||
private LinkedList<String> loadingQueue = new LinkedList<>();
|
||||
|
||||
public void reset() {
|
||||
|
||||
ids.clear();
|
||||
loadingQueue = new LinkedList<>();
|
||||
pool.release();
|
||||
|
||||
pool = new SoundPool( MAX_STREAMS, AudioManager.STREAM_MUSIC, 0 );
|
||||
pool.setOnLoadCompleteListener( this );
|
||||
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
if (pool != null) {
|
||||
pool.autoPause();
|
||||
}
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
if (pool != null) {
|
||||
pool.autoResume();
|
||||
}
|
||||
}
|
||||
|
||||
public void load( String... assets ) {
|
||||
|
||||
for (String asset : assets) {
|
||||
loadingQueue.add( asset );
|
||||
}
|
||||
loadNext();
|
||||
}
|
||||
|
||||
private void loadNext() {
|
||||
final String asset = loadingQueue.poll();
|
||||
if (asset != null) {
|
||||
if (!ids.containsKey( asset )) {
|
||||
try {
|
||||
pool.setOnLoadCompleteListener( new SoundPool.OnLoadCompleteListener() {
|
||||
@Override
|
||||
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
|
||||
loadNext();
|
||||
}
|
||||
} );
|
||||
|
||||
AssetManager manager = Game.instance.getAssets();
|
||||
AssetFileDescriptor fd = manager.openFd( asset );
|
||||
int streamID = pool.load( fd, 1 ) ;
|
||||
ids.put( asset, streamID );
|
||||
fd.close();
|
||||
} catch (IOException e) {
|
||||
loadNext();
|
||||
} catch (NullPointerException e) {
|
||||
// Do nothing (stop loading sounds)
|
||||
}
|
||||
} else {
|
||||
loadNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void unload( Object src ) {
|
||||
|
||||
if (ids.containsKey( src )) {
|
||||
|
||||
pool.unload( ids.get( src ) );
|
||||
ids.remove( src );
|
||||
}
|
||||
}
|
||||
|
||||
public int play( Object id ) {
|
||||
return play( id, 1 );
|
||||
}
|
||||
|
||||
public int play( Object id, float volume ) {
|
||||
return play( id, volume, volume, 1 );
|
||||
}
|
||||
|
||||
public int play( Object id, float leftVolume, float rightVolume, float rate ) {
|
||||
if (enabled && ids.containsKey( id )) {
|
||||
return pool.play( ids.get( id ), leftVolume*volume, rightVolume*volume, 0, 0, rate );
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void enable( boolean value ) {
|
||||
enabled = value;
|
||||
}
|
||||
|
||||
public void volume( float value ) {
|
||||
this.volume = value;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadComplete( SoundPool soundPool, int sampleId, int status ) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.particles;
|
||||
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.watabou.gltextures.SmartTexture;
|
||||
import com.watabou.noosa.Image;
|
||||
import com.watabou.noosa.particles.Emitter;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class BitmaskEmitter extends Emitter {
|
||||
|
||||
// DON'T USE WITH COMPLETELY TRANSPARENT IMAGES!!!
|
||||
|
||||
private SmartTexture map;
|
||||
private int mapW;
|
||||
private int mapH;
|
||||
|
||||
public BitmaskEmitter( Image target ) {
|
||||
super();
|
||||
|
||||
this.target = target;
|
||||
|
||||
map = target.texture;
|
||||
mapW = map.bitmap.getWidth();
|
||||
mapH = map.bitmap.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void emit( int index ) {
|
||||
|
||||
RectF frame = ((Image)target).frame();
|
||||
float ofsX = frame.left * mapW;
|
||||
float ofsY = frame.top * mapH;
|
||||
|
||||
float x, y;
|
||||
do {
|
||||
x = Random.Float( frame.width() ) * mapW;
|
||||
y = Random.Float( frame.height() ) * mapH;
|
||||
} while ((map.bitmap.getPixel( (int)(x + ofsX), (int)(y + ofsY) ) & 0x000000FF) == 0);
|
||||
|
||||
factory.emit( this, index,
|
||||
target.x + x * target.scale.x,
|
||||
target.y + y * target.scale.y );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.particles;
|
||||
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
import com.watabou.noosa.Group;
|
||||
import com.watabou.noosa.Visual;
|
||||
import com.watabou.utils.PointF;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Emitter extends Group {
|
||||
|
||||
protected boolean lightMode = false;
|
||||
|
||||
public float x;
|
||||
public float y;
|
||||
public float width;
|
||||
public float height;
|
||||
|
||||
protected Visual target;
|
||||
public boolean fillTarget = true;
|
||||
|
||||
protected float interval;
|
||||
protected int quantity;
|
||||
|
||||
public boolean on = false;
|
||||
|
||||
public boolean autoKill = true;
|
||||
|
||||
protected int count;
|
||||
protected float time;
|
||||
|
||||
protected Factory factory;
|
||||
|
||||
public void pos( float x, float y ) {
|
||||
pos( x, y, 0, 0 );
|
||||
}
|
||||
|
||||
public void pos( PointF p ) {
|
||||
pos( p.x, p.y, 0, 0 );
|
||||
}
|
||||
|
||||
public void pos( float x, float y, float width, float height ) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
target = null;
|
||||
}
|
||||
|
||||
public void pos( Visual target ) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public void pos( Visual target, float x, float y, float width, float height ) {
|
||||
pos(x, y, width, height);
|
||||
pos(target);
|
||||
}
|
||||
|
||||
public void burst( Factory factory, int quantity ) {
|
||||
start( factory, 0, quantity );
|
||||
}
|
||||
|
||||
public void pour( Factory factory, float interval ) {
|
||||
start( factory, interval, 0 );
|
||||
}
|
||||
|
||||
public void start( Factory factory, float interval, int quantity ) {
|
||||
|
||||
this.factory = factory;
|
||||
this.lightMode = factory.lightMode();
|
||||
|
||||
this.interval = interval;
|
||||
this.quantity = quantity;
|
||||
|
||||
count = 0;
|
||||
time = Random.Float( interval );
|
||||
|
||||
on = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
|
||||
if (on) {
|
||||
time += Game.elapsed;
|
||||
while (time > interval) {
|
||||
time -= interval;
|
||||
emit( count++ );
|
||||
if (quantity > 0 && count >= quantity) {
|
||||
on = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (autoKill && countLiving() == 0) {
|
||||
kill();
|
||||
}
|
||||
|
||||
super.update();
|
||||
}
|
||||
|
||||
protected void emit( int index ) {
|
||||
if (target == null) {
|
||||
factory.emit(
|
||||
this,
|
||||
index,
|
||||
x + Random.Float( width ),
|
||||
y + Random.Float( height ) );
|
||||
} else {
|
||||
if (fillTarget) {
|
||||
factory.emit(
|
||||
this,
|
||||
index,
|
||||
target.x + Random.Float( target.width ),
|
||||
target.y + Random.Float( target.height ) );
|
||||
} else {
|
||||
factory.emit(
|
||||
this,
|
||||
index,
|
||||
target.x + x + Random.Float( width ),
|
||||
target.y + y + Random.Float( height ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
if (lightMode) {
|
||||
GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE );
|
||||
super.draw();
|
||||
GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA );
|
||||
} else {
|
||||
super.draw();
|
||||
}
|
||||
}
|
||||
|
||||
abstract public static class Factory {
|
||||
|
||||
abstract public void emit( Emitter emitter, int index, float x, float y );
|
||||
|
||||
public boolean lightMode() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.particles;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
import com.watabou.noosa.PseudoPixel;
|
||||
|
||||
public class PixelParticle extends PseudoPixel {
|
||||
|
||||
protected float size;
|
||||
|
||||
protected float lifespan;
|
||||
protected float left;
|
||||
|
||||
public PixelParticle() {
|
||||
super();
|
||||
|
||||
origin.set( +0.5f );
|
||||
}
|
||||
|
||||
public void reset( float x, float y, int color, float size, float lifespan ) {
|
||||
revive();
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
color( color );
|
||||
size( this.size = size );
|
||||
|
||||
this.left = this.lifespan = lifespan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
|
||||
if ((left -= Game.elapsed) <= 0) {
|
||||
kill();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Shrinking extends PixelParticle {
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
size( size * left / lifespan );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.tweeners;
|
||||
|
||||
import com.watabou.noosa.Visual;
|
||||
|
||||
public class AlphaTweener extends Tweener {
|
||||
|
||||
public Visual image;
|
||||
|
||||
public float start;
|
||||
public float delta;
|
||||
|
||||
public AlphaTweener( Visual image, float alpha, float time ) {
|
||||
super( image, time );
|
||||
|
||||
this.image = image;
|
||||
start = image.alpha();
|
||||
delta = alpha - start;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateValues( float progress ) {
|
||||
image.alpha( start + delta * progress );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.tweeners;
|
||||
|
||||
import com.watabou.noosa.Camera;
|
||||
import com.watabou.utils.PointF;
|
||||
|
||||
public class CameraScrollTweener extends Tweener {
|
||||
|
||||
public Camera camera;
|
||||
|
||||
public PointF start;
|
||||
public PointF end;
|
||||
|
||||
public CameraScrollTweener( Camera camera, PointF pos, float time ) {
|
||||
super( camera, time );
|
||||
|
||||
this.camera = camera;
|
||||
start = camera.scroll;
|
||||
end = pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateValues( float progress ) {
|
||||
camera.scroll = PointF.inter( start, end, progress );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.tweeners;
|
||||
|
||||
public class Delayer extends Tweener {
|
||||
|
||||
public Delayer() {
|
||||
super( null, 0 );
|
||||
}
|
||||
|
||||
public Delayer( float time ) {
|
||||
super( null, time );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateValues( float progress ) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.tweeners;
|
||||
|
||||
import com.watabou.noosa.Visual;
|
||||
import com.watabou.utils.PointF;
|
||||
|
||||
public class PosTweener extends Tweener {
|
||||
|
||||
public Visual visual;
|
||||
|
||||
public PointF start;
|
||||
public PointF end;
|
||||
|
||||
public PosTweener( Visual visual, PointF pos, float time ) {
|
||||
super( visual, time );
|
||||
|
||||
this.visual = visual;
|
||||
start = visual.point();
|
||||
end = pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateValues( float progress ) {
|
||||
visual.point( PointF.inter( start, end, progress ) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.tweeners;
|
||||
|
||||
import com.watabou.noosa.Visual;
|
||||
import com.watabou.utils.PointF;
|
||||
|
||||
public class ScaleTweener extends Tweener {
|
||||
|
||||
public Visual visual;
|
||||
|
||||
public PointF start;
|
||||
public PointF end;
|
||||
|
||||
public ScaleTweener( Visual visual, PointF scale, float time ) {
|
||||
super( visual, time );
|
||||
|
||||
this.visual = visual;
|
||||
start = visual.scale;
|
||||
end = scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateValues( float progress ) {
|
||||
visual.scale = PointF.inter( start, end, progress );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.tweeners;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
import com.watabou.noosa.Gizmo;
|
||||
|
||||
abstract public class Tweener extends Gizmo {
|
||||
|
||||
public Gizmo target;
|
||||
|
||||
public float interval;
|
||||
public float elapsed;
|
||||
|
||||
public Listener listener;
|
||||
|
||||
public Tweener( Gizmo target, float interval ) {
|
||||
super();
|
||||
|
||||
this.target = target;
|
||||
this.interval = interval;
|
||||
|
||||
elapsed = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
elapsed += Game.elapsed;
|
||||
if (elapsed >= interval) {
|
||||
updateValues( 1 );
|
||||
onComplete();
|
||||
kill();
|
||||
} else {
|
||||
updateValues( elapsed / interval );
|
||||
}
|
||||
}
|
||||
|
||||
protected void onComplete() {
|
||||
if (listener != null) {
|
||||
listener.onComplete( this );
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected void updateValues( float progress );
|
||||
|
||||
public static interface Listener {
|
||||
void onComplete( Tweener tweener );
|
||||
}
|
||||
}
|
100
SPD-classes/src/main/java/com/watabou/noosa/ui/Button.java
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.ui;
|
||||
|
||||
import com.watabou.input.Touchscreen.Touch;
|
||||
import com.watabou.noosa.Game;
|
||||
import com.watabou.noosa.TouchArea;
|
||||
|
||||
public class Button extends Component {
|
||||
|
||||
public static float longClick = 1f;
|
||||
|
||||
protected TouchArea hotArea;
|
||||
|
||||
protected boolean pressed;
|
||||
protected float pressTime;
|
||||
|
||||
protected boolean processed;
|
||||
|
||||
@Override
|
||||
protected void createChildren() {
|
||||
hotArea = new TouchArea( 0, 0, 0, 0 ) {
|
||||
@Override
|
||||
protected void onTouchDown(Touch touch) {
|
||||
pressed = true;
|
||||
pressTime = 0;
|
||||
processed = false;
|
||||
Button.this.onTouchDown();
|
||||
};
|
||||
@Override
|
||||
protected void onTouchUp(Touch touch) {
|
||||
pressed = false;
|
||||
Button.this.onTouchUp();
|
||||
};
|
||||
@Override
|
||||
protected void onClick( Touch touch ) {
|
||||
if (!processed) {
|
||||
Button.this.onClick();
|
||||
}
|
||||
};
|
||||
};
|
||||
add( hotArea );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
|
||||
hotArea.active = visible;
|
||||
|
||||
if (pressed) {
|
||||
if ((pressTime += Game.elapsed) >= longClick) {
|
||||
pressed = false;
|
||||
if (onLongClick()) {
|
||||
|
||||
hotArea.reset();
|
||||
processed = true;
|
||||
onTouchUp();
|
||||
|
||||
Game.vibrate( 50 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void onTouchDown() {};
|
||||
protected void onTouchUp() {};
|
||||
protected void onClick() {};
|
||||
|
||||
protected boolean onLongClick() {
|
||||
return false;
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void layout() {
|
||||
hotArea.x = x;
|
||||
hotArea.y = y;
|
||||
hotArea.width = width;
|
||||
hotArea.height = height;
|
||||
}
|
||||
}
|
51
SPD-classes/src/main/java/com/watabou/noosa/ui/CheckBox.java
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.ui;
|
||||
|
||||
public class CheckBox extends Button {
|
||||
|
||||
protected boolean checked;
|
||||
|
||||
public boolean checked() {
|
||||
return checked;
|
||||
}
|
||||
|
||||
public void checked( boolean value ) {
|
||||
if (checked != value) {
|
||||
checked = value;
|
||||
updateState();
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateState() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClick() {
|
||||
checked( !checked );
|
||||
onChange();
|
||||
}
|
||||
|
||||
protected void onChange() {
|
||||
}
|
||||
}
|
109
SPD-classes/src/main/java/com/watabou/noosa/ui/Component.java
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.noosa.ui;
|
||||
|
||||
import com.watabou.noosa.Group;
|
||||
|
||||
public class Component extends Group {
|
||||
|
||||
protected float x;
|
||||
protected float y;
|
||||
protected float width;
|
||||
protected float height;
|
||||
|
||||
public Component() {
|
||||
super();
|
||||
createChildren();
|
||||
}
|
||||
|
||||
public Component setPos( float x, float y ) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
layout();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Component setSize( float width, float height ) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
layout();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Component setRect( float x, float y, float width, float height ) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
layout();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean inside( float x, float y ) {
|
||||
return x >= this.x && y >= this.y && x < this.x + width && y < this.y + height;
|
||||
}
|
||||
|
||||
public void fill( Component c ) {
|
||||
setRect( c.x, c.y, c.width, c.height );
|
||||
}
|
||||
|
||||
public float left() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public float right() {
|
||||
return x + width;
|
||||
}
|
||||
|
||||
public float centerX() {
|
||||
return x + width / 2;
|
||||
}
|
||||
|
||||
public float top() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public float bottom() {
|
||||
return y + height;
|
||||
}
|
||||
|
||||
public float centerY() {
|
||||
return y + height / 2;
|
||||
}
|
||||
|
||||
public float width() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public float height() {
|
||||
return height;
|
||||
}
|
||||
|
||||
protected void createChildren() {
|
||||
}
|
||||
|
||||
protected void layout() {
|
||||
}
|
||||
}
|
125
SPD-classes/src/main/java/com/watabou/utils/BitmapCache.java
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
||||
public class BitmapCache {
|
||||
|
||||
private static final String DEFAULT = "__default";
|
||||
|
||||
private static HashMap<String,Layer> layers = new HashMap<String, BitmapCache.Layer>();
|
||||
|
||||
private static BitmapFactory.Options opts = new BitmapFactory.Options();
|
||||
static {
|
||||
opts.inDither = false;
|
||||
}
|
||||
|
||||
public static Context context;
|
||||
|
||||
public static Bitmap get( String assetName ) {
|
||||
return get( DEFAULT, assetName );
|
||||
}
|
||||
|
||||
public static Bitmap get( String layerName, String assetName ) {
|
||||
|
||||
Layer layer;
|
||||
if (!layers.containsKey( layerName )) {
|
||||
layer = new Layer();
|
||||
layers.put( layerName, layer );
|
||||
} else {
|
||||
layer = layers.get( layerName );
|
||||
}
|
||||
|
||||
if (layer.containsKey( assetName )) {
|
||||
return layer.get( assetName );
|
||||
} else {
|
||||
|
||||
try {
|
||||
InputStream stream = context.getResources().getAssets().open( assetName );
|
||||
Bitmap bmp = BitmapFactory.decodeStream( stream, null, opts );
|
||||
layer.put( assetName, bmp );
|
||||
return bmp;
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static Bitmap get( int resID ) {
|
||||
return get( DEFAULT, resID );
|
||||
}
|
||||
|
||||
public static Bitmap get( String layerName, int resID ) {
|
||||
|
||||
Layer layer;
|
||||
if (!layers.containsKey( layerName )) {
|
||||
layer = new Layer();
|
||||
layers.put( layerName, layer );
|
||||
} else {
|
||||
layer = layers.get( layerName );
|
||||
}
|
||||
|
||||
if (layer.containsKey( resID )) {
|
||||
return layer.get( resID );
|
||||
} else {
|
||||
|
||||
Bitmap bmp = BitmapFactory.decodeResource( context.getResources(), resID );
|
||||
layer.put( resID, bmp );
|
||||
return bmp;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void clear( String layerName ) {
|
||||
if (layers.containsKey( layerName )) {
|
||||
layers.get( layerName ).clear();
|
||||
layers.remove( layerName );
|
||||
}
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
for (Layer layer:layers.values()) {
|
||||
layer.clear();
|
||||
}
|
||||
layers.clear();
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class Layer extends HashMap<Object,Bitmap> {
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
for (Bitmap bmp:values()) {
|
||||
bmp.recycle();
|
||||
}
|
||||
super.clear();
|
||||
}
|
||||
}
|
||||
}
|
63
SPD-classes/src/main/java/com/watabou/utils/BitmapFilm.java
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
|
||||
public class BitmapFilm {
|
||||
|
||||
public Bitmap bitmap;
|
||||
|
||||
protected HashMap<Object,Rect> frames = new HashMap<Object, Rect>();
|
||||
|
||||
public BitmapFilm( Bitmap bitmap ) {
|
||||
this.bitmap = bitmap;
|
||||
add( null, new Rect( 0, 0, bitmap.getWidth(), bitmap.getHeight() ) );
|
||||
}
|
||||
|
||||
public BitmapFilm( Bitmap bitmap, int width ) {
|
||||
this( bitmap, width, bitmap.getHeight() );
|
||||
}
|
||||
|
||||
public BitmapFilm( Bitmap bitmap, int width, int height ) {
|
||||
this.bitmap = bitmap;
|
||||
int cols = bitmap.getWidth() / width;
|
||||
int rows = bitmap.getHeight() / height;
|
||||
for (int i=0; i < rows; i++) {
|
||||
for (int j=0; j < cols; j++) {
|
||||
Rect rect = new Rect( j * width, i * height, (j+1) * width, (i+1) * height );
|
||||
add( i * cols + j, rect );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void add( Object id, Rect rect ) {
|
||||
frames.put( id, rect );
|
||||
}
|
||||
|
||||
public Rect get( Object id ) {
|
||||
return frames.get( id );
|
||||
}
|
||||
}
|
29
SPD-classes/src/main/java/com/watabou/utils/Bundlable.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
public interface Bundlable {
|
||||
|
||||
void restoreFromBundle( Bundle bundle );
|
||||
void storeInBundle( Bundle bundle );
|
||||
|
||||
}
|
411
SPD-classes/src/main/java/com/watabou/utils/Bundle.java
Normal file
|
@ -0,0 +1,411 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PushbackInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONTokener;
|
||||
|
||||
public class Bundle {
|
||||
|
||||
private static final String CLASS_NAME = "__className";
|
||||
|
||||
private static HashMap<String,String> aliases = new HashMap<String, String>();
|
||||
|
||||
private JSONObject data;
|
||||
|
||||
public Bundle() {
|
||||
this( new JSONObject() );
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return data.toString();
|
||||
}
|
||||
|
||||
private Bundle( JSONObject data ) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public boolean isNull() {
|
||||
return data == null;
|
||||
}
|
||||
|
||||
public boolean contains( String key ) {
|
||||
return !data.isNull( key );
|
||||
}
|
||||
|
||||
public boolean getBoolean( String key ) {
|
||||
return data.optBoolean( key );
|
||||
}
|
||||
|
||||
public int getInt( String key ) {
|
||||
return data.optInt( key );
|
||||
}
|
||||
|
||||
public float getFloat( String key ) {
|
||||
return (float)data.optDouble( key, 0.0 );
|
||||
}
|
||||
|
||||
public String getString( String key ) {
|
||||
return data.optString( key );
|
||||
}
|
||||
|
||||
public Class getClass( String key ) {
|
||||
String clName = getString(key).replace("class ", "");;
|
||||
if (clName != null){
|
||||
if (aliases.containsKey( clName )) {
|
||||
clName = aliases.get( clName );
|
||||
}
|
||||
try {
|
||||
Class cl = Class.forName( clName );
|
||||
return cl;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Bundle getBundle( String key ) {
|
||||
return new Bundle( data.optJSONObject( key ) );
|
||||
}
|
||||
|
||||
private Bundlable get() {
|
||||
if (data == null) return null;
|
||||
try {
|
||||
String clName = getString( CLASS_NAME );
|
||||
if (aliases.containsKey( clName )) {
|
||||
clName = aliases.get( clName );
|
||||
}
|
||||
|
||||
Class<?> cl = Class.forName( clName );
|
||||
if (cl != null) {
|
||||
Bundlable object = (Bundlable)cl.newInstance();
|
||||
object.restoreFromBundle( this );
|
||||
return object;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (ClassNotFoundException e ) {
|
||||
return null;
|
||||
} catch (InstantiationException e ) {
|
||||
return null;
|
||||
} catch (IllegalAccessException e ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Bundlable get( String key ) {
|
||||
return getBundle( key ).get();
|
||||
}
|
||||
|
||||
public <E extends Enum<E>> E getEnum( String key, Class<E> enumClass ) {
|
||||
try {
|
||||
return Enum.valueOf( enumClass, data.getString( key ) );
|
||||
} catch (JSONException e) {
|
||||
return enumClass.getEnumConstants()[0];
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getIntArray( String key ) {
|
||||
try {
|
||||
JSONArray array = data.getJSONArray( key );
|
||||
int length = array.length();
|
||||
int[] result = new int[length];
|
||||
for (int i=0; i < length; i++) {
|
||||
result[i] = array.getInt( i );
|
||||
}
|
||||
return result;
|
||||
} catch (JSONException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean[] getBooleanArray( String key ) {
|
||||
try {
|
||||
JSONArray array = data.getJSONArray( key );
|
||||
int length = array.length();
|
||||
boolean[] result = new boolean[length];
|
||||
for (int i=0; i < length; i++) {
|
||||
result[i] = array.getBoolean( i );
|
||||
}
|
||||
return result;
|
||||
} catch (JSONException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getStringArray( String key ) {
|
||||
try {
|
||||
JSONArray array = data.getJSONArray( key );
|
||||
int length = array.length();
|
||||
String[] result = new String[length];
|
||||
for (int i=0; i < length; i++) {
|
||||
result[i] = array.getString( i );
|
||||
}
|
||||
return result;
|
||||
} catch (JSONException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Class[] getClassArray( String key ) {
|
||||
try {
|
||||
JSONArray array = data.getJSONArray( key );
|
||||
int length = array.length();
|
||||
Class[] result = new Class[length];
|
||||
for (int i=0; i < length; i++) {
|
||||
String clName = array.getString( i ).replace("class ", "");
|
||||
if (aliases.containsKey( clName )) {
|
||||
clName = aliases.get( clName );
|
||||
}
|
||||
try {
|
||||
Class cl = Class.forName( clName );
|
||||
result[i] = cl;
|
||||
} catch (ClassNotFoundException e) {
|
||||
result[i] = null;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (JSONException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Bundlable> getCollection( String key ) {
|
||||
|
||||
ArrayList<Bundlable> list = new ArrayList<Bundlable>();
|
||||
|
||||
try {
|
||||
JSONArray array = data.getJSONArray( key );
|
||||
for (int i=0; i < array.length(); i++) {
|
||||
Bundlable O = new Bundle( array.getJSONObject( i ) ).get();
|
||||
if (O != null) list.add( O );
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public void put( String key, boolean value ) {
|
||||
try {
|
||||
data.put( key, value );
|
||||
} catch (JSONException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, int value ) {
|
||||
try {
|
||||
data.put( key, value );
|
||||
} catch (JSONException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, float value ) {
|
||||
try {
|
||||
data.put( key, value );
|
||||
} catch (JSONException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, String value ) {
|
||||
try {
|
||||
data.put( key, value );
|
||||
} catch (JSONException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, Class value ){
|
||||
try {
|
||||
data.put( key, value );
|
||||
} catch (JSONException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, Bundle bundle ) {
|
||||
try {
|
||||
data.put( key, bundle.data );
|
||||
} catch (JSONException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, Bundlable object ) {
|
||||
if (object != null) {
|
||||
try {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.put( CLASS_NAME, object.getClass().getName() );
|
||||
object.storeInBundle( bundle );
|
||||
data.put( key, bundle.data );
|
||||
} catch (JSONException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, Enum<?> value ) {
|
||||
if (value != null) {
|
||||
try {
|
||||
data.put( key, value.name() );
|
||||
} catch (JSONException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, int[] array ) {
|
||||
try {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (int i=0; i < array.length; i++) {
|
||||
jsonArray.put( i, array[i] );
|
||||
}
|
||||
data.put( key, jsonArray );
|
||||
} catch (JSONException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, boolean[] array ) {
|
||||
try {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (int i=0; i < array.length; i++) {
|
||||
jsonArray.put( i, array[i] );
|
||||
}
|
||||
data.put( key, jsonArray );
|
||||
} catch (JSONException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, String[] array ) {
|
||||
try {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (int i=0; i < array.length; i++) {
|
||||
jsonArray.put( i, array[i] );
|
||||
}
|
||||
data.put( key, jsonArray );
|
||||
} catch (JSONException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, Class[] array ){
|
||||
try {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (int i=0; i < array.length; i++) {
|
||||
jsonArray.put( i, array[i] );
|
||||
}
|
||||
data.put( key, jsonArray );
|
||||
} catch (JSONException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void put( String key, Collection<? extends Bundlable> collection ) {
|
||||
JSONArray array = new JSONArray();
|
||||
for (Bundlable object : collection) {
|
||||
if (object != null) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.put(CLASS_NAME, object.getClass().getName());
|
||||
object.storeInBundle(bundle);
|
||||
array.put(bundle.data);
|
||||
}
|
||||
}
|
||||
try {
|
||||
data.put( key, array );
|
||||
} catch (JSONException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//useful to turn this off for save data debugging.
|
||||
private static final boolean compressByDefault = true;
|
||||
|
||||
private static final int GZIP_BUFFER = 1024*4; //4 kb
|
||||
|
||||
public static Bundle read( InputStream stream ) throws IOException {
|
||||
|
||||
try {
|
||||
BufferedReader reader;
|
||||
|
||||
//determines if we're reading a regular, or compressed file
|
||||
PushbackInputStream pb = new PushbackInputStream( stream, 2 );
|
||||
byte[] header = new byte[2];
|
||||
pb.unread(header, 0, pb.read(header));
|
||||
//GZIP header is 0x1f8b
|
||||
if( header[ 0 ] == (byte) 0x1f && header[ 1 ] == (byte) 0x8b )
|
||||
reader = new BufferedReader( new InputStreamReader( new GZIPInputStream( pb, GZIP_BUFFER ) ) );
|
||||
else
|
||||
reader = new BufferedReader( new InputStreamReader( pb ) );
|
||||
|
||||
JSONObject json = (JSONObject)new JSONTokener( reader.readLine() ).nextValue();
|
||||
reader.close();
|
||||
|
||||
return new Bundle( json );
|
||||
} catch (Exception e) {
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean write( Bundle bundle, OutputStream stream ){
|
||||
return write(bundle, stream, compressByDefault);
|
||||
}
|
||||
|
||||
public static boolean write( Bundle bundle, OutputStream stream, boolean compressed ) {
|
||||
try {
|
||||
BufferedWriter writer;
|
||||
if (compressed) writer = new BufferedWriter( new OutputStreamWriter( new GZIPOutputStream(stream, GZIP_BUFFER ) ) );
|
||||
else writer = new BufferedWriter( new OutputStreamWriter( stream ) );
|
||||
|
||||
writer.write( bundle.data.toString() );
|
||||
writer.close();
|
||||
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void addAlias( Class<?> cl, String alias ) {
|
||||
aliases.put( alias, cl.getName() );
|
||||
}
|
||||
}
|
28
SPD-classes/src/main/java/com/watabou/utils/Callback.java
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
public interface Callback {
|
||||
|
||||
void call();
|
||||
|
||||
}
|
65
SPD-classes/src/main/java/com/watabou/utils/ColorMath.java
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
public class ColorMath {
|
||||
|
||||
public static int interpolate( int A, int B, float p ) {
|
||||
|
||||
if (p <= 0) {
|
||||
return A;
|
||||
} else if (p >= 1) {
|
||||
return B;
|
||||
}
|
||||
|
||||
int ra = A >> 16;
|
||||
int ga = (A >> 8) & 0xFF;
|
||||
int ba = A & 0xFF;
|
||||
|
||||
int rb = B >> 16;
|
||||
int gb = (B >> 8) & 0xFF;
|
||||
int bb = B & 0xFF;
|
||||
|
||||
float p1 = 1 - p;
|
||||
|
||||
int r = (int)(p1 * ra + p * rb);
|
||||
int g = (int)(p1 * ga + p * gb);
|
||||
int b = (int)(p1 * ba + p * bb);
|
||||
|
||||
return (r << 16) + (g << 8) + b;
|
||||
}
|
||||
|
||||
public static int interpolate( float p, int... colors ) {
|
||||
if (p <= 0) {
|
||||
return colors[0];
|
||||
} else if (p >= 1) {
|
||||
return colors[colors.length-1];
|
||||
}
|
||||
int segment = (int)(colors.length * p);
|
||||
return interpolate( colors[segment], colors[segment+1], (p * (colors.length - 1)) % 1 );
|
||||
}
|
||||
|
||||
public static int random( int a, int b ) {
|
||||
return interpolate( a, b, Random.Float() );
|
||||
}
|
||||
|
||||
}
|
46
SPD-classes/src/main/java/com/watabou/utils/GameMath.java
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
|
||||
public class GameMath {
|
||||
|
||||
public static float speed( float speed, float acc ) {
|
||||
|
||||
if (acc != 0) {
|
||||
speed += acc * Game.elapsed;
|
||||
}
|
||||
|
||||
return speed;
|
||||
}
|
||||
|
||||
public static float gate( float min, float value, float max ) {
|
||||
if (value < min) {
|
||||
return min;
|
||||
} else if (value > max) {
|
||||
return max;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
107
SPD-classes/src/main/java/com/watabou/utils/Graph.java
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class Graph {
|
||||
|
||||
public static <T extends Node> void setPrice( List<T> nodes, int value ) {
|
||||
for (T node : nodes) {
|
||||
node.price( value );
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends Node> void buildDistanceMap( Collection<T> nodes, Node focus ) {
|
||||
|
||||
for (T node : nodes) {
|
||||
node.distance( Integer.MAX_VALUE );
|
||||
}
|
||||
|
||||
LinkedList<Node> queue = new LinkedList<Node>();
|
||||
|
||||
focus.distance( 0 );
|
||||
queue.add( focus );
|
||||
|
||||
while (!queue.isEmpty()) {
|
||||
|
||||
Node node = queue.poll();
|
||||
int distance = node.distance();
|
||||
int price = node.price();
|
||||
|
||||
for (Node edge : node.edges()) {
|
||||
if (edge.distance() > distance + price) {
|
||||
queue.add( edge );
|
||||
edge.distance( distance + price );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Node> List<T> buildPath( Collection<T> nodes, T from, T to ) {
|
||||
|
||||
List<T> path = new ArrayList<T>();
|
||||
|
||||
T room = from;
|
||||
while (room != to) {
|
||||
|
||||
int min = room.distance();
|
||||
T next = null;
|
||||
|
||||
Collection<? extends Node> edges = room.edges();
|
||||
|
||||
for (Node edge : edges) {
|
||||
|
||||
int distance = edge.distance();
|
||||
if (distance < min) {
|
||||
min = distance;
|
||||
next = (T)edge;
|
||||
}
|
||||
}
|
||||
|
||||
if (next == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
path.add( next );
|
||||
room = next;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public interface Node {
|
||||
|
||||
int distance();
|
||||
void distance( int value );
|
||||
|
||||
int price();
|
||||
void price( int value );
|
||||
|
||||
Collection<? extends Node> edges();
|
||||
|
||||
}
|
||||
}
|
81
SPD-classes/src/main/java/com/watabou/utils/Highlighter.java
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
package com.watabou.utils;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Highlighter {
|
||||
|
||||
private static final Pattern HIGHLIGHTER = Pattern.compile( "_(.*?)_" );
|
||||
private static final Pattern STRIPPER = Pattern.compile( "[ \n]" );
|
||||
|
||||
public String text;
|
||||
|
||||
public boolean[] mask;
|
||||
|
||||
public Highlighter( String text ) {
|
||||
|
||||
String stripped = STRIPPER.matcher( text ).replaceAll( "" );
|
||||
mask = new boolean[stripped.length()];
|
||||
|
||||
Matcher m = HIGHLIGHTER.matcher( stripped );
|
||||
|
||||
int pos = 0;
|
||||
int lastMatch = 0;
|
||||
|
||||
while (m.find()) {
|
||||
pos += (m.start() - lastMatch);
|
||||
int groupLen = m.group( 1 ).length();
|
||||
for (int i=pos; i < pos + groupLen; i++) {
|
||||
mask[i] = true;
|
||||
}
|
||||
pos += groupLen;
|
||||
lastMatch = m.end();
|
||||
}
|
||||
|
||||
m.reset( text );
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while (m.find()) {
|
||||
m.appendReplacement( sb, m.group( 1 ) );
|
||||
}
|
||||
m.appendTail( sb );
|
||||
|
||||
this.text = sb.toString();
|
||||
}
|
||||
|
||||
public boolean[] inverted() {
|
||||
boolean[] result = new boolean[mask.length];
|
||||
for (int i=0; i < result.length; i++) {
|
||||
result[i] = !mask[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isHighlighted() {
|
||||
for (int i=0; i < mask.length; i++) {
|
||||
if (mask[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
340
SPD-classes/src/main/java/com/watabou/utils/PathFinder.java
Normal file
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class PathFinder {
|
||||
|
||||
public static int[] distance;
|
||||
|
||||
private static boolean[] goals;
|
||||
private static int[] queue;
|
||||
|
||||
private static int size = 0;
|
||||
|
||||
private static int[] dir;
|
||||
|
||||
public static void setMapSize( int width, int height ) {
|
||||
|
||||
int size = width * height;
|
||||
|
||||
if (PathFinder.size != size) {
|
||||
|
||||
PathFinder.size = size;
|
||||
distance = new int[size];
|
||||
goals = new boolean[size];
|
||||
queue = new int[size];
|
||||
|
||||
dir = new int[]{-1, +1, -width, +width, -width-1, -width+1, +width-1, +width+1};
|
||||
}
|
||||
}
|
||||
|
||||
public static Path find( int from, int to, boolean[] passable ) {
|
||||
|
||||
if (!buildDistanceMap( from, to, passable )) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Path result = new Path();
|
||||
int s = from;
|
||||
|
||||
// From the starting position we are moving downwards,
|
||||
// until we reach the ending point
|
||||
do {
|
||||
int minD = distance[s];
|
||||
int mins = s;
|
||||
|
||||
for (int i=0; i < dir.length; i++) {
|
||||
|
||||
int n = s + dir[i];
|
||||
|
||||
int thisD = distance[n];
|
||||
if (thisD < minD) {
|
||||
minD = thisD;
|
||||
mins = n;
|
||||
}
|
||||
}
|
||||
s = mins;
|
||||
result.add( s );
|
||||
} while (s != to);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int getStep( int from, int to, boolean[] passable ) {
|
||||
|
||||
if (!buildDistanceMap( from, to, passable )) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// From the starting position we are making one step downwards
|
||||
int minD = distance[from];
|
||||
int best = from;
|
||||
|
||||
int step, stepD;
|
||||
|
||||
for (int i=0; i < dir.length; i++) {
|
||||
|
||||
if ((stepD = distance[step = from + dir[i]]) < minD) {
|
||||
minD = stepD;
|
||||
best = step;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
public static int getStepBack( int cur, int from, boolean[] passable ) {
|
||||
|
||||
int d = buildEscapeDistanceMap( cur, from, 2f, passable );
|
||||
for (int i=0; i < size; i++) {
|
||||
goals[i] = distance[i] == d;
|
||||
}
|
||||
if (!buildDistanceMap( cur, goals, passable )) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int s = cur;
|
||||
|
||||
// From the starting position we are making one step downwards
|
||||
int minD = distance[s];
|
||||
int mins = s;
|
||||
|
||||
for (int i=0; i < dir.length; i++) {
|
||||
|
||||
int n = s + dir[i];
|
||||
int thisD = distance[n];
|
||||
|
||||
if (thisD < minD) {
|
||||
minD = thisD;
|
||||
mins = n;
|
||||
}
|
||||
}
|
||||
|
||||
return mins;
|
||||
}
|
||||
|
||||
private static boolean buildDistanceMap( int from, int to, boolean[] passable ) {
|
||||
|
||||
if (from == to) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Arrays.fill( distance, Integer.MAX_VALUE );
|
||||
|
||||
boolean pathFound = false;
|
||||
|
||||
int head = 0;
|
||||
int tail = 0;
|
||||
|
||||
// Add to queue
|
||||
queue[tail++] = to;
|
||||
distance[to] = 0;
|
||||
|
||||
while (head < tail) {
|
||||
|
||||
// Remove from queue
|
||||
int step = queue[head++];
|
||||
if (step == from) {
|
||||
pathFound = true;
|
||||
break;
|
||||
}
|
||||
int nextDistance = distance[step] + 1;
|
||||
|
||||
for (int i=0; i < dir.length; i++) {
|
||||
|
||||
int n = step + dir[i];
|
||||
if (n == from || (n >= 0 && n < size && passable[n] && (distance[n] > nextDistance))) {
|
||||
// Add to queue
|
||||
queue[tail++] = n;
|
||||
distance[n] = nextDistance;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return pathFound;
|
||||
}
|
||||
|
||||
public static void buildDistanceMap( int to, boolean[] passable, int limit ) {
|
||||
|
||||
Arrays.fill( distance, Integer.MAX_VALUE );
|
||||
|
||||
int head = 0;
|
||||
int tail = 0;
|
||||
|
||||
// Add to queue
|
||||
queue[tail++] = to;
|
||||
distance[to] = 0;
|
||||
|
||||
while (head < tail) {
|
||||
|
||||
// Remove from queue
|
||||
int step = queue[head++];
|
||||
|
||||
int nextDistance = distance[step] + 1;
|
||||
if (nextDistance > limit) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=0; i < dir.length; i++) {
|
||||
|
||||
int n = step + dir[i];
|
||||
if (n >= 0 && n < size && passable[n] && (distance[n] > nextDistance)) {
|
||||
// Add to queue
|
||||
queue[tail++] = n;
|
||||
distance[n] = nextDistance;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean buildDistanceMap( int from, boolean[] to, boolean[] passable ) {
|
||||
|
||||
if (to[from]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Arrays.fill( distance, Integer.MAX_VALUE );
|
||||
|
||||
boolean pathFound = false;
|
||||
|
||||
int head = 0;
|
||||
int tail = 0;
|
||||
|
||||
// Add to queue
|
||||
for (int i=0; i < size; i++) {
|
||||
if (to[i]) {
|
||||
queue[tail++] = i;
|
||||
distance[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
while (head < tail) {
|
||||
|
||||
// Remove from queue
|
||||
int step = queue[head++];
|
||||
if (step == from) {
|
||||
pathFound = true;
|
||||
break;
|
||||
}
|
||||
int nextDistance = distance[step] + 1;
|
||||
|
||||
for (int i=0; i < dir.length; i++) {
|
||||
|
||||
int n = step + dir[i];
|
||||
if (n == from || (n >= 0 && n < size && passable[n] && (distance[n] > nextDistance))) {
|
||||
// Add to queue
|
||||
queue[tail++] = n;
|
||||
distance[n] = nextDistance;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return pathFound;
|
||||
}
|
||||
|
||||
private static int buildEscapeDistanceMap( int cur, int from, float factor, boolean[] passable ) {
|
||||
|
||||
Arrays.fill( distance, Integer.MAX_VALUE );
|
||||
|
||||
int destDist = Integer.MAX_VALUE;
|
||||
|
||||
int head = 0;
|
||||
int tail = 0;
|
||||
|
||||
// Add to queue
|
||||
queue[tail++] = from;
|
||||
distance[from] = 0;
|
||||
|
||||
int dist = 0;
|
||||
|
||||
while (head < tail) {
|
||||
|
||||
// Remove from queue
|
||||
int step = queue[head++];
|
||||
dist = distance[step];
|
||||
|
||||
if (dist > destDist) {
|
||||
return destDist;
|
||||
}
|
||||
|
||||
if (step == cur) {
|
||||
destDist = (int)(dist * factor) + 1;
|
||||
}
|
||||
|
||||
int nextDistance = dist + 1;
|
||||
|
||||
for (int i=0; i < dir.length; i++) {
|
||||
|
||||
int n = step + dir[i];
|
||||
if (n >= 0 && n < size && passable[n] && distance[n] > nextDistance) {
|
||||
// Add to queue
|
||||
queue[tail++] = n;
|
||||
distance[n] = nextDistance;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static void buildDistanceMap( int to, boolean[] passable ) {
|
||||
|
||||
Arrays.fill( distance, Integer.MAX_VALUE );
|
||||
|
||||
int head = 0;
|
||||
int tail = 0;
|
||||
|
||||
// Add to queue
|
||||
queue[tail++] = to;
|
||||
distance[to] = 0;
|
||||
|
||||
while (head < tail) {
|
||||
|
||||
// Remove from queue
|
||||
int step = queue[head++];
|
||||
int nextDistance = distance[step] + 1;
|
||||
|
||||
for (int i=0; i < dir.length; i++) {
|
||||
|
||||
int n = step + dir[i];
|
||||
if (n >= 0 && n < size && passable[n] && (distance[n] > nextDistance)) {
|
||||
// Add to queue
|
||||
queue[tail++] = n;
|
||||
distance[n] = nextDistance;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class Path extends LinkedList<Integer> {
|
||||
}
|
||||
}
|
85
SPD-classes/src/main/java/com/watabou/utils/Point.java
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
public class Point {
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
|
||||
public Point() {
|
||||
}
|
||||
|
||||
public Point( int x, int y ) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public Point( Point p ) {
|
||||
this.x = p.x;
|
||||
this.y = p.y;
|
||||
}
|
||||
|
||||
public Point set( int x, int y ) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Point set( Point p ) {
|
||||
x = p.x;
|
||||
y = p.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Point clone() {
|
||||
return new Point( this );
|
||||
}
|
||||
|
||||
public Point scale( float f ) {
|
||||
this.x *= f;
|
||||
this.y *= f;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Point offset( int dx, int dy ) {
|
||||
x += dx;
|
||||
y += dy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Point offset( Point d ) {
|
||||
x += d.x;
|
||||
y += d.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object obj ) {
|
||||
if (obj instanceof Point) {
|
||||
Point p = (Point)obj;
|
||||
return p.x == x && p.y == y;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
154
SPD-classes/src/main/java/com/watabou/utils/PointF.java
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.util.FloatMath;
|
||||
|
||||
@SuppressLint("FloatMath")
|
||||
public class PointF {
|
||||
|
||||
public static final float PI = 3.1415926f;
|
||||
public static final float PI2 = PI * 2;
|
||||
public static final float G2R = PI / 180;
|
||||
|
||||
public float x;
|
||||
public float y;
|
||||
|
||||
public PointF() {
|
||||
}
|
||||
|
||||
public PointF( float x, float y ) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public PointF( PointF p ) {
|
||||
this.x = p.x;
|
||||
this.y = p.y;
|
||||
}
|
||||
|
||||
public PointF( Point p ) {
|
||||
this.x = p.x;
|
||||
this.y = p.y;
|
||||
}
|
||||
|
||||
public PointF clone() {
|
||||
return new PointF( this );
|
||||
}
|
||||
|
||||
public PointF scale( float f ) {
|
||||
this.x *= f;
|
||||
this.y *= f;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PointF invScale( float f ) {
|
||||
this.x /= f;
|
||||
this.y /= f;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PointF set( float x, float y ) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PointF set( PointF p ) {
|
||||
this.x = p.x;
|
||||
this.y = p.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PointF set( float v ) {
|
||||
this.x = v;
|
||||
this.y = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PointF polar( float a, float l ) {
|
||||
this.x = l * (float)Math.cos( a );
|
||||
this.y = l * (float)Math.sin( a );
|
||||
return this;
|
||||
}
|
||||
|
||||
public PointF offset( float dx, float dy ) {
|
||||
x += dx;
|
||||
y += dy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PointF offset( PointF p ) {
|
||||
x += p.x;
|
||||
y += p.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PointF negate() {
|
||||
x = -x;
|
||||
y = -y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PointF normalize() {
|
||||
float l = length();
|
||||
x /= l;
|
||||
y /= l;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Point floor() {
|
||||
return new Point( (int)x, (int)y );
|
||||
}
|
||||
|
||||
public float length() {
|
||||
return (float)Math.sqrt( x * x + y * y );
|
||||
}
|
||||
|
||||
public static PointF sum( PointF a, PointF b ) {
|
||||
return new PointF( a.x + b.x, a.y + b.y );
|
||||
}
|
||||
|
||||
public static PointF diff( PointF a, PointF b ) {
|
||||
return new PointF( a.x - b.x, a.y - b.y );
|
||||
}
|
||||
|
||||
public static PointF inter( PointF a, PointF b, float d ) {
|
||||
return new PointF( a.x + (b.x - a.x) * d, a.y + (b.y - a.y) * d );
|
||||
}
|
||||
|
||||
public static float distance( PointF a, PointF b ) {
|
||||
float dx = a.x - b.x;
|
||||
float dy = a.y - b.y;
|
||||
return (float)Math.sqrt( dx * dx + dy * dy );
|
||||
}
|
||||
|
||||
public static float angle( PointF start, PointF end ) {
|
||||
return (float)Math.atan2( end.y - start.y, end.x - start.x );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "" + x + ", " + y;
|
||||
}
|
||||
}
|
154
SPD-classes/src/main/java/com/watabou/utils/Random.java
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Random {
|
||||
|
||||
public static float Float( float min, float max ) {
|
||||
return (float)(min + Math.random() * (max - min));
|
||||
}
|
||||
|
||||
public static float Float( float max ) {
|
||||
return (float)(Math.random() * max);
|
||||
}
|
||||
|
||||
public static float Float() {
|
||||
return (float)Math.random();
|
||||
}
|
||||
|
||||
public static int Int( int max ) {
|
||||
return max > 0 ? (int)(Math.random() * max) : 0;
|
||||
}
|
||||
|
||||
public static int Int( int min, int max ) {
|
||||
return min + (int)(Math.random() * (max - min));
|
||||
}
|
||||
|
||||
public static int IntRange( int min, int max ) {
|
||||
return min + (int)(Math.random() * (max - min + 1));
|
||||
}
|
||||
|
||||
public static int NormalIntRange( int min, int max ) {
|
||||
return min + (int)((Math.random() + Math.random()) * (max - min + 1) / 2f);
|
||||
}
|
||||
|
||||
public static int chances( float[] chances ) {
|
||||
|
||||
int length = chances.length;
|
||||
|
||||
float sum = 0;
|
||||
for (int i=0; i < length; i++) {
|
||||
sum += chances[i];
|
||||
}
|
||||
|
||||
float value = Float( sum );
|
||||
sum = 0;
|
||||
for (int i=0; i < length; i++) {
|
||||
sum += chances[i];
|
||||
if (value < sum) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K> K chances( HashMap<K,Float> chances ) {
|
||||
|
||||
int size = chances.size();
|
||||
|
||||
Object[] values = chances.keySet().toArray();
|
||||
float[] probs = new float[size];
|
||||
float sum = 0;
|
||||
for (int i=0; i < size; i++) {
|
||||
probs[i] = chances.get( values[i] );
|
||||
sum += probs[i];
|
||||
}
|
||||
|
||||
float value = Float( sum );
|
||||
|
||||
sum = probs[0];
|
||||
for (int i=0; i < size; i++) {
|
||||
if (value < sum) {
|
||||
return (K)values[i];
|
||||
}
|
||||
sum += probs[i + 1];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int index( Collection<?> collection ) {
|
||||
return (int)(Math.random() * collection.size());
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static<T> T oneOf( T... array ) {
|
||||
return array[(int)(Math.random() * array.length)];
|
||||
}
|
||||
|
||||
public static<T> T element( T[] array ) {
|
||||
return element( array, array.length );
|
||||
}
|
||||
|
||||
public static<T> T element( T[] array, int max ) {
|
||||
return array[(int)(Math.random() * max)];
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static<T> T element( Collection<? extends T> collection ) {
|
||||
int size = collection.size();
|
||||
return size > 0 ?
|
||||
(T)collection.toArray()[Int( size )] :
|
||||
null;
|
||||
}
|
||||
|
||||
public static<T> void shuffle( T[] array ) {
|
||||
for (int i=0; i < array.length - 1; i++) {
|
||||
int j = Int( i, array.length );
|
||||
if (j != i) {
|
||||
T t = array[i];
|
||||
array[i] = array[j];
|
||||
array[j] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static<U,V> void shuffle( U[] u, V[]v ) {
|
||||
for (int i=0; i < u.length - 1; i++) {
|
||||
int j = Int( i, u.length );
|
||||
if (j != i) {
|
||||
U ut = u[i];
|
||||
u[i] = u[j];
|
||||
u[j] = ut;
|
||||
|
||||
V vt = v[i];
|
||||
v[i] = v[j];
|
||||
v[j] = vt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
132
SPD-classes/src/main/java/com/watabou/utils/Rect.java
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
public class Rect {
|
||||
|
||||
public int left;
|
||||
public int top;
|
||||
public int right;
|
||||
public int bottom;
|
||||
|
||||
public Rect() {
|
||||
this( 0, 0, 0, 0 );
|
||||
}
|
||||
|
||||
public Rect( Rect rect ) {
|
||||
this( rect.left, rect.top, rect.right, rect.bottom );
|
||||
}
|
||||
|
||||
public Rect( int left, int top, int right, int bottom ) {
|
||||
this.left = left;
|
||||
this.top = top;
|
||||
this.right = right;
|
||||
this.bottom = bottom;
|
||||
}
|
||||
|
||||
public int width() {
|
||||
return right - left;
|
||||
}
|
||||
|
||||
public int height() {
|
||||
return bottom - top;
|
||||
}
|
||||
|
||||
public int square() {
|
||||
return (right - left) * (bottom - top);
|
||||
}
|
||||
|
||||
public Rect set( int left, int top, int right, int bottom ) {
|
||||
this.left = left;
|
||||
this.top = top;
|
||||
this.right = right;
|
||||
this.bottom = bottom;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Rect set( Rect rect ) {
|
||||
return set( rect.left, rect.top, rect.right, rect.bottom );
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return right <= left || bottom <= top;
|
||||
}
|
||||
|
||||
public Rect setEmpty() {
|
||||
left = right = top = bottom = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Rect intersect( Rect other ) {
|
||||
Rect result = new Rect();
|
||||
result.left = Math.max( left, other.left );
|
||||
result.right = Math.min( right, other.right );
|
||||
result.top = Math.max( top, other.top );
|
||||
result.bottom = Math.min( bottom, other.bottom );
|
||||
return result;
|
||||
}
|
||||
|
||||
public Rect union( int x, int y ) {
|
||||
if (isEmpty()) {
|
||||
return set( x, y, x + 1, y + 1 );
|
||||
} else {
|
||||
if (x < left) {
|
||||
left = x;
|
||||
} else if (x >= right) {
|
||||
right = x + 1;
|
||||
}
|
||||
if (y < top) {
|
||||
top = y;
|
||||
} else if (y >= bottom) {
|
||||
bottom = y + 1;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public Rect union( Point p ) {
|
||||
return union( p.x, p.y );
|
||||
}
|
||||
|
||||
public boolean inside( Point p ) {
|
||||
return p.x >= left && p.x < right && p.y >= top && p.y < bottom;
|
||||
}
|
||||
|
||||
public Rect shrink( int d ) {
|
||||
return new Rect( left + d, top + d, right - d, bottom - d );
|
||||
}
|
||||
|
||||
public Rect shrink() {
|
||||
return shrink( 1 );
|
||||
}
|
||||
|
||||
public HashSet<Point> getPoints() {
|
||||
HashSet<Point> points = new HashSet<>(square()*2);
|
||||
for (int i = left; i <= right; i++)
|
||||
for (int j = top; j <= bottom; j++)
|
||||
points.add(new Point(i, j));
|
||||
return points;
|
||||
}
|
||||
|
||||
}
|
96
SPD-classes/src/main/java/com/watabou/utils/Signal.java
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class Signal<T> {
|
||||
|
||||
private LinkedList<Listener<T>> listeners = new LinkedList<Signal.Listener<T>>();
|
||||
|
||||
private boolean canceled;
|
||||
|
||||
private boolean stackMode;
|
||||
|
||||
public Signal() {
|
||||
this( false );
|
||||
}
|
||||
|
||||
public Signal( boolean stackMode ) {
|
||||
this.stackMode = stackMode;
|
||||
}
|
||||
|
||||
public void add( Listener<T> listener ) {
|
||||
if (!listeners.contains( listener )) {
|
||||
if (stackMode) {
|
||||
listeners.addFirst( listener );
|
||||
} else {
|
||||
listeners.addLast( listener );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void remove( Listener<T> listener ) {
|
||||
listeners.remove( listener );
|
||||
}
|
||||
|
||||
public void removeAll() {
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
public void replace( Listener<T> listener ) {
|
||||
removeAll();
|
||||
add( listener );
|
||||
}
|
||||
|
||||
public int numListeners() {
|
||||
return listeners.size();
|
||||
}
|
||||
|
||||
public void dispatch( T t ) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Listener<T>[] list = listeners.toArray( new Listener[0] );
|
||||
|
||||
canceled = false;
|
||||
for (int i=0; i < list.length; i++) {
|
||||
|
||||
Listener<T> listener = list[i];
|
||||
|
||||
if (listeners.contains( listener )) {
|
||||
listener.onSignal( t );
|
||||
if (canceled) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
canceled = true;
|
||||
}
|
||||
|
||||
public static interface Listener<T> {
|
||||
public void onSignal( T t );
|
||||
}
|
||||
}
|
46
SPD-classes/src/main/java/com/watabou/utils/SparseArray.java
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SparseArray<T> extends android.util.SparseArray<T> {
|
||||
|
||||
public int[] keyArray() {
|
||||
int size = size();
|
||||
int[] array = new int[size];
|
||||
for (int i=0; i < size; i++) {
|
||||
array[i] = keyAt( i );
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public List<T> values() {
|
||||
int size = size();
|
||||
ArrayList<T> list = new ArrayList<T>( size );
|
||||
for (int i=0; i < size; i++) {
|
||||
list.add( i, valueAt( i ) );
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
32
SPD-classes/src/main/java/com/watabou/utils/SystemTime.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2016 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.watabou.utils;
|
||||
|
||||
public class SystemTime {
|
||||
|
||||
public static long now;
|
||||
|
||||
public static void tick() {
|
||||
now = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
3
SPD-classes/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">SPD-Classes</string>
|
||||
</resources>
|
14
build.gradle
Normal file
|
@ -0,0 +1,14 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.1.2'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
}
|
17
core/build.gradle
Normal file
|
@ -0,0 +1,17 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "24.0.0"
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':SPD-classes')
|
||||
}
|
21
core/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in C:\Program Files (x86)\Android\android-sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
-dontwarn **
|
||||
-keep class com.shatteredpixel.** { *; }
|
||||
-keep class com.watabou.** { *; }
|
Before Width: | Height: | Size: 578 B After Width: | Height: | Size: 578 B |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 516 B After Width: | Height: | Size: 516 B |
Before Width: | Height: | Size: 482 B After Width: | Height: | Size: 482 B |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1020 B After Width: | Height: | Size: 1020 B |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 123 B After Width: | Height: | Size: 123 B |