Changed path to de.frajul

This commit is contained in:
=
2017-05-25 13:51:15 +02:00
parent bf848cd46c
commit beb0a6e747
187 changed files with 12 additions and 18100 deletions

View File

@ -4,7 +4,7 @@ android {
compileSdkVersion 23
buildToolsVersion '25.0.0'
defaultConfig {
applicationId "com.example.particlelab"
applicationId "de.frajul.particlelab"
minSdkVersion 12
targetSdkVersion 23
versionCode 1

View File

@ -1,13 +0,0 @@
package com.example.particlelab;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

View File

@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.particlelab">
package="de.frajul.particlelab">
<uses-feature
android:glEsVersion="0x00020000"

View File

@ -1,69 +0,0 @@
package com.example.particlelab.data;
/**
* Created by Julian on 02.08.2016.
*/
public class Color {
private float r, g, b;
public Color() {
}
public Color(float r, float g, float b){
this.r = r;
this.g = g;
this.b = b;
}
public Color(Color other) {
this.r = other.getR();
this.g = other.getG();
this.b = other.getB();
}
public Color mix(float leftValue, float rightValue, Color color2) {
Color mySelf = new Color(this);
Color second = new Color(color2);
mySelf.mul(leftValue);
second.mul(rightValue);
mySelf.add(second);
return mySelf;
}
private void mul(float a) {
r *= a;
g *= a;
b *= a;
}
private void add(Color other) {
r += other.getR();
g += other.getG();
b += other.getB();
}
public float getR() {
return r;
}
public void setR(float r) {
this.r = r;
}
public float getG() {
return g;
}
public void setG(float g) {
this.g = g;
}
public float getB() {
return b;
}
public void setB(float b) {
this.b = b;
}
}

View File

@ -1,101 +0,0 @@
package com.example.particlelab.data;
/**
* Created by Julian on 01.12.2015.
*/
public class Vector {
public float x, y;
public Vector() {
this(0, 0);
}
public Vector(Vector other) {
this(other.x, other.y);
}
public Vector(float x, float y) {
set(x, y);
}
@Override
public String toString() {
return "Vector(" + x + ", " + y + ")";
}
public Vector set(float x, float y) {
this.x = x;
this.y = y;
return this;
}
public float length() {
return (float) Math.sqrt(x * x + y * y);
}
public Vector normalize() {
float length = this.length();
x /= length;
y /= length;
return this;
}
public Vector translate(Vector other) {
this.x += other.x;
this.y += other.y;
return this;
}
public Vector translate(float x, float y) {
this.x += x;
this.y += y;
return this;
}
public Vector mul(float z) {
x *= z;
y *= z;
return this;
}
public Vector mul(Vector other) {
this.x *= other.x;
this.y *= other.y;
return this;
}
public Vector mul(float x, float y) {
this.x *= x;
this.y *= y;
return this;
}
public Vector negate() {
this.x *= -1;
this.y *= -1;
return this;
}
public Vector vectorTo(Vector other) {
float x = other.x - this.x;
float y = other.y - this.y;
return new Vector(x, y);
}
public void setX(float x) {
this.x = x;
}
public void setY(float y) {
this.y = y;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
}

View File

@ -1,80 +0,0 @@
package com.example.particlelab.entities;
import com.example.particlelab.data.Color;
import com.example.particlelab.entities.textures.Texture;
import com.example.particlelab.data.Vector;
/**
* Created by Julian on 20.11.2015.
*/
public class Entity extends Quad {
private Color color;
private Texture texture;
private Vector movement;
private float rotation;
private float dynamicRotation;
private float alpha = 1.0f;
private boolean destroyed;
public Entity(Texture texture, Vector position, float width, float height) {
super(position, width, height);
this.texture = texture;
this.movement = new Vector();
}
public Entity(Texture texture, Color color, Vector position, float width, float height) {
super(position, width, height);
this.texture = texture;
this.color = color;
this.movement = new Vector();
}
public void move(Vector movement) {
position.translate(movement);
}
public void rotate(float factor) {
rotation += factor;
}
public Texture getTexture() {
return texture;
}
public void setTexture(Texture texture) {
this.texture = texture;
}
public Vector getMovement() {
return movement;
}
public void setMovement(Vector movement) {
this.movement = movement;
}
public float getRotation() {
return rotation;
}
public void setRotation(float rotation) {
this.rotation = rotation;
}
public void setAlpha(float alpha) {
this.alpha = alpha;
}
public float getAlpha() {
return alpha;
}
public void setColor(Color color) {
this.color = color;
}
public Color getColor() {
return color;
}
}

View File

@ -1,59 +0,0 @@
package com.example.particlelab.entities;
import com.example.particlelab.data.Vector;
/**
* Created by Julian on 01.12.2015.
*/
public class Quad {
protected Vector position;
protected float width, height;
public Quad(Vector position, float width, float height) {
this.position = position;
this.width = width;
this.height = height;
}
public float getRightEdge() {
return position.x + width / 2;
}
public float getLeftEdge() {
return position.x - width / 2;
}
public float getTopEdge() {
return position.y + height / 2;
}
public float getBottomEdge() {
return position.y - height / 2;
}
public Vector getPosition() {
return position;
}
public void setPosition(Vector position) {
this.position = position;
}
public float getWidth() {
return width;
}
public void setWidth(float width) {
this.width = width;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
}

View File

@ -1,89 +0,0 @@
package com.example.particlelab.entities.particles;
import com.example.particlelab.data.Vector;
import com.example.particlelab.entities.Entity;
import com.example.particlelab.entities.particles.attributes.attributeValues.Range;
import com.example.particlelab.entities.particles.attributes.attributeValues.Timeline;
import com.example.particlelab.entities.particles.attributes.attributeValues.TintTimeline;
import com.example.particlelab.main.GameLog;
import com.example.particlelab.rendering.Timer;
import java.util.Random;
/**
* Created by Julian on 02.08.2016.
*/
public class Particle extends Entity {
private Random random;
private boolean active;
private float maxLife;
private float passedLifetime;
private Timeline scaleTimeline;
private Range scale;
private Timeline velocityTimeline;
private Range velocity;
private Timeline angleTimeline;
private Range angle;
private Timeline rotationTimeline;
private Range rotation;
private Timeline transparencyTimeline;
private TintTimeline tintTimeline;
public Particle(Random random) {
super(null, new Vector(), 1, 1);
this.random = random;
}
public void activate(Vector position, float liveValue, ParticleData particleData) {
active = true;
passedLifetime = 0;
super.setPosition(position);
maxLife = particleData.getLife().createValue(random, liveValue);
scaleTimeline = particleData.getScaleTR().getTimeline();
scale = particleData.getScaleTR().getRange().createNormalizedInstance(random);
velocityTimeline = particleData.getVelocityTR().getTimeline();
velocity = particleData.getVelocityTR().getRange().createNormalizedInstance(random);
angleTimeline = particleData.getAngleTR().getTimeline();
angle = particleData.getAngleTR().getRange().createNormalizedInstance(random);
rotationTimeline = particleData.getRotationTR().getTimeline();
rotation = particleData.getRotationTR().getRange().createNormalizedInstance(random);
transparencyTimeline = particleData.getTransparencyT();
tintTimeline = particleData.getTint();
}
public void update(Timer timer, float windStrength, float gravityStrength) {
if (active) {
passedLifetime += timer.getFrameTime();
if (passedLifetime >= maxLife)
active = false;
float lifetimePercent = passedLifetime / maxLife;
setScale(scale.createValue(random, scaleTimeline.getValueAtTime(lifetimePercent)));
setMovement(velocity.createValue(random, velocityTimeline.getValueAtTime(lifetimePercent)),
angle.createValue(random, angleTimeline.getValueAtTime(lifetimePercent)), windStrength, gravityStrength);
super.setRotation(-rotation.createValue(random, rotationTimeline.getValueAtTime(lifetimePercent)));
super.setAlpha(transparencyTimeline.getValueAtTime(lifetimePercent));
super.setColor(tintTimeline.getValueAtTime(lifetimePercent));
}
}
private void setScale(float scale) {
super.setWidth(scale * ParticleSystem.TRANSFER_VALUE);
super.setHeight(scale * ParticleSystem.TRANSFER_VALUE);
}
private void setMovement(float velocity, float angle, float windStrength, float gravityStrength) {
float radians = (float) Math.toRadians(angle);
Vector normalMovement = new Vector();
normalMovement.setX((float) Math.cos(radians));
normalMovement.setY((float) Math.sin(radians));
normalMovement.mul(velocity * ParticleSystem.TRANSFER_VALUE);
normalMovement.translate(windStrength * ParticleSystem.TRANSFER_VALUE, gravityStrength * ParticleSystem.TRANSFER_VALUE);
super.setMovement(normalMovement);
}
public boolean isActive() {
return active;
}
}

View File

@ -1,59 +0,0 @@
package com.example.particlelab.entities.particles;
import com.example.particlelab.entities.particles.attributes.attributeValues.Range;
import com.example.particlelab.entities.particles.attributes.attributeValues.Timeline;
import com.example.particlelab.entities.particles.attributes.attributeValues.TimelineRange;
import com.example.particlelab.entities.particles.attributes.attributeValues.TintTimeline;
import com.example.particlelab.entities.textures.Texture;
/**
* Created by Julian on 03.08.2016.
*/
public class ParticleData {
private Range life;
private TimelineRange scaleTR;
private TimelineRange velocityTR;
private TimelineRange angleTR;
private TimelineRange rotationTR;
private Timeline transparencyT;
private TintTimeline tint;
public ParticleData(Range life, TimelineRange scaleTR, TimelineRange velocityTR, TimelineRange angleTR, TimelineRange rotationTR, Timeline transparencyT, TintTimeline tint) {
this.life = life;
this.scaleTR = scaleTR;
this.velocityTR = velocityTR;
this.angleTR = angleTR;
this.rotationTR = rotationTR;
this.transparencyT = transparencyT;
this.tint = tint;
}
public Range getLife() {
return life;
}
public TimelineRange getScaleTR() {
return scaleTR;
}
public TimelineRange getVelocityTR() {
return velocityTR;
}
public TimelineRange getAngleTR() {
return angleTR;
}
public TimelineRange getRotationTR() {
return rotationTR;
}
public Timeline getTransparencyT() {
return transparencyT;
}
public TintTimeline getTint() {
return tint;
}
}

View File

@ -1,218 +0,0 @@
package com.example.particlelab.entities.particles;
import com.example.particlelab.entities.particles.attributes.attributeValues.Options;
import com.example.particlelab.entities.particles.attributes.attributeValues.Range;
import com.example.particlelab.entities.particles.attributes.attributeValues.SpawnShape;
import com.example.particlelab.entities.particles.attributes.attributeValues.Timeline;
import com.example.particlelab.entities.particles.attributes.attributeValues.TimelineRange;
import com.example.particlelab.entities.particles.attributes.attributeValues.TintTimeline;
import com.example.particlelab.entities.textures.Texture;
import com.example.particlelab.rendering.Timer;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* Created by Julian on 05.08.2016.
*/
public class ParticleEffect {
private TimelineRange life;
//Particle Timeline
private TimelineRange scale;
private TimelineRange velocity;
private TimelineRange angle;
private TimelineRange rotation;
private Timeline transparency;
private TintTimeline tint;
//Source Timeline
private Range delay;
private Range duration;
private TimelineRange emission;
private Range xOffset;
private Range yOffset;
private SpawnShape.Shape spawnShape;
private TimelineRange spawnWidth;
private TimelineRange spawnHeight;
private TimelineRange wind;
private TimelineRange gravity;
private Options options;
private Texture texture;
private String textureName;
private Random random;
private List<ParticleSource> sources = new ArrayList<>();
public ParticleEffect() {
this.random = new Random();
}
public void update(Timer timer) {
for (ParticleSource source : sources)
source.update(timer);
}
public ParticleData createParticleData(){
return new ParticleData(life.getRange(), scale, velocity, angle, rotation, transparency, tint);
}
public Random getRandom() {
return random;
}
public void addSource(ParticleSource source) {
sources.add(source);
}
public void setDelay(Range delay) {
this.delay = delay;
}
public void setDuration(Range duration) {
this.duration = duration;
}
public void setEmission(TimelineRange emission) {
this.emission = emission;
}
public void setLife(TimelineRange life) {
this.life = life;
}
public void setxOffset(Range xOffset) {
this.xOffset = xOffset;
}
public void setyOffset(Range yOffset) {
this.yOffset = yOffset;
}
public void setSpawnShape(SpawnShape.Shape spawnShape) {
this.spawnShape = spawnShape;
}
public void setSpawnWidth(TimelineRange spawnWidth) {
this.spawnWidth = spawnWidth;
}
public void setSpawnHeight(TimelineRange spawnHeight) {
this.spawnHeight = spawnHeight;
}
public void setScale(TimelineRange scale) {
this.scale = scale;
}
public void setVelocity(TimelineRange velocity) {
this.velocity = velocity;
}
public void setAngle(TimelineRange angle) {
this.angle = angle;
}
public void setRotation(TimelineRange rotation) {
this.rotation = rotation;
}
public void setWind(TimelineRange wind) {
this.wind = wind;
}
public void setGravity(TimelineRange gravity) {
this.gravity = gravity;
}
public void setTint(TintTimeline tint) {
this.tint = tint;
}
public void setTransparency(Timeline transparency) {
this.transparency = transparency;
}
public Timeline getTransparency() {
return transparency;
}
public TintTimeline getTint() {
return tint;
}
public void setOptions(Options options) {
this.options = options;
}
public void setTexture(Texture texture) {
this.texture = texture;
}
public void setTextureName(String textureName) {
this.textureName = textureName;
}
public String getTextureName() {
return textureName;
}
public Texture getTexture() {
return texture;
}
public Range getDelay() {
return delay;
}
public Range getDuration() {
return duration;
}
public TimelineRange getEmission() {
return emission;
}
public Options getOptions() {
return options;
}
public TimelineRange getWind() {
return wind;
}
public TimelineRange getGravity() {
return gravity;
}
public Range getxOffset() {
return xOffset;
}
public Range getyOffset() {
return yOffset;
}
public List<ParticleSource> getSources() {
return sources;
}
public TimelineRange getLife() {
return life;
}
public SpawnShape.Shape getSpawnShape() {
return spawnShape;
}
public TimelineRange getSpawnHeight() {
return spawnHeight;
}
public TimelineRange getSpawnWidth() {
return spawnWidth;
}
}

View File

@ -1,164 +0,0 @@
package com.example.particlelab.entities.particles;
import android.content.Context;
import com.example.particlelab.entities.particles.attributes.Attribute;
import com.example.particlelab.entities.particles.attributes.AttributeValueReader;
import com.example.particlelab.entities.particles.attributes.ParticleAttributeType;
import com.example.particlelab.entities.particles.attributes.attributeValues.ImagePath;
import com.example.particlelab.entities.particles.attributes.attributeValues.Options;
import com.example.particlelab.entities.particles.attributes.attributeValues.ParticleAttributeValueType;
import com.example.particlelab.entities.particles.attributes.attributeValues.Range;
import com.example.particlelab.entities.particles.attributes.attributeValues.SpawnShape;
import com.example.particlelab.entities.particles.attributes.attributeValues.Timeline;
import com.example.particlelab.entities.particles.attributes.attributeValues.TimelineRange;
import com.example.particlelab.entities.particles.attributes.attributeValues.TintTimeline;
import com.example.particlelab.main.GameLog;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Julian on 02.08.2016.
*/
public class ParticleReader {
private Context context;
private AttributeValueReader attributeValueReader;
private List<Attribute> attributes;
private Attribute currentAttribute;
public ParticleReader(Context context) {
this.context = context;
attributeValueReader = new AttributeValueReader();
}
/**
* reads ParticleEffect from *.pe files
* !Ignores COUNT, LIFE_OFFSET!
*/
public ParticleEffect read(String filename) throws Exception {
try {
attributes = new ArrayList<>();
currentAttribute = null;
InputStream is = context.getAssets().open(filename);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
handleLine(line);
}
reader.close();
return createParticleEffect();
} catch (Exception e) {
throw new Exception("Could not read particleFile: ", e);
}
}
private void handleLine(String line) throws Exception {
if (line.startsWith("- ")) {
Attribute attrib = ParticleAttributeType.getByInFileTitle(line).createInstance();
attributes.add(attrib);
currentAttribute = attrib;
} else if (currentAttribute != null)
attributeValueReader.addValueForAttribute(currentAttribute, line);
}
private ParticleEffect createParticleEffect() throws Exception {
ParticleEffect effect = new ParticleEffect();
Timeline timeline = null;
Range range = null;
for (Attribute attribute : attributes) {
switch (attribute.getType()) {
case DELAY:
effect.setDelay((Range) attribute.get(ParticleAttributeValueType.RANGE));
break;
case DURATION:
effect.setDuration((Range) attribute.get(ParticleAttributeValueType.RANGE));
break;
case COUNT:
break;
case EMISSION:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setEmission(new TimelineRange(timeline, range));
break;
case LIFE:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setLife(new TimelineRange(timeline, range));
break;
case LIFE_OFFSET:
break;
case X_OFFSET:
effect.setxOffset((Range) attribute.get(ParticleAttributeValueType.RANGE));
break;
case Y_OFFSET:
effect.setyOffset((Range) attribute.get(ParticleAttributeValueType.RANGE));
break;
case SPAWN_SHAPE:
effect.setSpawnShape(((SpawnShape) attribute.get(ParticleAttributeValueType.SPAWN_SHAPE)).getShape());
break;
case SPAWN_WIDTH:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setSpawnWidth(new TimelineRange(timeline, range));
break;
case SPAWN_HEIGHT:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setSpawnHeight(new TimelineRange(timeline, range));
break;
case SCALE:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setScale(new TimelineRange(timeline, range));
break;
case VELOCITY:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setVelocity(new TimelineRange(timeline, range));
break;
case ANGLE:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setAngle(new TimelineRange(timeline, range));
break;
case ROTATION:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setRotation(new TimelineRange(timeline, range));
break;
case WIND:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setWind(new TimelineRange(timeline, range));
break;
case GRAVITY:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setGravity(new TimelineRange(timeline, range));
break;
case TINT:
effect.setTint((TintTimeline) attribute.get(ParticleAttributeValueType.TINT_TIMELINE));
break;
case TRANSPARENCY:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
effect.setTransparency(timeline);
break;
case OPTIONS:
effect.setOptions((Options) attribute.get(ParticleAttributeValueType.OPTIONS));
break;
case IMAGE_PATH:
String path = ((ImagePath) attribute.get(ParticleAttributeValueType.IMAGE_PATH)).getImagePath();
effect.setTextureName(path);
break;
}
}
return effect;
}
}

View File

@ -1,150 +0,0 @@
package com.example.particlelab.entities.particles;
import com.example.particlelab.data.Vector;
import com.example.particlelab.entities.particles.attributes.attributeValues.SpawnShape;
import com.example.particlelab.main.GameLog;
import com.example.particlelab.rendering.Lock;
import com.example.particlelab.rendering.Timer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
/**
* Created by Julian on 02.08.2016.
*/
public class ParticleSource {
private Vector position;
private ParticleEffect effect;
private Random random;
private boolean alife;
private float currentDelay;
private float lifePercent;
private float maxTime = -1;
private float passedTime;
private float emittPause;
private float passedEmittPause;
private float passedSecond;
private float windStrength;
private float gravityStrength;
private Vector spawnSize = null;
private ParticleData particleData;
private List<Particle> activeParticles = new ArrayList<>();
private List<Particle> inactiveParticles = new ArrayList<>();
private Lock activeParticleLock = new Lock();
public ParticleSource(Vector position, ParticleEffect effect) {
this.position = position;
this.effect = effect;
random = effect.getRandom();
effect.addSource(this);
}
public void start() {
alife = true;
currentDelay = effect.getDelay().createValue(random, 0);
maxTime = effect.getDuration().createValue(random, 0) + currentDelay;
passedTime = 0;
emittPause = calcEmittPause();
passedEmittPause = 0;
passedSecond = 0;
lifePercent = 0;
}
public void update(Timer timer) {
if (alife) {
passedTime += timer.getFrameTime();
lifePercent = passedTime / maxTime;
if (passedTime >= currentDelay) {
passedEmittPause += timer.getFrameTime();
calcWindAndGravity();
while (passedEmittPause >= emittPause) {
passedEmittPause -= emittPause;
emitt();
}
passedSecond += timer.getFrameTime();
if (passedSecond >= 1000) {
passedSecond -= 1000;
calcEmittPause();
}
}
if (passedTime >= maxTime)
die();
}
updateParticles(timer);
}
private void updateParticles(Timer timer) {
activeParticleLock.lock();
Iterator<Particle> iter = activeParticles.iterator();
while (iter.hasNext()) {
Particle particle = iter.next();
particle.update(timer, windStrength, gravityStrength);
if (!particle.isActive()) {
inactiveParticles.add(particle);
iter.remove();
} else {
particle.move(new Vector(particle.getMovement()).mul(timer.getFrameTime() / 1000));
}
}
activeParticleLock.unlock();
}
private void die() {
alife = false;
if (effect.getOptions().isContinuous())
start();
}
public void emitt() {
if (particleData == null)
particleData = effect.createParticleData();
float xOff = effect.getxOffset().createValue(random, 0) * ParticleSystem.TRANSFER_VALUE;
float yOff = effect.getyOffset().createValue(random, 0) * ParticleSystem.TRANSFER_VALUE;
if (effect.getSpawnShape() == SpawnShape.Shape.SQUARE) {
float width = effect.getSpawnWidth().getRange().createValue(random, effect.getSpawnWidth().getTimeline().getValueAtTime(lifePercent));
float height = effect.getSpawnHeight().getRange().createValue(random, effect.getSpawnHeight().getTimeline().getValueAtTime(lifePercent));
xOff += (random.nextFloat() * width - width * 0.5f)*ParticleSystem.TRANSFER_VALUE;
yOff += (random.nextFloat() * height - height * 0.5f)*ParticleSystem.TRANSFER_VALUE;
}
setUpParticle(new Vector(position).translate(xOff, yOff));
}
private Particle setUpParticle(Vector position) {
Particle particle;
if (inactiveParticles.size() > 0)
particle = inactiveParticles.remove(0);
else
particle = new Particle(random);
particle.activate(position, effect.getLife().getTimeline().getValueAtTime(lifePercent), particleData);
activeParticleLock.lock();
activeParticles.add(particle);
activeParticleLock.unlock();
return particle;
}
private void calcWindAndGravity() {
windStrength = effect.getWind().getRange().createValue(random, effect.getWind().getTimeline().getValueAtTime(lifePercent));
gravityStrength = effect.getGravity().getRange().createValue(random, effect.getGravity().getTimeline().getValueAtTime(lifePercent));
}
private float calcEmittPause() {
float emittedPerSecond = effect.getEmission().getRange().createValue(random, effect.getEmission().getTimeline().getValueAtTime(passedTime / maxTime));
return 1000 / emittedPerSecond;
}
public Lock getActiveParticleLock() {
return activeParticleLock;
}
public List<Particle> getActiveParticles() {
return activeParticles;
}
}

View File

@ -1,40 +0,0 @@
package com.example.particlelab.entities.particles;
import android.content.Context;
import com.example.particlelab.entities.textures.TextureLoader;
import com.example.particlelab.rendering.Timer;
/**
* Created by Julian on 02.08.2016.
*/
public class ParticleSystem {
public static final float TRANSFER_VALUE = 0.002f;
public final ParticleEffect explosion;
private ParticleEffect[] effects;
private TextureLoader textureLoader;
public ParticleSystem(Context context) throws Exception {
this.textureLoader = new TextureLoader(context);
ParticleReader reader = new ParticleReader(context);
explosion = reader.read("explosion.pe");
effects = new ParticleEffect[]{explosion};
}
public void update(Timer timer) {
for (ParticleEffect effect : effects)
effect.update(timer);
}
public void loadTextures() throws Exception {
for (ParticleEffect effect : effects)
effect.setTexture(textureLoader.loadTexture(effect.getTextureName()));
}
public ParticleEffect[] getEffects() {
return effects;
}
}

View File

@ -1,33 +0,0 @@
package com.example.particlelab.entities.particles.attributes;
import com.example.particlelab.entities.particles.attributes.attributeValues.ParticleAttributeValue;
import com.example.particlelab.entities.particles.attributes.attributeValues.ParticleAttributeValueType;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Julian on 02.08.2016.
*/
public class Attribute {
private ParticleAttributeType type;
private List<ParticleAttributeValue> values = new ArrayList<>();
public Attribute(ParticleAttributeType type, ParticleAttributeValueType... valueTypes) {
this.type = type;
for (ParticleAttributeValueType valueType : valueTypes)
values.add(valueType.createInstance());
}
public ParticleAttributeValue get(ParticleAttributeValueType valueType) throws Exception {
for (ParticleAttributeValue v : values)
if (v.getType() == valueType)
return v;
throw new Exception("ParticleAttributeValue with type: " + valueType + " does not exist in Attribute "+type);
}
public ParticleAttributeType getType() {
return type;
}
}

View File

@ -1,77 +0,0 @@
package com.example.particlelab.entities.particles.attributes;
import com.example.particlelab.entities.particles.attributes.attributeValues.ImagePath;
import com.example.particlelab.entities.particles.attributes.attributeValues.Options;
import com.example.particlelab.entities.particles.attributes.attributeValues.ParticleAttributeValueType;
import com.example.particlelab.entities.particles.attributes.attributeValues.Range;
import com.example.particlelab.entities.particles.attributes.attributeValues.SpawnShape;
import com.example.particlelab.entities.particles.attributes.attributeValues.Timeline;
import com.example.particlelab.entities.particles.attributes.attributeValues.TintTimeline;
/**
* Created by Julian on 02.08.2016.
*/
public class AttributeValueReader {
public void addValueForAttribute(Attribute attribute, String line) throws Exception {
//RANGE
if (line.startsWith("lowMin:") || line.startsWith("min:"))
((Range) attribute.get(ParticleAttributeValueType.RANGE)).setLowMin(parseFloat(line));
else if (line.startsWith("lowMax:") || line.startsWith("max:"))
((Range) attribute.get(ParticleAttributeValueType.RANGE)).setLowMax(parseFloat(line));
else if (line.startsWith("highMin:"))
((Range) attribute.get(ParticleAttributeValueType.RANGE)).setHighMin(parseFloat(line));
else if (line.startsWith("highMax:"))
((Range) attribute.get(ParticleAttributeValueType.RANGE)).setHighMax(parseFloat(line));
//TIMELINE
else if (!line.startsWith("scalingCount") && line.startsWith("scaling"))
((Timeline) attribute.get(ParticleAttributeValueType.TIMELINE)).setValueOfPoint(parseTimeLineIndex("scaling", line), parseFloat(line));
else if (!line.startsWith("timelineCount") && line.startsWith("timeline") && attribute.getType() != ParticleAttributeType.TINT)
((Timeline) attribute.get(ParticleAttributeValueType.TIMELINE)).setTimeOfPoint(parseTimeLineIndex("timeline", line), parseFloat(line));
//TINT_TIMELINE
else if (!line.startsWith("colorsCount") && line.startsWith("colors")) {
int index = parseTimeLineIndex("colors", line);
((TintTimeline) attribute.get(ParticleAttributeValueType.TINT_TIMELINE)).setValueOfPoint((int) (index / 3f), index % 3, parseFloat(line));
} else if (!line.startsWith("timelineCount") && line.startsWith("timeline") && attribute.getType() == ParticleAttributeType.TINT)
((TintTimeline) attribute.get(ParticleAttributeValueType.TINT_TIMELINE)).setTimeOfPoint(parseTimeLineIndex("timeline", line), parseFloat(line));
//SPAWN_SHAPE
else if (line.startsWith("shape:"))
((SpawnShape) attribute.get(ParticleAttributeValueType.SPAWN_SHAPE)).setShape(SpawnShape.Shape.byName(parseString(line)));
//OPTIONS
else if (line.startsWith("attached:"))
((Options) attribute.get(ParticleAttributeValueType.OPTIONS)).setAttached(parseBoolean(line));
else if (line.startsWith("continuous:"))
((Options) attribute.get(ParticleAttributeValueType.OPTIONS)).setContinuous(parseBoolean(line));
else if (line.startsWith("aligned:"))
((Options) attribute.get(ParticleAttributeValueType.OPTIONS)).setAligned(parseBoolean(line));
else if (line.startsWith("additive:"))
((Options) attribute.get(ParticleAttributeValueType.OPTIONS)).setAdditive(parseBoolean(line));
else if (line.startsWith("behind:"))
((Options) attribute.get(ParticleAttributeValueType.OPTIONS)).setBehind(parseBoolean(line));
else if (line.startsWith("premultipliedAlpha:"))
((Options) attribute.get(ParticleAttributeValueType.OPTIONS)).setPremultipliedAlpha(parseBoolean(line));
//IMAGE PATH
else if (attribute.getType() == ParticleAttributeType.IMAGE_PATH)
((ImagePath) attribute.get(ParticleAttributeValueType.IMAGE_PATH)).setImagePath(line);
}
private int parseTimeLineIndex(String start, String line) throws Exception {
String asString = line.split(start)[1].split(":")[0];
return Integer.parseInt(asString);
}
private float parseFloat(String line) throws Exception {
String asString = line.split(" ")[1];
return Float.parseFloat(asString);
}
private String parseString(String line) throws Exception {
return line.split(" ")[1];
}
private boolean parseBoolean(String line) throws Exception {
String asString = line.split(" ")[1];
return Boolean.parseBoolean(asString);
}
}

View File

@ -1,55 +0,0 @@
package com.example.particlelab.entities.particles.attributes;
import com.example.particlelab.entities.particles.attributes.attributeValues.ParticleAttributeValueType;
public enum ParticleAttributeType {
NONE(""),
DELAY("Delay", ParticleAttributeValueType.RANGE),
DURATION("Duration", ParticleAttributeValueType.RANGE),
COUNT("Count", ParticleAttributeValueType.RANGE),
EMISSION("Emission", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
LIFE("Life", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
LIFE_OFFSET("Life Offset", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
X_OFFSET("X Offset", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
Y_OFFSET("Y Offset", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
SPAWN_SHAPE("Spawn Shape", ParticleAttributeValueType.SPAWN_SHAPE),
SPAWN_WIDTH("Spawn Width", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
SPAWN_HEIGHT("Spawn Height", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
SCALE("Scale", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
VELOCITY("Velocity", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
ANGLE("Angle", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
ROTATION("Rotation", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
WIND("Wind", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
GRAVITY("Gravity", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
TINT("Tint", ParticleAttributeValueType.TINT_TIMELINE),
TRANSPARENCY("Transparency", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
OPTIONS("Options", ParticleAttributeValueType.OPTIONS),
IMAGE_PATH("Image Path", ParticleAttributeValueType.IMAGE_PATH);
private String name;
private ParticleAttributeValueType[] valueTypes;
ParticleAttributeType(String name, ParticleAttributeValueType... valueTypes) {
this.name = name;
this.valueTypes = valueTypes;
}
private String getInFileTitle() {
return "- " + name + " -";
}
public static ParticleAttributeType getByInFileTitle(String title) throws Exception {
for (ParticleAttributeType setting : values()) {
if (setting != NONE && setting.getInFileTitle().equals(title))
return setting;
}
throw new Exception("Could not find ParticleAttributeType by title: " + title);
}
public Attribute createInstance() throws Exception {
if (this == NONE)
throw new Exception("Cannot create Instance from Attribute NONE");
return new Attribute(this, valueTypes);
}
}

View File

@ -1,21 +0,0 @@
package com.example.particlelab.entities.particles.attributes.attributeValues;
/**
* Created by Julian on 02.08.2016.
*/
public class ImagePath extends ParticleAttributeValue {
private String imagePath;
public ImagePath() {
super(ParticleAttributeValueType.IMAGE_PATH);
}
public String getImagePath() {
return imagePath;
}
public void setImagePath(String imagePath) {
this.imagePath = imagePath;
}
}

View File

@ -1,66 +0,0 @@
package com.example.particlelab.entities.particles.attributes.attributeValues;
/**
* Created by Julian on 02.08.2016.
*/
public class Options extends ParticleAttributeValue {
private boolean attached;
private boolean continuous;
private boolean aligned;
private boolean additive;
private boolean behind;
private boolean premultipliedAlpha;
public Options() {
super(ParticleAttributeValueType.OPTIONS);
}
public boolean isAttached() {
return attached;
}
public void setAttached(boolean attached) {
this.attached = attached;
}
public boolean isContinuous() {
return continuous;
}
public void setContinuous(boolean continuous) {
this.continuous = continuous;
}
public boolean isAligned() {
return aligned;
}
public void setAligned(boolean aligned) {
this.aligned = aligned;
}
public boolean isAdditive() {
return additive;
}
public void setAdditive(boolean additive) {
this.additive = additive;
}
public boolean isBehind() {
return behind;
}
public void setBehind(boolean behind) {
this.behind = behind;
}
public boolean isPremultipliedAlpha() {
return premultipliedAlpha;
}
public void setPremultipliedAlpha(boolean premultipliedAlpha) {
this.premultipliedAlpha = premultipliedAlpha;
}
}

View File

@ -1,17 +0,0 @@
package com.example.particlelab.entities.particles.attributes.attributeValues;
/**
* Created by Julian on 02.08.2016.
*/
public abstract class ParticleAttributeValue {
private ParticleAttributeValueType type;
public ParticleAttributeValue(ParticleAttributeValueType type){
this.type = type;
}
public ParticleAttributeValueType getType() {
return type;
}
}

View File

@ -1,28 +0,0 @@
package com.example.particlelab.entities.particles.attributes.attributeValues;
/**
* Created by Julian on 02.08.2016.
*/
public enum ParticleAttributeValueType {
RANGE, TIMELINE, TINT_TIMELINE, SPAWN_SHAPE, OPTIONS, IMAGE_PATH;
public ParticleAttributeValue createInstance(){
switch (this){
case RANGE:
return new Range();
case TIMELINE:
return new Timeline();
case TINT_TIMELINE:
return new TintTimeline();
case SPAWN_SHAPE:
return new SpawnShape();
case OPTIONS:
return new Options();
case IMAGE_PATH:
return new ImagePath();
}
return null;
}
}

View File

@ -1,82 +0,0 @@
package com.example.particlelab.entities.particles.attributes.attributeValues;
import java.util.Random;
/**
* Created by Julian on 02.08.2016.
*/
public class Range extends ParticleAttributeValue {
private float lowMin;
private float lowMax;
private float highMin;
private float highMax;
public Range() {
super(ParticleAttributeValueType.RANGE);
}
public Range createNormalizedInstance(Random random) {
Range range = new Range();
float high = createHighValue(random);
range.setHighMax(high);
range.setHighMin(high);
float low = createLowValue(random);
range.setLowMax(low);
range.setLowMin(low);
return range;
}
public float createValue(Random random, float mix) {
if (mix == 1)
return createHighValue(random);
else if (mix == 0)
return createLowValue(random);
else {
float highValue = createHighValue(random);
float lowValue = createLowValue(random);
return mix * (highValue - lowValue) + lowValue;
}
}
private float createHighValue(Random random) {
float min = highMin;
float max = highMax;
if (min == max)
return min;
return random.nextFloat() * (max - min) + min;
}
private float createLowValue(Random random) {
float min = lowMin;
float max = lowMax;
if (min == max)
return min;
return random.nextFloat() * (max - min) + min;
}
public void setLowMin(float lowMin) {
this.lowMin = lowMin;
}
public void setLowMax(float lowMax) {
this.lowMax = lowMax;
}
public void setHighMin(float highMin) {
this.highMin = highMin;
}
public void setHighMax(float highMax) {
this.highMax = highMax;
}
private boolean isLowDifference() {
return lowMin - lowMax != 0;
}
private boolean isHighDifference() {
return highMin - highMax != 0;
}
}

View File

@ -1,38 +0,0 @@
package com.example.particlelab.entities.particles.attributes.attributeValues;
/**
* Created by Julian on 02.08.2016.
*/
public class SpawnShape extends ParticleAttributeValue {
public enum Shape {
POINT("point"), SQUARE("square");
private String name;
Shape(String name) {
this.name = name;
}
public static Shape byName(String text) throws Exception{
for(Shape shape : values())
if(shape.name.equals(text))
return shape;
throw new Exception("Shape with name \""+text+"\" does not exist");
}
}
private Shape shape;
public SpawnShape() {
super(ParticleAttributeValueType.SPAWN_SHAPE);
}
public Shape getShape() {
return shape;
}
public void setShape(Shape shape) {
this.shape = shape;
}
}

View File

@ -1,52 +0,0 @@
package com.example.particlelab.entities.particles.attributes.attributeValues;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Julian on 02.08.2016.
*/
public class Timeline extends ParticleAttributeValue {
private List<TimelinePoint> points = new ArrayList<>();
public Timeline() {
super(ParticleAttributeValueType.TIMELINE);
}
public void setValueOfPoint(int index, float value) {
if (points.size() <= index) {
points.add(new TimelinePoint());
}
points.get(index).setValue(value);
}
public void setTimeOfPoint(int index, float time) {
if (points.size() <= index) {
points.add(new TimelinePoint());
}
points.get(index).setTime(time);
}
public float getValueAtTime(float time) {
TimelinePoint left = null, right = null;
for (TimelinePoint point : points) {
if (point.getTime() <= time) {
if (left == null || left.getTime() < point.getTime())
left = point;
} else if (right == null || right.getTime() > point.getTime())
right = point;
}
if (left != null) {
if (right != null) {
float leftDist = 1 - Math.abs(left.getTime() - time);
float rightDist = 1 - Math.abs(right.getTime() - time);
float totalDist = leftDist + rightDist;
return left.getValue() * (leftDist / totalDist) + right.getValue() * (rightDist / totalDist);
}
return left.getValue();
}
return 0;
}
}

View File

@ -1,23 +0,0 @@
package com.example.particlelab.entities.particles.attributes.attributeValues;
public class TimelinePoint {
private float time, value;
public float getTime() {
return time;
}
public void setTime(float time) {
this.time = time;
}
public float getValue() {
return value;
}
public void setValue(float value) {
this.value = value;
}
}

View File

@ -1,34 +0,0 @@
package com.example.particlelab.entities.particles.attributes.attributeValues;
import com.example.particlelab.entities.particles.attributes.attributeValues.Range;
import com.example.particlelab.entities.particles.attributes.attributeValues.Timeline;
/**
* Created by Julian on 02.08.2016.
*/
public class TimelineRange {
private Timeline timeline;
private Range range;
public TimelineRange(Timeline timeline, Range range) {
this.timeline = timeline;
this.range = range;
}
public Timeline getTimeline() {
return timeline;
}
public void setTimeline(Timeline timeline) {
this.timeline = timeline;
}
public Range getRange() {
return range;
}
public void setRange(Range range) {
this.range = range;
}
}

View File

@ -1,57 +0,0 @@
package com.example.particlelab.entities.particles.attributes.attributeValues;
import com.example.particlelab.data.Color;
import com.example.particlelab.main.GameLog;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Julian on 02.08.2016.
*/
public class TintTimeline extends ParticleAttributeValue {
private List<TintTimelinePoint> points = new ArrayList<>();
public TintTimeline() {
super(ParticleAttributeValueType.TINT_TIMELINE);
}
public void setValueOfPoint(int index, int colorIndex, float value) {
GameLog.i("Set value: index="+index+"; colorIndex="+colorIndex+"; value="+value);
if (points.size() <= index) {
points.add(new TintTimelinePoint());
}
points.get(index).setValue(colorIndex, value);
}
public void setTimeOfPoint(int index, float time) {
GameLog.i("Set time: index="+index+"; time="+time);
if (points.size() <= index) {
points.add(new TintTimelinePoint());
}
points.get(index).setTime(time);
}
public Color getValueAtTime(float time) {
TintTimelinePoint left = null, right = null;
for (TintTimelinePoint point : points) {
if (point.getTime() <= time) {
if (left == null || left.getTime() < point.getTime())
left = point;
} else if (right == null || right.getTime() > point.getTime())
right = point;
}
if (left != null) {
if (right != null) {
float leftDist = 1 - Math.abs(left.getTime() - time);
float rightDist = 1 - Math.abs(right.getTime() - time);
float totalDist = leftDist + rightDist;
return left.getColor().mix((leftDist / totalDist), (rightDist / totalDist), right.getColor());
}
return left.getColor();
}
return new Color();
}
}

View File

@ -1,33 +0,0 @@
package com.example.particlelab.entities.particles.attributes.attributeValues;
import com.example.particlelab.data.Color;
public class TintTimelinePoint {
private float time;
private Color color;
public float getTime() {
return time;
}
public void setTime(float time) {
this.time = time;
}
public Color getColor() {
return color;
}
public void setValue(int colorIndex, float value) {
if (color == null)
color = new Color();
if (colorIndex == 0)
color.setR(value);
else if (colorIndex == 1)
color.setG(value);
else if (colorIndex == 2)
color.setB(value);
}
}

View File

@ -1,44 +0,0 @@
package com.example.particlelab.entities.textures;
/**
* Created by Julian on 11.12.2015.
*/
public class Texture {
private int id;
private int atlasWidth;
private int atlasHeight;
private int atlasIndex;
public Texture(int id, int atlasWidth, int atlasHeight) {
this.id = id;
this.atlasWidth = atlasWidth;
this.atlasHeight = atlasHeight;
}
public Texture(Texture other) {
this.id = other.getId();
this.atlasWidth = other.getAtlasWidth();
this.atlasHeight = other.getAtlasHeight();
}
public int getId() {
return id;
}
public int getAtlasWidth() {
return atlasWidth;
}
public int getAtlasHeight() {
return atlasHeight;
}
public int getAtlasIndex() {
return atlasIndex;
}
public void setAtlasIndex(int atlasIndex) {
this.atlasIndex = atlasIndex;
}
}

View File

@ -1,62 +0,0 @@
package com.example.particlelab.entities.textures;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import com.example.particlelab.main.GameLog;
import java.io.InputStream;
/**
* Created by Julian on 26.11.2015.
*/
public class TextureLoader {
private Context context;
public TextureLoader(Context context) {
this.context = context;
}
public int loadTextureId(int texture, boolean isAtlas) {
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), texture);
return loadTextureId(bitmap, isAtlas);
}
public Texture loadTexture(String inAssetsLocation) throws Exception {
InputStream is = context.getAssets().open(inAssetsLocation);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
return new Texture(loadTextureId(bitmap, false), 1, 1);
}
private int loadTextureId(Bitmap bitmap, boolean isAtlas) {
int id = genTexture();
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id);
if (!isAtlas) {
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
} else {
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
}
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
GameLog.d("Texture " + id + " successfully loaded");
return id;
}
private int genTexture() {
int[] idField = new int[1];
GLES20.glGenTextures(1, idField, 0);
return idField[0];
}
}

View File

@ -1,35 +0,0 @@
package com.example.particlelab.entities.textures;
import android.content.Context;
import com.example.particlelab.R;
/**
* Created by Julian on 05.12.2015.
*/
public class TexturePack {
private TextureLoader loader;
public final Texture star;
public final Texture yellowParticle;
public final Texture redParticle;
public TexturePack(Context context) {
loader = new TextureLoader(context);
star = loadTexture(R.drawable.star);
yellowParticle = loadTexture(R.drawable.yellowparticle);
redParticle = loadTexture(R.drawable.redparticle);
}
private Texture loadTexture(int id) {
int texId = loader.loadTextureId(id, false);
return new Texture(texId, 1, 1);
}
public Texture loadAtlas(int id, int atlasWidth, int atlasHeight) {
int texId = loader.loadTextureId(id, true);
return new Texture(texId, atlasWidth, atlasHeight);
}
}

View File

@ -1,44 +0,0 @@
package com.example.particlelab.main;
import android.util.Log;
/**
* Created by Julian on 23.11.2015.
*/
public class GameLog {
private final static String TAG = "GameLog";
public static boolean debugging = true;
public static void i(String message) {
Log.i(TAG + getCallerInfo(), message);
}
public static void d(String message) {
if (debugging)
Log.d(TAG + getCallerInfo(), message);
}
public static void e(String message) {
Log.e(TAG + getCallerInfo(), message);
}
public static void e(Throwable error) {
Log.e(TAG + getCallerInfo(), error.getMessage(), error);
}
//Possible to get Method which called i, d, e
//Method found at stack[4]
public static void stack() {
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
Log.i(TAG + "Stack", "StackSize: " + stack.length);
for (int i = 0; i < stack.length; i++) {
Log.i(TAG + "Stack", i + ": " + stack[i]);
}
}
private static String getCallerInfo() {
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
return "(" + stack[4].getFileName() + ", " + stack[4].getMethodName() + ", " + stack[4].getLineNumber() + ")";
}
}

View File

@ -1,81 +0,0 @@
package com.example.particlelab.main;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
import com.example.particlelab.entities.particles.ParticleReader;
import com.example.particlelab.entities.particles.ParticleSystem;
import com.example.particlelab.rendering.GameRenderer;
import com.example.particlelab.rendering.Rendering;
/**
* Created by Julian on 02.08.2016.
*/
public class MainActivity extends Activity {
private MyGlSurfaceView glSurfaceView;
private ParticleSystem particleSystem;
@Override
protected void onCreate(Bundle savedInstanceState) {
try {
GameLog.d("OnCreate");
super.onCreate(savedInstanceState);
super.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
if (!hasGLES20())
throw new Exception("OpenGL ES 2.0 not supported");
particleSystem = new ParticleSystem(this);
Rendering rendering = new Rendering(this, particleSystem);
glSurfaceView = new MyGlSurfaceView(this, new GameRenderer(this,rendering));
super.setContentView(glSurfaceView);
} catch (Exception e) {
onException(e);
}
}
public void onException(Exception e) {
GameLog.e(e);
super.finish();
}
@Override
protected void onPause() {
GameLog.d("OnPause");
glSurfaceView.onPause();
super.onPause();
}
@Override
protected void onResume() {
GameLog.d("OnResume");
glSurfaceView.onResume();
super.onResume();
}
@Override
protected void onDestroy() {
GameLog.d("OnDestroy");
super.onDestroy();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
private boolean hasGLES20() {
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo info = am.getDeviceConfigurationInfo();
return info.reqGlEsVersion >= 0x20000;
}
}

View File

@ -1,35 +0,0 @@
package com.example.particlelab.main;
import android.content.Context;
import android.opengl.GLSurfaceView;
import com.example.particlelab.rendering.GameRenderer;
/**
* Created by Julian on 30.07.2016.
*/
public class MyGlSurfaceView extends GLSurfaceView {
private boolean rendererSet;
public MyGlSurfaceView(Context context, GameRenderer gameRenderer) throws Exception {
super(context);
super.setEGLContextClientVersion(2);
super.setRenderer(gameRenderer);
rendererSet = true;
}
@Override
public void onResume() {
GameLog.i("SurfaceView: onResume");
if (rendererSet)
super.onResume();
}
@Override
public void onPause() {
GameLog.i("SurfaceView: onPause");
if (rendererSet)
super.onPause();
}
}

View File

@ -1,69 +0,0 @@
package com.example.particlelab.main;
import android.content.Context;
import com.example.particlelab.data.Vector;
import com.example.particlelab.entities.Entity;
import com.example.particlelab.entities.particles.ParticleSource;
import com.example.particlelab.entities.particles.ParticleSystem;
import com.example.particlelab.entities.textures.TexturePack;
import com.example.particlelab.rendering.Timer;
import java.util.ArrayList;
import java.util.Iterator;
/**
* Created by Julian on 20.07.2016.
*/
public class Scene extends ArrayList<Entity> {
public float cameraX;
private Vector screenSize;
private ParticleSystem particleSystem;
private TexturePack textures;
public Scene(Context context, TexturePack texturePack, ParticleSystem particleSystem) {
this.particleSystem = particleSystem;
setTexturePack(texturePack);
new ParticleSource(new Vector(0, 0), particleSystem.explosion).start();
}
public void setTexturePack(TexturePack texturePack) {
this.textures = texturePack;
}
public void update(Timer timer) {
Iterator<Entity> iterator = super.iterator();
while (iterator.hasNext()) {
Entity entity = iterator.next();
Vector movement = entity.getMovement();
Vector finalMovement = new Vector(movement).mul(timer.getFrameTime());
entity.move(finalMovement);
if (entity.getRightEdge() - cameraX < -3f) {
iterator.remove();
super.remove(entity);
}
}
}
public Vector calcWorldFromScreenCoords(float screenX, float screenY) throws Exception {
if (screenSize == null)
throw new Exception("ScreenSize not set");
float glCoordWidth = (2f * screenSize.x / screenSize.y);
float x = ((screenX / screenSize.x) * 2f - 1f) * glCoordWidth / 2;
x += cameraX;
float y = -((screenY / screenSize.y) * 2f - 1f);
return new Vector(x, y);
}
public void setScreenSize(Vector screenSize) {
this.screenSize = screenSize;
}
public ParticleSystem getParticleSystem() {
return particleSystem;
}
}

View File

@ -1,124 +0,0 @@
package com.example.particlelab.rendering;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import com.example.particlelab.data.Color;
import com.example.particlelab.entities.Entity;
import com.example.particlelab.entities.particles.ParticleEffect;
import com.example.particlelab.entities.particles.ParticleSource;
import com.example.particlelab.entities.particles.ParticleSystem;
import com.example.particlelab.entities.textures.TexturePack;
import com.example.particlelab.main.GameLog;
import com.example.particlelab.main.Scene;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
/**
* Created by Julian on 22.11.2015.
*/
public class GameRenderer implements GLSurfaceView.Renderer {
private Rendering rendering;
private MatrixCreator matrixCreator;
private boolean additiveBlending;
private Color emptyColor;
private Context context;
private Quad quad;
//GL Context
private ShaderProgram shaderProgram;
private TexturePack texturePack;
private Timer timer;
public GameRenderer(Context context, Rendering rendering) {
this.context = context;
this.rendering = rendering;
emptyColor = new Color(-1, -1, -1);
matrixCreator = new MatrixCreator();
quad = new Quad();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GameLog.d("onSurfaceCreated");
GLES20.glClearColor(0, 0, 0, 1.0f);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
try {
shaderProgram = new ShaderProgram(context);
texturePack = new TexturePack(context);
timer = new Timer();
} catch (Exception e) {
rendering.onException(e);
}
rendering.initiate(texturePack, timer);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GameLog.d("onSurfaceChanged: width=" + width + ", height=" + height);
GLES20.glViewport(0, 0, width, height);
matrixCreator.setMVPMSize(width, height);
rendering.setScreenSize(width, height);
}
@Override
public void onDrawFrame(GL10 gl) {
timer.update();
rendering.update();
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Scene scene = rendering.getScene();
ParticleSystem particleSystem = scene.getParticleSystem();
shaderProgram.start();
shaderProgram.loadMVPMatrix(matrixCreator, scene.cameraX);
for (ParticleEffect effect : particleSystem.getEffects()) {
gl.glActiveTexture(GL10.GL_TEXTURE0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, effect.getTexture().getId());
shaderProgram.loadTextureAtlasInfos(effect.getTexture());
if (effect.getOptions().isAdditive() && !additiveBlending)
enableAdditiveBlending(gl);
if (!effect.getOptions().isAdditive() && additiveBlending)
disableAdditiveBlending(gl);
for (ParticleSource source : effect.getSources()) {
source.getActiveParticleLock().lock();
for (Entity particle : source.getActiveParticles())
renderParticle(gl, particle);
source.getActiveParticleLock().unlock();
}
}
shaderProgram.stop();
}
private void renderEntity(GL10 gl, Entity entity) {
gl.glActiveTexture(GL10.GL_TEXTURE0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, entity.getTexture().getId());
shaderProgram.loadTransformationMatrix(matrixCreator, entity);
shaderProgram.loadAlpha(entity.getAlpha());
shaderProgram.loadTextureAtlasInfos(entity.getTexture());
shaderProgram.loadColor(entity.getColor() != null ? entity.getColor() : emptyColor);
quad.draw();
}
private void renderParticle(GL10 gl, Entity entity) {
shaderProgram.loadTransformationMatrix(matrixCreator, entity);
shaderProgram.loadAlpha(entity.getAlpha());
shaderProgram.loadColor(entity.getColor() != null ? entity.getColor() : emptyColor);
quad.draw();
}
private void enableAdditiveBlending(GL10 gl) {
additiveBlending = true;
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
}
private void disableAdditiveBlending(GL10 gl) {
additiveBlending = false;
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
}
}

View File

@ -1,22 +0,0 @@
package com.example.particlelab.rendering;
public class Lock {
private boolean isLocked = false;
public synchronized void lock() {
while (isLocked) {
try {
wait();
} catch (Exception e) {
e.printStackTrace();
}
}
isLocked = true;
}
public synchronized void unlock() {
isLocked = false;
notify();
}
}

View File

@ -1,49 +0,0 @@
package com.example.particlelab.rendering;
import android.opengl.Matrix;
import com.example.particlelab.entities.Entity;
import com.example.particlelab.data.Vector;
/**
* Created by Julian on 23.11.2015.
*/
public class MatrixCreator {
private float width, height;
public void setMVPMSize(float width, float height) {
this.width = width;
this.height = height;
}
public float[] createModelViewProjectionMatrix(float cameraX) {
float[] mvpMatrix = new float[16];
float[] projectionMatrix = new float[16];
float[] viewMatrix = new float[16];
float ratio = width / height;
Matrix.frustumM(projectionMatrix, 0, -ratio + cameraX, ratio + cameraX, -1, 1, 1, 2);
Matrix.setLookAtM(viewMatrix, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0);
Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
return mvpMatrix;
}
public float[] createTransformationMatrix(Entity entity) {
float width = entity.getWidth();
float height = entity.getHeight();
float rotation = entity.getRotation();
Vector position = entity.getPosition();
return createTransformationMatrix(width, height, rotation, position);
}
public float[] createTransformationMatrix(float width, float height, float rotation, Vector position) {
float[] transformationMatrix = new float[16];
Matrix.setIdentityM(transformationMatrix, 0);
Matrix.translateM(transformationMatrix, 0, position.x, position.y, 0);
Matrix.rotateM(transformationMatrix, 0, rotation, 0, 0, 1);
Matrix.scaleM(transformationMatrix, 0, width * .5f, height * .5f, 0);
return transformationMatrix;
}
}

View File

@ -1,49 +0,0 @@
package com.example.particlelab.rendering;
import android.opengl.GLES20;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
/**
* Created by Julian on 26.11.2015.
*/
public class Quad {
private FloatBuffer vertexBuffer;
private FloatBuffer textureBuffer;
private float vertices[] = {1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f};
private float textures[] = {1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
public Quad() {
vertexBuffer = createEmptyFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
textureBuffer = createEmptyFloatBuffer();
textureBuffer.put(textures);
textureBuffer.position(0);
}
private FloatBuffer createEmptyFloatBuffer() {
ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
bb.order(ByteOrder.nativeOrder());
return bb.asFloatBuffer();
}
public void draw() {
GLES20.glEnableVertexAttribArray(0);
GLES20.glEnableVertexAttribArray(1);
GLES20.glVertexAttribPointer(0, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glVertexAttribPointer(1, 2, GLES20.GL_FLOAT, false, 0, textureBuffer);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertices.length / 2);
GLES20.glDisableVertexAttribArray(1);
GLES20.glDisableVertexAttribArray(0);
}
}

View File

@ -1,57 +0,0 @@
package com.example.particlelab.rendering;
import com.example.particlelab.entities.particles.ParticleSystem;
import com.example.particlelab.entities.textures.TexturePack;
import com.example.particlelab.main.MainActivity;
import com.example.particlelab.main.Scene;
import com.example.particlelab.data.Vector;
/**
* Created by Julian on 26.11.2015.
*/
public class Rendering {
private MainActivity mainActivity;
private ParticleSystem particleSystem;
private Timer timer;
private Scene scene;
private boolean alreadyInitiated = false;
public Rendering(MainActivity mainActivity, ParticleSystem particleSystem) {
this.mainActivity = mainActivity;
this.particleSystem = particleSystem;
}
public void initiate(TexturePack texturePack, Timer timer) {
this.timer = timer;
if(!alreadyInitiated)
scene = new Scene(mainActivity, texturePack, particleSystem);
else {
scene.setTexturePack(texturePack);
}
try {
particleSystem.loadTextures();
}catch (Exception e){
onException(e);
}
alreadyInitiated = true;
}
public void update() {
particleSystem.update(timer);
scene.update(timer);
}
public void setScreenSize(int width, int height) {
if (scene != null)
scene.setScreenSize(new Vector(width, height));
}
public void onException(Exception e) {
mainActivity.onException(e);
}
public Scene getScene() {
return scene;
}
}

View File

@ -1,138 +0,0 @@
package com.example.particlelab.rendering;
import android.content.Context;
import android.opengl.GLES20;
import com.example.particlelab.entities.Entity;
import com.example.particlelab.data.Color;
import com.example.particlelab.entities.textures.Texture;
import com.example.particlelab.main.GameLog;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* Created by Julian on 23.11.2015.
*/
public class ShaderProgram {
private Context context;
private int vertexShader, fragmentShader, program;
private int location_mvpMatrix;
private int location_transformationMatrix;
private int location_alpha;
private int location_texAtlasSize;
private int location_texAtlasIndex;
private int location_isTerrain;
private int location_color;
public ShaderProgram(Context context) throws Exception {
this.context = context;
vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, "vertexShader.glsl");
fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, "fragmentShader.glsl");
program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == GLES20.GL_FALSE) {
GLES20.glDeleteProgram(program);
throw new Exception("Could not link program: "
+ GLES20.glGetProgramInfoLog(program));
}
bindAttribLocations();
loadUniformLocations();
GameLog.d("ShaderProgram successfully loaded");
}
private void loadUniformLocations() {
location_mvpMatrix = GLES20.glGetUniformLocation(program, "mvpMatrix");
location_transformationMatrix = GLES20.glGetUniformLocation(program, "transformationMatrix");
location_alpha = GLES20.glGetUniformLocation(program, "alpha");
location_texAtlasSize = GLES20.glGetUniformLocation(program, "texAtlasSize");
location_texAtlasIndex = GLES20.glGetUniformLocation(program, "texAtlasIndex");
location_isTerrain = GLES20.glGetUniformLocation(program, "isTerrain");
location_color = GLES20.glGetUniformLocation(program, "color");
}
private void bindAttribLocations() {
GLES20.glBindAttribLocation(program, 0, "position");
GLES20.glBindAttribLocation(program, 1, "texCoords");
}
public void start() {
GLES20.glUseProgram(program);
}
public void stop() {
GLES20.glUseProgram(0);
}
public void loadMVPMatrix(MatrixCreator matrixCreator, float cameraX) {
float[] mvpMatrix = matrixCreator.createModelViewProjectionMatrix(cameraX);
GLES20.glUniformMatrix4fv(location_mvpMatrix, 1, false, mvpMatrix, 0);
}
public void loadTransformationMatrix(MatrixCreator matrixCreator, Entity entity) {
float[] transformationMatrix = matrixCreator.createTransformationMatrix(entity);
GLES20.glUniformMatrix4fv(location_transformationMatrix, 1, false, transformationMatrix, 0);
}
public void loadColor(Color color){
GLES20.glUniform3f(location_color, color.getR(), color.getG(), color.getB());
}
public void loadAlpha(float alpha) {
GLES20.glUniform1f(location_alpha, alpha);
}
public void loadTextureAtlasInfos(Texture texture) {
GLES20.glUniform2f(location_texAtlasSize, texture.getAtlasWidth(), texture.getAtlasHeight());
GLES20.glUniform1f(location_texAtlasIndex, texture.getAtlasIndex());
}
public void loadIsTerrain(boolean isTerrain) {
float fIsTerrain = isTerrain ? 1 : 0;
GLES20.glUniform1f(location_isTerrain, fIsTerrain);
}
public void cleanUp() {
stop();
GLES20.glDeleteShader(vertexShader);
GLES20.glDeleteShader(fragmentShader);
GLES20.glDeleteProgram(program);
GameLog.d("Shader cleaned");
}
private int loadShader(int type, String shaderName) throws Exception {
try {
InputStream is = context.getAssets().open(shaderName);
InputStreamReader isReader = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isReader);
StringBuilder source = new StringBuilder();
String line;
while ((line = reader.readLine()) != null)
source.append(line);
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, source.toString());
GLES20.glCompileShader(shader);
int[] compiled = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == GLES20.GL_FALSE) {
GLES20.glDeleteShader(shader);
throw new Exception("Could not compile shader \"" + shaderName + "\": "
+ GLES20.glGetShaderInfoLog(shader));
}
GameLog.d("Shader \"" + shaderName + "\" successfully loaded");
return shader;
} catch (Exception e) {
throw new Exception("Could not load Shader \"" + shaderName + "\"", e);
}
}
}

View File

@ -1,46 +0,0 @@
package com.example.particlelab.rendering;
/**
* Created by Julian on 22.11.2015.
*/
public class Timer {
private long lastFpsTime;
private int fpsCounter;
private int fps;
private long lastTime;
private long delta;
public Timer() {
lastTime = System.currentTimeMillis();
lastFpsTime = lastTime;
}
public void update() {
long currentTime = System.currentTimeMillis();
delta = currentTime - lastTime;
lastTime = currentTime;
fpsCounter++;
if (currentTime - lastFpsTime > 1000) {
fps = fpsCounter;
lastFpsTime += 1000;
fpsCounter = 0;
}
}
public float getFrameTime() {
return delta;
}
public int getFps() {
return fps;
}
public long getCurrentTime() {
return System.currentTimeMillis();
}
}