Init der fehlenden Dateien

This commit is contained in:
= 2017-11-22 16:04:46 +01:00
parent 3324056634
commit 8c24604447
216 changed files with 12756 additions and 0 deletions

2
.gitignore vendored
View File

@ -1,7 +1,9 @@
.gradle
/app/*.apk
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
/app/build

View File

@ -0,0 +1,13 @@
package de.frajul.endlessroll;
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

@ -0,0 +1,37 @@
<levelPack id="2">
<world>ICY_MOUNTAINS</world>
<levels class="java.util.ArrayList">
<level packId="2" id="1" goalX="0.6333344" startSpeed="0.5" endSpeed="0.5" terrainEdge="-0.6" ceilingEdge="1.0">
<terrainTiles class="java.util.ArrayList">
<tileData x="-1.7933328" width="2.4133344"/>
<tileData x="0.023334444" width="1.2199999"/>
</terrainTiles>
<ceilingTiles class="java.util.ArrayList">
<tileData x="-1.7933328" width="2.4133344"/>
<tileData x="0.023334444" width="1.2199999"/>
</ceilingTiles>
<obstacles class="java.util.ArrayList"/>
<stars class="java.util.ArrayList">
<positionData x="-0.57999986" y="-0.45999992"/>
<positionData x="-0.2666666" y="-0.46666658"/>
<positionData x="0.033333335" y="-0.4466666"/>
</stars>
<energy x="0.36666656" y="-0.43333337"/>
</level>
<level packId="2" id="2" goalX="0.2466674" startSpeed="0.5" endSpeed="0.5" terrainEdge="-0.6" ceilingEdge="1.0">
<terrainTiles class="java.util.ArrayList">
<tileData x="-1.3766663" width="3.2466674"/>
</terrainTiles>
<ceilingTiles class="java.util.ArrayList">
<tileData x="-1.3766663" width="3.2466674"/>
</ceilingTiles>
<obstacles class="java.util.ArrayList"/>
<stars class="java.util.ArrayList">
<positionData x="-0.57333314" y="-0.45333323"/>
<positionData x="-0.2799999" y="-0.17333329"/>
<positionData x="0.006666667" y="-0.45333326"/>
</stars>
<energy x="-0.29333326" y="-0.45333314"/>
</level>
</levels>
</levelPack>

View File

@ -0,0 +1,151 @@
Untitled
- Delay -
active: false
- Duration -
lowMin: 1000.0
lowMax: 1000.0
- Count -
min: 0
max: 200
- Emission -
lowMin: 0.0
lowMax: 0.0
highMin: 7.0
highMax: 7.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Life -
lowMin: 0.0
lowMax: 0.0
highMin: 1100.0
highMax: 2000.0
relative: false
scalingCount: 5
scaling0: 1.0
scaling1: 1.0
scaling2: 1.0
scaling3: 1.0
scaling4: 1.0
timelineCount: 5
timeline0: 0.0
timeline1: 0.001
timeline2: 0.002
timeline3: 0.003
timeline4: 1.0
- Life Offset -
active: false
- X Offset -
active: false
- Y Offset -
active: false
- Spawn Shape -
shape: square
- Spawn Width -
lowMin: 0.0
lowMax: 0.0
highMin: 200.0
highMax: 200.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Spawn Height -
lowMin: 0.0
lowMax: 0.0
highMin: 200.0
highMax: 200.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Scale -
lowMin: 0.0
lowMax: 0.0
highMin: 60.0
highMax: 30.0
relative: false
scalingCount: 4
scaling0: 1.0
scaling1: 0.64705884
scaling2: 0.23529412
scaling3: 0.0
timelineCount: 4
timeline0: 0.0
timeline1: 0.8630137
timeline2: 0.98630136
timeline3: 1.0
- Velocity -
active: true
lowMin: 0.0
lowMax: 0.0
highMin: 0.0
highMax: 60.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Angle -
active: true
lowMin: 0.0
lowMax: 360.0
highMin: 60.0
highMax: 120.0
relative: false
scalingCount: 3
scaling0: 1.0
scaling1: 1.0
scaling2: 1.0
timelineCount: 3
timeline0: 0.0
timeline1: 0.56164384
timeline2: 0.9931507
- Rotation -
active: false
- Wind -
active: false
- Gravity -
active: false
- Tint -
colorsCount: 6
colors0: 0.047058824
colors1: 1.0
colors2: 0.93333334
colors3: 0.3137255
colors4: 0.047058824
colors5: 1.0
timelineCount: 2
timeline0: 0.0
timeline1: 1.0
- Transparency -
lowMin: 0.0
lowMax: 0.0
highMin: 1.0
highMax: 1.0
relative: false
scalingCount: 5
scaling0: 0.0
scaling1: 1.0
scaling2: 1.0
scaling3: 0.6666667
scaling4: 0.0
timelineCount: 5
timeline0: 0.0
timeline1: 0.2
timeline2: 0.201
timeline3: 0.9246575
timeline4: 1.0
- Options -
attached: false
continuous: true
aligned: false
additive: true
behind: false
premultipliedAlpha: false
- Image Path -
particle.png

View File

@ -0,0 +1,135 @@
Untitled
- Delay -
active: false
- Duration -
lowMin: 3000.0
lowMax: 3000.0
- Count -
min: 0
max: 200
- Emission -
lowMin: 0.0
lowMax: 0.0
highMin: 250.0
highMax: 250.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Life -
lowMin: 0.0
lowMax: 0.0
highMin: 500.0
highMax: 1000.0
relative: false
scalingCount: 3
scaling0: 1.0
scaling1: 1.0
scaling2: 0.3
timelineCount: 3
timeline0: 0.0
timeline1: 0.66
timeline2: 1.0
- Life Offset -
active: false
- X Offset -
active: false
- Y Offset -
active: false
- Spawn Shape -
shape: point
- Spawn Width -
lowMin: 0.0
lowMax: 0.0
highMin: 0.0
highMax: 0.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Spawn Height -
lowMin: 0.0
lowMax: 0.0
highMin: 0.0
highMax: 0.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Scale -
lowMin: 0.0
lowMax: 0.0
highMin: 100.0
highMax: 100.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Velocity -
active: true
lowMin: 0.0
lowMax: 0.0
highMin: 90.0
highMax: 900.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Angle -
active: true
lowMin: 90.0
lowMax: 90.0
highMin: 45.0
highMax: 135.0
relative: false
scalingCount: 3
scaling0: 1.0
scaling1: 0.0
scaling2: 0.0
timelineCount: 3
timeline0: 0.0
timeline1: 0.5
timeline2: 1.0
- Rotation -
active: false
- Wind -
active: false
- Gravity -
active: false
- Tint -
colorsCount: 3
colors0: 1.0
colors1: 0.12156863
colors2: 0.047058824
timelineCount: 1
timeline0: 0.0
- Transparency -
lowMin: 0.0
lowMax: 0.0
highMin: 1.0
highMax: 1.0
relative: false
scalingCount: 4
scaling0: 0.0
scaling1: 1.0
scaling2: 0.75
scaling3: 0.0
timelineCount: 4
timeline0: 0.0
timeline1: 0.2
timeline2: 0.8
timeline3: 1.0
- Options -
attached: false
continuous: true
aligned: false
additive: true
behind: false
premultipliedAlpha: false
- Image Path -
particle.png

View File

@ -0,0 +1,69 @@
package de.frajul.endlessroll.data;
import de.frajul.endlessroll.main.GameLog;
/**
* 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 interpolate(float leftValue, float rightValue, Color color2) {
float r = this.r + (color2.r - this.r) * leftValue;
float g = this.g + (color2.g - this.g) * leftValue;
float b = this.b + (color2.b - this.b) * leftValue;
return new Color(r, g, b);
}
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

@ -0,0 +1,147 @@
package de.frajul.endlessroll.data;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Created by Julian on 16.11.2016.
*/
public class SynchronizedArrayList<E> extends ArrayList<E> {
@Override
public synchronized String toString() {
return super.toString();
}
@Override
public synchronized boolean add(E object) {
return super.add(object);
}
@Override
public synchronized void add(int index, E object) {
super.add(index, object);
}
@Override
public synchronized boolean addAll(Collection<? extends E> collection) {
return super.addAll(collection);
}
@Override
public synchronized boolean addAll(int index, Collection<? extends E> collection) {
return super.addAll(index, collection);
}
@Override
public synchronized void clear() {
super.clear();
}
@Override
public synchronized Object clone() {
return super.clone();
}
@Override
public synchronized void ensureCapacity(int minimumCapacity) {
super.ensureCapacity(minimumCapacity);
}
@Override
public synchronized E get(int index) {
return super.get(index);
}
@Override
public synchronized int size() {
return super.size();
}
@Override
public synchronized boolean isEmpty() {
return super.isEmpty();
}
@Override
public synchronized boolean contains(Object object) {
return super.contains(object);
}
@Override
public synchronized int indexOf(Object object) {
return super.indexOf(object);
}
@Override
public synchronized int lastIndexOf(Object object) {
return super.lastIndexOf(object);
}
@Override
public synchronized E remove(int index) {
return super.remove(index);
}
@Override
public synchronized boolean remove(Object object) {
return super.remove(object);
}
@Override
protected synchronized void removeRange(int fromIndex, int toIndex) {
super.removeRange(fromIndex, toIndex);
}
@Override
public synchronized E set(int index, E object) {
return super.set(index, object);
}
@Override
public synchronized Object[] toArray() {
return super.toArray();
}
@Override
public synchronized <T> T[] toArray(T[] contents) {
return super.toArray(contents);
}
@Override
public synchronized void trimToSize() {
super.trimToSize();
}
@Override
public synchronized int hashCode() {
return super.hashCode();
}
@Override
public synchronized boolean equals(Object o) {
return super.equals(o);
}
@Override
public synchronized List<E> subList(int start, int end) {
return super.subList(start, end);
}
@Override
public synchronized boolean containsAll(Collection<?> collection) {
return super.containsAll(collection);
}
@Override
public synchronized boolean removeAll(Collection<?> collection) {
return super.removeAll(collection);
}
@Override
public synchronized boolean retainAll(Collection<?> collection) {
return super.retainAll(collection);
}
}

View File

@ -0,0 +1,101 @@
package de.frajul.endlessroll.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

@ -0,0 +1,25 @@
package de.frajul.endlessroll.entities;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.textures.Texture;
import de.frajul.endlessroll.main.game.Timer;
/**
* Created by Julian on 20.02.2017.
*/
public class AnimatedEntity extends Entity {
protected Animation animation;
public AnimatedEntity(Texture texture, Vector position, float width, float height) {
super(texture, position, width, height);
animation = new Animation();
}
public void update(Timer timer){
animation.update(timer);
super.setTextureAtlasIndex(animation.getCurrentTexIndex());
}
}

View File

@ -0,0 +1,55 @@
package de.frajul.endlessroll.entities;
import de.frajul.endlessroll.main.game.Timer;
/**
* Created by Julian on 14.12.2015.
*/
public class Animation {
private int[] indexSequence = {0, 1, 2, 3};
private boolean looping = false;
private int requiredDelta = 110;
private int indexPointer = 0;
private boolean stillRunning = true;
private long lastSwitchTime = -1;
public void disable(){
stillRunning = false;
}
public void update(Timer timer) {
if (lastSwitchTime == -1) {
lastSwitchTime = timer.getCurrentTime();
return;
}
if (stillRunning) {
long delta = timer.getCurrentTime() - lastSwitchTime;
if (delta >= requiredDelta) {
lastSwitchTime = timer.getCurrentTime();
indexPointer++;
if (!looping && indexPointer == indexSequence.length - 1)
stillRunning = false;
if (looping && indexPointer == indexSequence.length)
indexPointer = 0;
}
}
}
public int getCurrentTexIndex() {
return indexSequence[indexPointer];
}
public void setIndexSequence(int[] indexSequence) {
this.indexSequence = indexSequence;
}
public void setRequiredDelta(int requiredDelta) {
this.requiredDelta = requiredDelta;
}
public void setLooping(boolean looping) {
this.looping = looping;
}
}

View File

@ -0,0 +1,56 @@
package de.frajul.endlessroll.entities;
import de.frajul.endlessroll.data.SynchronizedArrayList;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.textures.Texture;
/**
* Created by Julian on 20.07.2016.
*/
public class Background extends SynchronizedArrayList<Entity> {
private final float PART_WIDTH = 5;
private final float HALF_PART_WIDTH = PART_WIDTH / 2;
private final float HEIGHT = 2.5f;
private Texture texture;
public Background(Texture texture) {
this.texture = texture;
super.add(createPart(-HALF_PART_WIDTH));
}
public void changeTexture(Texture texture) {
this.texture = texture;
synchronized (this) {
for (Entity entity : this)
entity.setTexture(texture);
}
}
private Entity createPart(float xLeftEdge) {
return new Entity(texture, new Vector(xLeftEdge + HALF_PART_WIDTH, (HEIGHT - 2) / 2), PART_WIDTH, HEIGHT);
}
public void move(float x, float cameraX) {
Vector movement = new Vector(x, 0);
synchronized (this) {
for (Entity part : this)
part.move(movement);
}
if (!super.isEmpty()) {
Entity last = super.get(super.size() - 1);
if (last.getRightEdge() - cameraX < 3) {
super.add(createPart(last.getRightEdge() - 0.001f));
}
if (super.get(0).getRightEdge() - cameraX < -3) {
super.remove(0);
}
}
}
public void resetPosition() {
super.clear();
super.add(createPart(-HALF_PART_WIDTH));
}
}

View File

@ -0,0 +1,39 @@
package de.frajul.endlessroll.entities;
import android.support.annotation.Nullable;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.particles.ParticleEffect;
import de.frajul.endlessroll.entities.particles.ParticleSource;
import de.frajul.endlessroll.entities.particles.ParticleSystem;
/**
* Created by Julian on 11.03.2016.
*/
public enum DestroyEffect {
EXPLOSION, STAR_EXPLOSION, ENERGY_COLLECT, NONE;
@Nullable
public ParticleSource createEffect(ParticleSystem system, Vector position, Vector size) {
if (this == NONE)
return null;
ParticleSource source = new ParticleSource(position, getEffect(system));
source.setSpawnSize(size);
return source;
}
private ParticleEffect getEffect(ParticleSystem system) {
switch (this) {
case EXPLOSION:
return system.explosion;
case STAR_EXPLOSION:
return system.starCollect;
case ENERGY_COLLECT:
return system.energyCollect;
default:
return null;
}
}
}

View File

@ -0,0 +1,113 @@
package de.frajul.endlessroll.entities;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.collision.geometry.Quad;
import de.frajul.endlessroll.entities.textures.Texture;
/**
* Created by Julian on 20.11.2015.
*/
public class Entity extends Quad {
private int textureAtlasIndex;
private Texture texture;
private Vector movement;
private float rotation;
private float alpha = 1.0f;
private boolean destroyed;
private DestroyEffect destroyEffect;
private Vector maxTexSize;
private boolean visible = true;
public Entity(Texture texture, Vector position, float width, float height) {
super(position, width, height);
this.texture = texture;
this.movement = new Vector();
this.maxTexSize = new Vector();
}
public void move(Vector movement) {
position.translate(movement);
}
public void rotate(float factor) {
rotation += factor;
}
public void setToTerrain(float terrainEdge) {
position.y = terrainEdge + height / 2;
}
public void setTopEdge(float y) {
position.y = y - height / 2;
}
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 destroy(DestroyEffect destroyEffect) {
this.destroyed = true;
this.destroyEffect = destroyEffect;
}
public boolean isDestroyed() {
return destroyed;
}
public DestroyEffect getDestroyEffect() {
return destroyEffect;
}
public void setTextureAtlasIndex(int textureAtlasIndex) {
this.textureAtlasIndex = textureAtlasIndex;
}
public int getTextureAtlasIndex() {
return textureAtlasIndex;
}
public void setMaxTexSize(Vector maxTexSize) {
this.maxTexSize = maxTexSize;
}
public Vector getMaxTexSize() {
return maxTexSize;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public boolean isVisible() {
return visible;
}
}

View File

@ -0,0 +1,16 @@
package de.frajul.endlessroll.entities;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.textures.Texture;
public class Goal extends Entity {
public Goal(Texture texture) {
super(texture, new Vector(), 0.1f, 3);
super.getMaxTexSize().setY(0.2f);
}
public void setGoalX(float goalX) {
super.setPosition(new Vector(goalX - 0.05f, 0));
}
}

View File

@ -0,0 +1,130 @@
package de.frajul.endlessroll.entities;
import java.util.ArrayList;
import java.util.List;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.particles.ParticleSource;
import de.frajul.endlessroll.entities.particles.ParticleSystem;
import de.frajul.endlessroll.entities.shapes.PlayerShape;
import de.frajul.endlessroll.entities.tools.PlayerInfluenceTool;
import de.frajul.endlessroll.main.game.Timer;
/**
* Created by Julian on 20.11.2015.
*/
public class Player extends Entity {
private final float ROTATION_SPEED = -400;
public final float RADIUS = 0.1f;
private final float START_X = -0.9f;
private final float SPEED = 0.002f;
private float startSpeed, endSpeed;
private float speed = SPEED;
private long currentSuperPowerDuration;
private boolean hasSuperPower;
private long superPowerDuration;
private ParticleSource superPowerParticles;
private ParticleSystem particleSystem;
private List<PlayerInfluenceTool> influenceTools = new ArrayList<>();
private List<Float> forces = new ArrayList<>();
private float gravityForce;
public Player() {
super(PlayerShape.BALL.getTexture(), new Vector(), 0, 0);
super.setWidth(RADIUS * 2);
super.setHeight(RADIUS * 2);
}
public void startSuperPower(long duration) {
this.superPowerDuration = duration;
currentSuperPowerDuration = 0;
hasSuperPower = true;
superPowerParticles = new ParticleSource(
new Vector(super.getPosition().x, super.getPosition().y), particleSystem.superPower);
superPowerParticles.start();
}
public void init(PlayerShape playerShape, float terrainEdge, float startSpeed, float endSpeed, ParticleSystem particleSystem) {
super.setTexture(playerShape.getTexture());
super.setToTerrain(terrainEdge);
super.getPosition().x = START_X;
super.setMovement(new Vector(speed, 0));
this.startSpeed = startSpeed;
this.endSpeed = endSpeed;
setSpeedByProgress(0);
this.particleSystem = particleSystem;
}
public void setSpeedByProgress(float progress) {
this.speed = ((endSpeed - startSpeed) * progress + startSpeed) * SPEED;
super.getMovement().x = speed;
}
public void preMoveUpdate(Timer timer) {
if (hasSuperPower && superPowerParticles != null) {
currentSuperPowerDuration += timer.getFrameTimeSeconds();
hasSuperPower = superPowerDuration >= currentSuperPowerDuration;
superPowerParticles.setPosition(new Vector(super.getPosition()));
}
if (!hasSuperPower && superPowerParticles != null)
superPowerParticles.kill();
for (PlayerInfluenceTool tool : influenceTools)
tool.influencePlayerValues(this);
for (float force : forces)
super.getMovement().y += force;
super.getMovement().y += gravityForce;
}
public void clearAllForces() {
forces.clear();
gravityForce = 0;
}
public void manipulateAllForces(float factor) {
for (int i = 0; i < forces.size(); i++)
forces.set(i, forces.get(i) * factor);
gravityForce *= factor * factor;
}
public void postMoveUpdate() {
influenceTools.clear();
forces.clear();
}
public float getProgress() {
return getPosition().x - START_X;
}
public float getSpeed() {
return speed;
}
public boolean hasSuperPower() {
return hasSuperPower;
}
public void addInfluenceTool(PlayerInfluenceTool tool) {
influenceTools.add(tool);
}
public void addForce(float force) {
forces.add(force);
}
public void setGravityForce(float gravityForce) {
this.gravityForce = gravityForce;
}
@Override
public void move(Vector movement) {
super.move(movement);
rotate(movement.x * ROTATION_SPEED);
}
}

View File

@ -0,0 +1,44 @@
package de.frajul.endlessroll.entities;
import de.frajul.endlessroll.main.GameLog;
/**
* Created by Julian on 11.12.2016.
*/
public enum Vertex {
UL(0, -1, 1), UR(1, 1, 1), BL(3, -1, -1), BR(2, 1, -1);
private int index;
private float x, y;
Vertex(int index, float x, float y) {
this.index = index;
this.x = x;
this.y = y;
}
public Vertex getNext(boolean clockwise) {
int newIndex = index + 1;
if (!clockwise)
newIndex = index - 1;
if (newIndex > 3)
newIndex = 0;
if (newIndex < 0)
newIndex = 3;
for (Vertex vertex : values())
if (vertex.index == newIndex)
return vertex;
GameLog.e("No vertex with index " + index + " found!!!");
return null;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
}

View File

@ -0,0 +1,17 @@
package de.frajul.endlessroll.entities.collectables;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.AnimatedEntity;
import de.frajul.endlessroll.entities.textures.Texture;
import de.frajul.endlessroll.levels.PositionData;
public class Energy extends AnimatedEntity {
private final static float SIZE = 0.3f;
public Energy(Texture texture, PositionData data) {
super(texture, new Vector(data.getX(), data.getY()), SIZE, SIZE);
animation.setLooping(true);
animation.setRequiredDelta(130);
}
}

View File

@ -0,0 +1,21 @@
package de.frajul.endlessroll.entities.collectables;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.Entity;
import de.frajul.endlessroll.entities.textures.Texture;
import de.frajul.endlessroll.levels.PositionData;
public class Star extends Entity {
private final static float SIZE = 0.25f;
private int index;
public Star(int index, Texture texture, PositionData data) {
super(texture, new Vector(data.getX(), data.getY()), SIZE, SIZE);
this.index = index;
}
public int getIndex() {
return index;
}
}

View File

@ -0,0 +1,78 @@
package de.frajul.endlessroll.entities.collision;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.collision.geometry.Circle;
import de.frajul.endlessroll.entities.collision.geometry.Triangle;
/**
* Created by Julian on 28.02.2016.
*/
public class CircleTriangleCollisionDetector {
public boolean circleTriangleCollision(Circle circle, Triangle triangle) {
if (circleIntersectingWithTriangleVertices(circle, triangle))
return true;
if (circleCenterInsideTriangle(circle, triangle))
return true;
if (circleIntersectingWithTriangleEdges(circle, triangle))
return true;
return false;
}
private boolean circleIntersectingWithTriangleEdges(Circle circle, Triangle triangle) {
Vector edge1 = triangle.getVertex1().vectorTo(triangle.getVertex2());
Vector edge2 = triangle.getVertex2().vectorTo(triangle.getVertex3());
Vector edge3 = triangle.getVertex3().vectorTo(triangle.getVertex1());
boolean intersectingWithEdge1 = circleIntersectingWithTriangleEdge(circle, triangle.getVertex1(), edge1);
boolean intersectingWithEdge2 = circleIntersectingWithTriangleEdge(circle, triangle.getVertex2(), edge2);
boolean intersectingWithEdge3 = circleIntersectingWithTriangleEdge(circle, triangle.getVertex3(), edge3);
return intersectingWithEdge1 || intersectingWithEdge2 || intersectingWithEdge3;
}
private boolean circleIntersectingWithTriangleEdge(Circle circle, Vector vertex, Vector edge) {
Vector vertexToCenter = vertex.vectorTo(circle.getCenter());
Vector kVector = new Vector(vertexToCenter).mul(edge);
float k = kVector.x + kVector.y;
if (k > 0) {
float length = edge.length();
k = k / length;
if (k < length)
if (Math.sqrt(vertexToCenter.x * vertexToCenter.x + vertexToCenter.y * vertexToCenter.y - k * k) <= circle.getRadius())
return true;
}
return false;
}
private boolean circleCenterInsideTriangle(Circle circle, Triangle triangle) {
Vector vertex1To2 = triangle.getVertex1().vectorTo(triangle.getVertex2());
Vector vertex2To3 = triangle.getVertex2().vectorTo(triangle.getVertex3());
Vector vertex3To1 = triangle.getVertex3().vectorTo(triangle.getVertex1());
Vector vertex1ToCenter = triangle.getVertex1().vectorTo(circle.getCenter());
Vector vertex2ToCenter = triangle.getVertex2().vectorTo(circle.getCenter());
Vector vertex3ToCenter = triangle.getVertex3().vectorTo(circle.getCenter());
boolean centerInsideV1V2 = vertex1To2.y * vertex1ToCenter.x - vertex1To2.x * vertex1ToCenter.y < 0;
boolean centerInsideV2V3 = vertex2To3.y * vertex2ToCenter.x - vertex2To3.x * vertex2ToCenter.y < 0;
boolean centerInsideV3V1 = vertex3To1.y * vertex3ToCenter.x - vertex3To1.x * vertex3ToCenter.y < 0;
return centerInsideV1V2 && centerInsideV2V3 && centerInsideV3V1;
}
private boolean circleIntersectingWithTriangleVertices(Circle circle, Triangle triangle) {
boolean intersectingWithVertex1 = circleIntersectingWithTriangleVertex(circle, triangle.getVertex1());
boolean intersectingWithVertex2 = circleIntersectingWithTriangleVertex(circle, triangle.getVertex2());
boolean intersectingWithVertex3 = circleIntersectingWithTriangleVertex(circle, triangle.getVertex3());
return intersectingWithVertex1 || intersectingWithVertex2 || intersectingWithVertex3;
}
private boolean circleIntersectingWithTriangleVertex(Circle circle, Vector vertex) {
Vector centerToVertex = circle.getCenter().vectorTo(vertex);
return centerToVertex.length() <= circle.getRadius();
}
}

View File

@ -0,0 +1,205 @@
package de.frajul.endlessroll.entities.collision;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.Entity;
import de.frajul.endlessroll.entities.Player;
import de.frajul.endlessroll.entities.collision.collisionData.EntityCollisionData;
import de.frajul.endlessroll.entities.collision.geometry.Circle;
import de.frajul.endlessroll.entities.collision.geometry.Quad;
import de.frajul.endlessroll.entities.collision.geometry.Triangle;
/**
* Created by Julian on 01.12.2015.
*/
public class CollisionDetector {
private CircleTriangleCollisionDetector triangleDetector;
public CollisionDetector() {
triangleDetector = new CircleTriangleCollisionDetector();
}
public boolean isCircleCircleCollision(Circle c1, Circle c2) {
float distance = Math.abs(c1.getCenter().vectorTo(c2.getCenter()).length());
float radiusSum = c1.getRadius() + c2.getRadius();
return distance < radiusSum;
}
public boolean isCircleQuadCollision(Circle circle, Quad quad) {
Vector distance = circle.getCenter().vectorTo(quad.getPosition());
distance.x = Math.abs(distance.x);
distance.y = Math.abs(distance.y);
if (distance.x > circle.getRadius() + quad.getWidth() / 2)
return false;
if (distance.y > circle.getRadius() + quad.getHeight() / 2)
return false;
if (distance.x <= quad.getWidth() / 2)
return true;
if (distance.y <= quad.getHeight() / 2)
return true;
float cornerDistance_sq = (distance.x - quad.getWidth() / 2) * (distance.x - quad
.getWidth() / 2) + (distance.y - quad.getHeight() / 2) * (distance.y - quad
.getHeight() / 2);
return cornerDistance_sq <= circle.getRadius() * circle.getRadius();
}
public boolean isCircleTriangleCollision(Circle circle, Triangle triangle) {
return triangleDetector.circleTriangleCollision(circle, triangle);
}
public boolean isQuadQuadCollision(Quad q1, Quad q2) {
float xDistance = Math.abs(q2.getPosition().x - q1.getPosition().x);
float yDistance = Math.abs(q2.getPosition().y - q1.getPosition().y);
if (xDistance >= q1.getWidth() / 2 + q2.getWidth() / 2)
return false;
if (yDistance >= q1.getHeight() / 2 + q2.getHeight() / 2)
return false;
return true;
}
public boolean isQuadTriangleCollision(Quad quad, Triangle triangle) {
boolean quadVertex1InTriangle = isVertexInTriangle(
new Vector(quad.getLeftEdge(), quad.getTopEdge()), triangle);
if (quadVertex1InTriangle)
return true;
boolean quadVertex2InTriangle = isVertexInTriangle(
new Vector(quad.getRightEdge(), quad.getTopEdge()), triangle);
if (quadVertex2InTriangle)
return true;
boolean quadVertex3InTriangle = isVertexInTriangle(
new Vector(quad.getRightEdge(), quad.getBottomEdge()), triangle);
if (quadVertex3InTriangle)
return true;
boolean quadVertex4InTriangle = isVertexInTriangle(
new Vector(quad.getLeftEdge(), quad.getBottomEdge()), triangle);
if (quadVertex4InTriangle)
return true;
boolean triangleVertex1InQuad = isVertexInQuad(triangle.getVertex1(), quad);
if (triangleVertex1InQuad)
return true;
boolean triangleVertex2InQuad = isVertexInQuad(triangle.getVertex2(), quad);
if (triangleVertex2InQuad)
return true;
boolean triangleVertex3InQuad = isVertexInQuad(triangle.getVertex3(), quad);
if (triangleVertex3InQuad)
return true;
return false;
}
public boolean isTriangleTriangleCollision(Triangle triangle1, Triangle triangle2) {
boolean triangle1Vertex1InTriangle2 = isVertexInTriangle(triangle1.getVertex1(), triangle2);
if (triangle1Vertex1InTriangle2)
return true;
boolean triangle1Vertex2InTriangle2 = isVertexInTriangle(triangle1.getVertex2(), triangle2);
if (triangle1Vertex2InTriangle2)
return true;
boolean triangle1Vertex3InTriangle2 = isVertexInTriangle(triangle1.getVertex3(), triangle2);
if (triangle1Vertex3InTriangle2)
return true;
boolean triangle2Vertex1InTriangle1 = isVertexInTriangle(triangle2.getVertex1(), triangle1);
if (triangle2Vertex1InTriangle1)
return true;
boolean triangle2Vertex2InTriangle1 = isVertexInTriangle(triangle2.getVertex2(), triangle1);
if (triangle2Vertex2InTriangle1)
return true;
boolean triangle2Vertex3InTriangle1 = isVertexInTriangle(triangle2.getVertex3(), triangle1);
if (triangle2Vertex3InTriangle1)
return true;
return false;
}
private boolean isVertexInTriangle(Vector vertex, Triangle triangle) {
Vector vertex1To2 = triangle.getVertex1().vectorTo(triangle.getVertex2());
Vector vertex2To3 = triangle.getVertex2().vectorTo(triangle.getVertex3());
Vector vertex3To1 = triangle.getVertex3().vectorTo(triangle.getVertex1());
Vector vertex1ToCenter = triangle.getVertex1().vectorTo(vertex);
Vector vertex2ToCenter = triangle.getVertex2().vectorTo(vertex);
Vector vertex3ToCenter = triangle.getVertex3().vectorTo(vertex);
boolean centerInsideV1V2 = vertex1To2.y * vertex1ToCenter.x - vertex1To2.x * vertex1ToCenter.y < 0;
boolean centerInsideV2V3 = vertex2To3.y * vertex2ToCenter.x - vertex2To3.x * vertex2ToCenter.y < 0;
boolean centerInsideV3V1 = vertex3To1.y * vertex3ToCenter.x - vertex3To1.x * vertex3ToCenter.y < 0;
return centerInsideV1V2 && centerInsideV2V3 && centerInsideV3V1;
}
private boolean isVertexInQuad(Vector vertex, Quad quad) {
return vertex.getX() >= quad.getLeftEdge() && vertex.getX() <= quad.getRightEdge() && vertex
.getY() >= quad.getBottomEdge() && vertex.getY() <= quad.getTopEdge();
}
public EntityCollisionData playerEntityCollision(Player player, Entity entity) {
Circle circle = new Circle(player);
Quad quad = entity;
if (isCircleQuadCollision(circle, quad)) {
Edge edge = circleQuadCollisionEdge(circle, player.getMovement(), quad,
entity.getMovement());
return new EntityCollisionData(entity, edge);
}
return new EntityCollisionData(null, null);
}
private Edge circleQuadCollisionEdge(Circle circle, Vector circleMovement, Quad quad, Vector quadMovement) {
Vector relativeMovement = circleMovement.translate(quadMovement);
//LEFT || TOP || BOTTOM
if (relativeMovement.x > 0) {
//LEFT || BOTTOM
if (relativeMovement.y > 0) {
float toLeftDistance = quad.getLeftEdge() - circle.getCenter().x;
float actualY = toLeftDistance * (relativeMovement.y / relativeMovement.x) + circle
.getCenter().y;
if (actualY < quad.getBottomEdge())
return Edge.BOTTOM;
else
return Edge.LEFT;
}
//LEFT || TOP
else if (relativeMovement.y < 0) {
float toLeftDistance = quad.getLeftEdge() - circle.getCenter().x;
float actualY = toLeftDistance * (relativeMovement.y / relativeMovement.x) + circle
.getCenter().y;
if (actualY < quad.getTopEdge())
return Edge.LEFT;
else
return Edge.TOP;
} else
return Edge.LEFT;
}
//RIGHT || TOP || BOTTOM
else if (relativeMovement.x < 0) {
//RIGHT || BOTTOM
if (relativeMovement.y > 0) {
float toRightDistance = quad.getRightEdge() - circle.getCenter().x;
float actualY = toRightDistance * (relativeMovement.y / relativeMovement.x) + circle
.getCenter().y;
if (actualY < quad.getBottomEdge())
return Edge.BOTTOM;
else
return Edge.RIGHT;
}
//RIGHT || TOP
else if (relativeMovement.y < 0) {
float toRightDistance = quad.getRightEdge() - circle.getCenter().x;
float actualY = toRightDistance * (relativeMovement.y / relativeMovement.x) + circle
.getCenter().y;
if (actualY < quad.getTopEdge())
return Edge.RIGHT;
else
return Edge.TOP;
} else
return Edge.RIGHT;
} else {
if (relativeMovement.y > 0)
return Edge.BOTTOM;
else if (relativeMovement.y < 0)
return Edge.TOP;
}
return Edge.NONE;
}
}

View File

@ -0,0 +1,104 @@
package de.frajul.endlessroll.entities.collision;
import de.frajul.endlessroll.entities.DestroyEffect;
import de.frajul.endlessroll.entities.Obstacle;
import de.frajul.endlessroll.entities.Player;
import de.frajul.endlessroll.entities.collectables.Energy;
import de.frajul.endlessroll.entities.collectables.Star;
import de.frajul.endlessroll.entities.collision.collisionData.EntityCollisionData;
import de.frajul.endlessroll.entities.collision.collisionData.ObstacleCollisionData;
import de.frajul.endlessroll.entities.collision.collisionData.PlayerCollisionData;
import de.frajul.endlessroll.entities.collision.collisionData.ToolCollisionData;
import de.frajul.endlessroll.entities.tools.Tool;
import de.frajul.endlessroll.main.game.Game;
import de.frajul.endlessroll.main.game.GameScene;
import de.frajul.endlessroll.main.game.Timer;
import de.frajul.endlessroll.main.physics.Physics;
/**
* Created by Julian on 02.01.2016.
*/
public class CollisionManager {
private Game game;
private Player player;
private Timer timer;
public CollisionManager(Game game) {
this.game = game;
}
//Check Obstacle always before tool, because at tool, player could be moved etc.
public void update(Physics physics, GameScene scene, Timer timer) {
physics.checkToolCollision(scene);
this.player = scene.getPlayer();
this.timer = timer;
PlayerCollisionData data = physics.getPlayerCollisionData(scene);
if (data.isTerrainCollision())
checkTerrainCollision(data.getTerrainCollisionData());
if (data.isCeilingCollision())
checkCeilingCollision(data.getCeilingCollisionData());
if (data.isObstacleCollision())
checkObstacleCollision(data.getObstacleCollisionData(), player.hasSuperPower());
if (data.isToolCollision())
checkToolCollision(data.getToolCollisionData());
if (data.isStarCollision())
game.onStarCollision((Star) data.getStarCollisionData().getEntity());
if (data.isEnergyCollision())
game.onEnergyCollision((Energy) data.getEnergyCollisionData().getEntity());
}
private void checkTerrainCollision(EntityCollisionData data) {
checkEntityCollision(data, -0.01f);
if (data.getEdge() != Edge.TOP)
game.onGameOver(true);
}
private void checkCeilingCollision(EntityCollisionData data) {
checkEntityCollision(data, -0.01f);
if (data.getEdge() == Edge.RIGHT || data.getEdge() == Edge.LEFT)
game.onGameOver(true);
}
private void checkToolCollision(ToolCollisionData data) {
for (Tool tool : data.getTools())
tool.onPlayerCollision(player, timer);
}
private void checkObstacleCollision(ObstacleCollisionData data, boolean playerHasSuperpower) {
for (EntityCollisionData entityData : data.getCollisions()) {
if (playerHasSuperpower) {
entityData.getEntity().destroy(DestroyEffect.EXPLOSION);
} else {
if (entityData.getEdge() != Edge.TOP || ((Obstacle) entityData.getEntity())
.isDeadly())
game.onGameOver(true);
else
checkEntityCollision(entityData, 0);
}
}
}
private void checkEntityCollision(EntityCollisionData data, float xBounceFactor) {
switch (data.getEdge()) {
case TOP:
player.getMovement().y = 0;
player.setToTerrain(data.getEntity().getTopEdge());
break;
case BOTTOM:
player.getMovement().y = 0;
player.setTopEdge(data.getEntity().getBottomEdge());
break;
case LEFT:
player.getMovement().x *= xBounceFactor;
player.getPosition().x = data.getEntity().getLeftEdge() - player.RADIUS;
break;
case RIGHT:
player.getMovement().x *= xBounceFactor;
player.getPosition().x = data.getEntity().getRightEdge() + player.RADIUS;
break;
}
}
}

View File

@ -0,0 +1,5 @@
package de.frajul.endlessroll.entities.collision;
public enum Edge {
LEFT, RIGHT, TOP, BOTTOM, NONE;
}

View File

@ -0,0 +1,30 @@
package de.frajul.endlessroll.entities.collision.collisionData;
import de.frajul.endlessroll.entities.Entity;
import de.frajul.endlessroll.entities.collision.Edge;
/**
* Created by Julian on 01.01.2016.
*/
public class EntityCollisionData {
private Entity entity;
private Edge edge;
public EntityCollisionData(Entity entity, Edge edge) {
this.entity = entity;
this.edge = edge;
}
public boolean isCollision() {
return entity != null && edge != null;
}
public Entity getEntity() {
return entity;
}
public Edge getEdge() {
return edge;
}
}

View File

@ -0,0 +1,23 @@
package de.frajul.endlessroll.entities.collision.collisionData;
import java.util.List;
/**
* Created by Julian on 04.01.2016.
*/
public class ObstacleCollisionData {
private List<EntityCollisionData> collisions;
public ObstacleCollisionData(List<EntityCollisionData> collisions) {
this.collisions = collisions;
}
public boolean isCollision() {
return collisions.size() > 0;
}
public List<EntityCollisionData> getCollisions() {
return collisions;
}
}

View File

@ -0,0 +1,71 @@
package de.frajul.endlessroll.entities.collision.collisionData;
/**
* Created by Julian on 05.12.2015.
*/
public class PlayerCollisionData {
private EntityCollisionData terrainCollision;
private EntityCollisionData ceilingCollision;
private ObstacleCollisionData obstacleCollision;
private ToolCollisionData toolCollision;
private EntityCollisionData starCollision;
private EntityCollisionData energyCollision;
public PlayerCollisionData(EntityCollisionData terrainCollision, EntityCollisionData ceilingCollision, ObstacleCollisionData obstacleCollision, ToolCollisionData toolCollision, EntityCollisionData starCollision, EntityCollisionData energyCollision) {
this.terrainCollision = terrainCollision;
this.ceilingCollision = ceilingCollision;
this.obstacleCollision = obstacleCollision;
this.toolCollision = toolCollision;
this.starCollision = starCollision;
this.energyCollision = energyCollision;
}
public boolean isTerrainCollision() {
return terrainCollision.isCollision();
}
public EntityCollisionData getTerrainCollisionData() {
return terrainCollision;
}
public boolean isCeilingCollision() {
return ceilingCollision.isCollision();
}
public EntityCollisionData getCeilingCollisionData() {
return ceilingCollision;
}
public boolean isObstacleCollision() {
return obstacleCollision.isCollision();
}
public ObstacleCollisionData getObstacleCollisionData() {
return obstacleCollision;
}
public boolean isToolCollision() {
return toolCollision.isCollision();
}
public ToolCollisionData getToolCollisionData() {
return toolCollision;
}
public boolean isStarCollision() {
return starCollision.isCollision();
}
public EntityCollisionData getStarCollisionData() {
return starCollision;
}
public boolean isEnergyCollision() {
return energyCollision.isCollision();
}
public EntityCollisionData getEnergyCollisionData() {
return energyCollision;
}
}

View File

@ -0,0 +1,25 @@
package de.frajul.endlessroll.entities.collision.collisionData;
import de.frajul.endlessroll.entities.tools.Tool;
import java.util.List;
/**
* Created by Julian on 21.02.2016.
*/
public class ToolCollisionData {
private List<Tool> tools;
public ToolCollisionData(List<Tool> tools) {
this.tools = tools;
}
public boolean isCollision() {
return tools.size() > 0;
}
public List<Tool> getTools() {
return tools;
}
}

View File

@ -0,0 +1,51 @@
package de.frajul.endlessroll.entities.collision.geometry;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.Player;
import de.frajul.endlessroll.entities.collision.CollisionDetector;
/**
* Created by Julian on 01.12.2015.
*/
public class Circle implements Geometry {
private Vector center;
private float radius;
public Circle(Player ball) {
this(new Vector(ball.getPosition()), ball.getWidth() / 2);
}
public Circle(Vector center, float radius) {
this.center = center;
this.radius = radius;
}
public Vector getCenter() {
return center;
}
public float getRadius() {
return radius;
}
public void setRadius(float radius) {
this.radius = radius;
}
@Override
public boolean isCollisionWithCircle(Circle circle, CollisionDetector collisionDetector){
return collisionDetector.isCircleCircleCollision(this, circle);
}
@Override
public boolean isCollisionWithQuad(Quad quad, CollisionDetector collisionDetector){
return collisionDetector.isCircleQuadCollision(this, quad);
}
@Override
public boolean isCollisionWithTriangle(Triangle triangle, CollisionDetector collisionDetector){
return collisionDetector.isCircleTriangleCollision(this, triangle);
}
}

View File

@ -0,0 +1,17 @@
package de.frajul.endlessroll.entities.collision.geometry;
import de.frajul.endlessroll.entities.collision.CollisionDetector;
/**
* Created by Julian on 28.02.2016.
*/
public interface Geometry {
boolean isCollisionWithCircle(Circle circle, CollisionDetector collisionDetector);
boolean isCollisionWithQuad(Quad quad, CollisionDetector collisionDetector);
boolean isCollisionWithTriangle(Triangle triangle, CollisionDetector collisionDetector);
}

View File

@ -0,0 +1,75 @@
package de.frajul.endlessroll.entities.collision.geometry;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.collision.CollisionDetector;
/**
* Created by Julian on 01.12.2015.
*/
public class Quad implements Geometry {
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;
}
@Override
public boolean isCollisionWithCircle(Circle circle, CollisionDetector collisionDetector) {
return collisionDetector.isCircleQuadCollision(circle, this);
}
@Override
public boolean isCollisionWithQuad(Quad quad, CollisionDetector collisionDetector) {
return collisionDetector.isQuadQuadCollision(this, quad);
}
@Override
public boolean isCollisionWithTriangle(Triangle triangle, CollisionDetector collisionDetector) {
return collisionDetector.isQuadTriangleCollision(this, triangle);
}
}

View File

@ -0,0 +1,61 @@
package de.frajul.endlessroll.entities.collision.geometry;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.collision.CollisionDetector;
import de.frajul.endlessroll.entities.tools.Ramp;
/**
* Created by Julian on 01.12.2015.
*/
public class Triangle implements Geometry {
//bottom right
private Vector vertex1;
//top right
private Vector vertex2;
//bottom left
private Vector vertex3;
public Triangle(Ramp ramp) {
Vector vertex1 = new Vector(ramp.getRightEdge(), ramp.getBottomEdge());
Vector vertex2 = new Vector(ramp.getRightEdge(), ramp.getTopEdge());
Vector vertex3 = new Vector(ramp.getLeftEdge(), ramp.getBottomEdge());
this.vertex1 = vertex1;
this.vertex2 = vertex2;
this.vertex3 = vertex3;
}
public Triangle(Vector vertex1, Vector vertex2, Vector vertex3) {
this.vertex1 = vertex1;
this.vertex2 = vertex2;
this.vertex3 = vertex3;
}
public Vector getVertex1() {
return vertex1;
}
public Vector getVertex2() {
return vertex2;
}
public Vector getVertex3() {
return vertex3;
}
@Override
public boolean isCollisionWithCircle(Circle circle, CollisionDetector collisionDetector) {
return collisionDetector.isCircleTriangleCollision(circle, this);
}
@Override
public boolean isCollisionWithQuad(Quad quad, CollisionDetector collisionDetector) {
return collisionDetector.isQuadTriangleCollision(quad, this);
}
@Override
public boolean isCollisionWithTriangle(Triangle triangle, CollisionDetector collisionDetector) {
return collisionDetector.isTriangleTriangleCollision(this, triangle);
}
}

View File

@ -0,0 +1,111 @@
package de.frajul.endlessroll.entities.particles;
import java.util.Random;
import de.frajul.endlessroll.data.Color;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.Entity;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.Range;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.Timeline;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.TintTimeline;
import de.frajul.endlessroll.main.game.Timer;
/**
* Created by Julian on 02.08.2016.
*/
public class Particle extends Entity {
private Color color;
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;
private Timeline windTimeline;
private Range wind;
private Timeline gravityTimeline;
private Range gravity;
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();
windTimeline = particleData.getWindTR().getTimeline();
wind = particleData.getWindTR().getRange().createNormalizedInstance(random);
gravityTimeline = particleData.getGravityTR().getTimeline();
gravity = particleData.getGravityTR().getRange().createNormalizedInstance(random);
}
public void update(Timer timer) {
if (active) {
passedLifetime += timer.getFrameTimeSeconds();
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)),
wind.createValue(random, windTimeline.getValueAtTime(lifetimePercent)),
gravity.createValue(random, gravityTimeline.getValueAtTime(lifetimePercent)));
super.setRotation(-rotation
.createValue(random, rotationTimeline.getValueAtTime(lifetimePercent)));
super.setAlpha(transparencyTimeline.getValueAtTime(lifetimePercent));
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;
}
public void setColor(Color color) {
this.color = color;
}
public Color getColor() {
return color;
}
}

View File

@ -0,0 +1,70 @@
package de.frajul.endlessroll.entities.particles;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.Range;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.Timeline;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.TimelineRange;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.TintTimeline;
/**
* 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;
private TimelineRange windTR;
private TimelineRange gravityTR;
public ParticleData(Range life, TimelineRange scaleTR, TimelineRange velocityTR, TimelineRange angleTR, TimelineRange rotationTR, Timeline transparencyT, TintTimeline tint, TimelineRange windTR, TimelineRange gravityTR) {
this.life = life;
this.scaleTR = scaleTR;
this.velocityTR = velocityTR;
this.angleTR = angleTR;
this.rotationTR = rotationTR;
this.transparencyT = transparencyT;
this.tint = tint;
this.windTR = windTR;
this.gravityTR = gravityTR;
}
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;
}
public TimelineRange getWindTR() {
return windTR;
}
public TimelineRange getGravityTR() {
return gravityTR;
}
}

View File

@ -0,0 +1,229 @@
package de.frajul.endlessroll.entities.particles;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.Options;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.Range;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.SpawnShape;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.Timeline;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.TimelineRange;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.TintTimeline;
import de.frajul.endlessroll.entities.textures.Texture;
import de.frajul.endlessroll.main.game.Timer;
import java.util.ArrayList;
import java.util.Collections;
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;
private TimelineRange wind;
private TimelineRange gravity;
//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 Options options;
private Texture texture;
private String textureName;
private Random random;
private List<ParticleSource> sources = Collections.synchronizedList(new ArrayList<ParticleSource>());
public ParticleEffect() {
this.random = new Random();
}
public void update(Timer timer) {
synchronized (sources) {
for (ParticleSource source : sources)
source.update(timer);
}
}
public ParticleData createParticleData() {
return new ParticleData(life.getRange(), scale, velocity, angle, rotation, transparency, tint, wind , gravity);
}
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 synchronized List<ParticleSource> getSources() {
return sources;
}
public TimelineRange getLife() {
return life;
}
public SpawnShape.Shape getSpawnShape() {
return spawnShape;
}
public TimelineRange getSpawnHeight() {
return spawnHeight;
}
public void deleteSources() {
synchronized (sources) {
for (ParticleSource source : sources)
source.kill();
sources.clear();
}
}
public TimelineRange getSpawnWidth() {
return spawnWidth;
}
}

View File

@ -0,0 +1,163 @@
package de.frajul.endlessroll.entities.particles;
import android.content.Context;
import de.frajul.endlessroll.entities.particles.attributes.Attribute;
import de.frajul.endlessroll.entities.particles.attributes.AttributeValueReader;
import de.frajul.endlessroll.entities.particles.attributes.ParticleAttributeType;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.ImagePath;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.Options;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.ParticleAttributeValueType;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.Range;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.SpawnShape;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.Timeline;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.TimelineRange;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.TintTimeline;
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

@ -0,0 +1,176 @@
package de.frajul.endlessroll.entities.particles;
import android.util.Log;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.SpawnShape;
import de.frajul.endlessroll.main.GameLog;
import de.frajul.endlessroll.main.game.Timer;
import de.frajul.endlessroll.rendering.Lock;
/**
* Created by Julian on 02.08.2016.
*/
public class ParticleSource {
private Vector position;
private ParticleEffect effect;
private Random random;
private boolean delayManuallySet = false;
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 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;
if (!delayManuallySet)
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.getFrameTimeSeconds();
lifePercent = passedTime / maxTime;
if (passedTime >= currentDelay) {
passedEmittPause += timer.getFrameTimeSeconds();
while (passedEmittPause >= emittPause) {
passedEmittPause -= emittPause;
emitt();
}
passedSecond += timer.getFrameTimeSeconds();
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);
if (!particle.isActive()) {
inactiveParticles.add(particle);
iter.remove();
} else {
particle.move(
new Vector(particle.getMovement()).mul(timer.getFrameTimeSeconds() / 1000));
}
}
activeParticleLock.unlock();
}
private void die() {
alife = false;
if (effect.getOptions().isContinuous())
start();
}
public void kill() {
alife = false;
}
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 || effect.getSpawnShape() == SpawnShape.Shape.LINE) {
float width, height;
if (spawnSize == null) {
width = effect.getSpawnWidth().getRange().createValue(random,
effect.getSpawnWidth().getTimeline().getValueAtTime(lifePercent));
height = effect.getSpawnHeight().getRange().createValue(random,
effect.getSpawnHeight().getTimeline().getValueAtTime(lifePercent));
} else {
width = spawnSize.getX() / ParticleSystem.TRANSFER_VALUE;
height = spawnSize.getY() / ParticleSystem.TRANSFER_VALUE;
}
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 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;
}
public void setSpawnSize(Vector spawnSize) {
this.spawnSize = spawnSize;
}
public void setPosition(Vector position) {
this.position = position;
}
public void setDelayMS(float delay) {
currentDelay = delay;
delayManuallySet = true;
}
}

View File

@ -0,0 +1,69 @@
package de.frajul.endlessroll.entities.particles;
import android.content.Context;
import de.frajul.endlessroll.entities.textures.TextureLoader;
import de.frajul.endlessroll.main.game.Timer;
/**
* Created by Julian on 02.08.2016.
*/
public class ParticleSystem {
public static final float TRANSFER_VALUE = 0.002f;
public final ParticleEffect stasis;
public final ParticleEffect testFire;
public final ParticleEffect colorChange;
public final ParticleEffect explosion;
public final ParticleEffect magnet;
public final ParticleEffect starCollect;
public final ParticleEffect energyCollect;
public final ParticleEffect firework;
public final ParticleEffect superPower;
private ParticleEffect[] effects;
private TextureLoader textureLoader;
public ParticleSystem(Context context) throws Exception {
this.textureLoader = new TextureLoader(context);
ParticleReader reader = new ParticleReader(context);
stasis = reader.read("particleEffects/stasis.pe");
testFire = reader.read("particleEffects/test_fire.pe");
colorChange = reader.read("particleEffects/colorChange.pe");
explosion = reader.read("particleEffects/explosion.pe");
magnet = reader.read("particleEffects/magnet.pe");
starCollect = reader.read("particleEffects/collectStar.pe");
energyCollect = reader.read("particleEffects/collectEnergy.pe");
firework = reader.read("particleEffects/firework.pe");
superPower = reader.read("particleEffects/superPower.pe");
effects = new ParticleEffect[]{stasis, testFire,colorChange, explosion, magnet, starCollect, energyCollect, firework, superPower};
}
public void update(Timer timer) {
synchronized (effects) {
for (ParticleEffect effect : effects)
effect.update(timer);
}
}
public void loadTextures() throws Exception {
synchronized (effects) {
for (ParticleEffect effect : effects)
effect.setTexture(
textureLoader.loadTexture("particleEffects/" + effect.getTextureName()));
}
}
public void deleteAllSources() {
synchronized (effects) {
for (ParticleEffect effect : effects) {
effect.deleteSources();
}
}
}
public synchronized ParticleEffect[] getEffects() {
return effects;
}
}

View File

@ -0,0 +1,33 @@
package de.frajul.endlessroll.entities.particles.attributes;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.ParticleAttributeValue;
import de.frajul.endlessroll.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

@ -0,0 +1,77 @@
package de.frajul.endlessroll.entities.particles.attributes;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.ImagePath;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.Options;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.ParticleAttributeValueType;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.Range;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.SpawnShape;
import de.frajul.endlessroll.entities.particles.attributes.attributeValues.Timeline;
import de.frajul.endlessroll.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

@ -0,0 +1,55 @@
package de.frajul.endlessroll.entities.particles.attributes;
import de.frajul.endlessroll.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

@ -0,0 +1,21 @@
package de.frajul.endlessroll.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

@ -0,0 +1,66 @@
package de.frajul.endlessroll.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

@ -0,0 +1,17 @@
package de.frajul.endlessroll.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

@ -0,0 +1,28 @@
package de.frajul.endlessroll.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

@ -0,0 +1,82 @@
package de.frajul.endlessroll.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

@ -0,0 +1,38 @@
package de.frajul.endlessroll.entities.particles.attributes.attributeValues;
/**
* Created by Julian on 02.08.2016.
*/
public class SpawnShape extends ParticleAttributeValue {
public enum Shape {
POINT("point"), SQUARE("square"), LINE("line");
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("spawnShape 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

@ -0,0 +1,54 @@
package de.frajul.endlessroll.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 = Math.abs(left.getTime() - time);
float rightDist = Math.abs(right.getTime() - time);
float totalDist = leftDist + rightDist;
float leftMultiplier = 1 - (leftDist / totalDist);
float rightMultiplier = 1 - (rightDist / totalDist);
return left.getValue() * leftMultiplier + right.getValue() * rightMultiplier;
}
return left.getValue();
}
return 0;
}
}

View File

@ -0,0 +1,23 @@
package de.frajul.endlessroll.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

@ -0,0 +1,31 @@
package de.frajul.endlessroll.entities.particles.attributes.attributeValues;
/**
* 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

@ -0,0 +1,58 @@
package de.frajul.endlessroll.entities.particles.attributes.attributeValues;
import de.frajul.endlessroll.data.Color;
import de.frajul.endlessroll.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) {
if (points.size() <= index) {
points.add(new TintTimelinePoint());
}
points.get(index).setValue(colorIndex, value);
}
public void setTimeOfPoint(int index, float 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 = Math.abs(left.getTime() - time);
float rightDist = Math.abs(right.getTime() - time);
float totalDist = leftDist + rightDist;
float leftMultiplier = leftDist / totalDist;
float rightMultiplier = rightDist / totalDist;
return left.getColor().interpolate(leftMultiplier,rightMultiplier, right.getColor());
}
return left.getColor();
}
return new Color();
}
}

View File

@ -0,0 +1,33 @@
package de.frajul.endlessroll.entities.particles.attributes.attributeValues;
import de.frajul.endlessroll.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

@ -0,0 +1,36 @@
package de.frajul.endlessroll.entities.textures;
/**
* Created by Julian on 11.12.2015.
*/
public class Texture {
private int id;
private int atlasWidth;
private int atlasHeight;
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;
}
}

View File

@ -0,0 +1,59 @@
package de.frajul.endlessroll.entities.textures;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import java.io.InputStream;
import de.frajul.endlessroll.main.GameLog;
/**
* 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);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_NEAREST);
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

@ -0,0 +1,45 @@
package de.frajul.endlessroll.entities.textures;
import android.content.Context;
import android.support.annotation.DrawableRes;
import de.frajul.endlessroll.R;
import de.frajul.endlessroll.entities.shapes.PlayerShape;
import de.frajul.endlessroll.entities.tools.ToolType;
import de.frajul.endlessroll.levels.worlds.World;
/**
* Created by Julian on 05.12.2015.
*/
public class TexturePack {
private TextureLoader loader;
public final Texture goal;
public final Texture playerArrow;
public final Texture star;
public final Texture energy;
public TexturePack(Context context) {
loader = new TextureLoader(context);
goal = loadTexture(R.drawable.guis_goal);
playerArrow = loadTexture(R.drawable.guis_playerarrow);
star = loadTexture(R.drawable.currency_star);
energy = loadAtlas(R.drawable.currency_energy_atlas, 2, 2);
PlayerShape.loadAllTextures(this);
ToolType.loadAllToolTextures(this);
World.loadAllSpecificTextures(this);
}
public Texture loadTexture(@DrawableRes int id) {
int texId = loader.loadTextureId(id, false);
return new Texture(texId, 1, 1);
}
public Texture loadAtlas(@DrawableRes int id, int atlasWidth, int atlasHeight) {
int texId = loader.loadTextureId(id, true);
return new Texture(texId, atlasWidth, atlasHeight);
}
}

View File

@ -0,0 +1,12 @@
package de.frajul.endlessroll.entities.tileLists;
import de.frajul.endlessroll.entities.textures.Texture;
@SuppressWarnings("serial")
public class Ceiling extends TileList {
public Ceiling(Texture texture) {
super(Type.CEILING, texture);
}
}

View File

@ -0,0 +1,12 @@
package de.frajul.endlessroll.entities.tileLists;
import de.frajul.endlessroll.entities.textures.Texture;
@SuppressWarnings("serial")
public class Terrain extends TileList {
public Terrain(Texture texture) {
super(TileList.Type.TERRAIN, texture);
}
}

View File

@ -0,0 +1,32 @@
package de.frajul.endlessroll.entities.tileLists;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.Entity;
import de.frajul.endlessroll.entities.textures.Texture;
import de.frajul.endlessroll.levels.TileData;
/**
* Created by Julian on 18.12.2015.
*/
public class Tile extends Entity {
public Tile(TileList.Type type, Texture texture, float edge, TileData data) {
this(type, texture, edge, data.getX(), data.getWidth());
}
public Tile(TileList.Type type, Texture texture, float edge, float x, float width) {
super(texture, new Vector(), width, 0);
super.height = type.calculateTileHeightFromEdge(edge);
super.position.x = x;
switch (type) {
case TERRAIN:
super.position.y = edge - super.height / 2;
break;
case CEILING:
super.position.y = edge + super.height / 2;
break;
}
}
}

View File

@ -0,0 +1,79 @@
package de.frajul.endlessroll.entities.tileLists;
import de.frajul.endlessroll.data.SynchronizedArrayList;
import de.frajul.endlessroll.entities.textures.Texture;
import de.frajul.endlessroll.levels.TileData;
import de.frajul.endlessroll.levels.worlds.World;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("serial")
public class TileList extends SynchronizedArrayList<Tile> {
public enum Type {
TERRAIN, CEILING;
public float calculateTileHeightFromEdge(float edge) {
switch (this) {
case TERRAIN:
return 1 + edge;
case CEILING:
return 1 - edge;
}
return 0;
}
}
private Type type;
private Texture texture;
private float edge;
private boolean endless;
public TileList(Type type, Texture texture) {
this.type = type;
this.texture = texture;
}
public void loadData(World world, float edge, List<TileData> tileData) {
this.texture = world.getTerrainTexture();
if (type == Type.CEILING)
this.texture = world.getCeilingTexture();
this.endless = false;
super.clear();
for (TileData data : tileData)
super.add(new Tile(type, texture, edge, data));
this.edge = edge;
if (edge >= 1 || edge <= -1)
super.clear();
}
public void createEndless(World world, float edge) {
loadData(world, edge, new ArrayList<TileData>());
super.add(createEndlessTile(0));
this.endless = true;
}
public void update(float cameraX) {
if (!super.isEmpty()) {
if (endless) {
Tile last = super.get(super.size() - 1);
if (last.getRightEdge() - cameraX < 3)
super.add(createEndlessTile(last.getRightEdge() + 2.5f));
}
if (super.get(0).getRightEdge() - cameraX < -3) {
super.remove(0);
}
}
}
private Tile createEndlessTile(float x) {
return new Tile(type, texture, edge, x, 5);
}
public float getEdge() {
return edge;
}
}

View File

@ -0,0 +1,67 @@
package de.frajul.endlessroll.entities.tools;
import java.util.List;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.DestroyEffect;
import de.frajul.endlessroll.entities.Obstacle;
import de.frajul.endlessroll.entities.Player;
import de.frajul.endlessroll.entities.collision.CollisionDetector;
import de.frajul.endlessroll.entities.collision.geometry.Geometry;
import de.frajul.endlessroll.entities.collision.geometry.Quad;
import de.frajul.endlessroll.main.game.Timer;
/**
* Created by Julian on 20.02.2016.
*/
public class Bomb extends Tool {
public final float RANGE = 1;
private float delta;
private boolean exploding = false;
public Bomb(Vector position) {
super(ToolType.BOMB, position, .29f, .29f, false, false);
animation.setIndexSequence(new int[]{0, 1, 2});
animation.setLooping(false);
animation.setRequiredDelta(
(int) (ToolType.BOMB.getCurrentUpgradeValue(ToolUpgradeType.DURATION) / 3));
}
@Override
public void update(Timer timer) {
super.update(timer);
delta += timer.getFrameTimeSeconds();
if (delta >= ToolType.BOMB.getCurrentUpgradeValue(ToolUpgradeType.DURATION))
exploding = true;
}
@Override
public void onPlayerCollision(Player player, Timer timer) {
}
@Override
protected Geometry createWorldCollisionBounds() {
return this;
}
@Override
protected Geometry createPlayerCollisionBounds() {
return this;
}
public boolean isExploding() {
return exploding;
}
public void explode(List<Obstacle> obstacles, CollisionDetector detector) {
float range = RANGE * ToolType.BOMB.getCurrentUpgradeValue(ToolUpgradeType.RANGE) / 100;
Quad explosionRange = new Quad(new Vector(super.getPosition()), range, range);
for (Obstacle obstacle : obstacles) {
if (detector.isQuadQuadCollision(obstacle, explosionRange))
obstacle.destroy(DestroyEffect.EXPLOSION);
}
super.destroy(DestroyEffect.EXPLOSION);
}
}

View File

@ -0,0 +1,59 @@
package de.frajul.endlessroll.entities.tools;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.DestroyEffect;
import de.frajul.endlessroll.entities.Player;
import de.frajul.endlessroll.entities.collision.geometry.Circle;
import de.frajul.endlessroll.entities.collision.geometry.Geometry;
import de.frajul.endlessroll.entities.particles.ParticleSource;
import de.frajul.endlessroll.entities.particles.ParticleSystem;
import de.frajul.endlessroll.main.game.Timer;
/**
* Created by Julian on 11.02.2016.
*/
public class Magnet extends Tool {
private ParticleSource particleSource;
public Magnet(Vector position, ParticleSystem particleSystem) {
super(ToolType.MAGNET, position, .24f, .24f, false, false);
animation.setRequiredDelta(300);
animation.setIndexSequence(new int[]{1, 1, 0});
animation.setLooping(true);
super.setFloating(true);
particleSource = new ParticleSource(new Vector(position), particleSystem.magnet);
particleSource.start();
}
@Override
public void destroy(DestroyEffect destroyEffect) {
super.destroy(destroyEffect);
particleSource.kill();
}
@Override
public void onPlayerCollision(Player player, Timer timer) {
float fromPlayerDistance = player.getPosition().vectorTo(super.getPosition()).length();
float fromPlayerDistanceGreaterFour = Math.max(fromPlayerDistance, 0.4f);
float fromPlayerYDistance = super.getPosition().y - player.getPosition().y;
float force = 0.0000012f / (fromPlayerDistanceGreaterFour * fromPlayerDistanceGreaterFour);
force *= ToolType.MAGNET.getCurrentUpgradeValue(ToolUpgradeType.FORCE) / 100;
force *= timer.getFrameTimeSeconds();
if (fromPlayerYDistance < 0) {
force = -force;
}
player.addForce(force);
}
@Override
protected Geometry createWorldCollisionBounds() {
return this;
}
@Override
protected Geometry createPlayerCollisionBounds() {
return new Circle(super.getPosition(), 2);
}
}

View File

@ -0,0 +1,64 @@
package de.frajul.endlessroll.entities.tools;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.Player;
import de.frajul.endlessroll.entities.collision.geometry.Geometry;
import de.frajul.endlessroll.entities.collision.geometry.Triangle;
import de.frajul.endlessroll.main.game.Timer;
/**
* Created by Julian on 29.11.2015.
*/
public class Ramp extends Tool {
public Ramp(Vector position) {
super(ToolType.RAMP, position, .4f, .35f, true, true);
animation.setLooping(true);
}
public float getGradient() {
return super.getHeight() / super.getWidth();
}
public float getHeightAt(float x, boolean clamp) {
float ratio = (x - getLeftEdge()) / super.getWidth();
if (clamp) {
if (ratio < 0)
return getBottomEdge();
if (ratio > 1)
return getTopEdge();
}
return getBottomEdge() + super.getHeight() * ratio;
}
@Override
public void onPlayerCollision(Player player, Timer timer) {
float necessaryY = calcNecessaryPlayerY(player);
player.getPosition().y = necessaryY;
float acceleration = player.getMovement().x * getGradient();
player.setGravityForce(0);
player.getMovement().setY(0);
player.addForce(acceleration);
}
private float calcNecessaryPlayerY(Player player) {
float normalM = -1 / getGradient();
Vector normalToCircleCenter = new Vector(-1, -normalM).normalize();
normalToCircleCenter.mul(player.RADIUS);
float normalX = player.getPosition().x - normalToCircleCenter.x;
float normalY = getHeightAt(normalX, false);
return normalY + normalToCircleCenter.y;
}
@Override
protected Geometry createWorldCollisionBounds() {
return new Triangle(this);
}
@Override
protected Geometry createPlayerCollisionBounds() {
return new Triangle(this);
}
}

View File

@ -0,0 +1,48 @@
package de.frajul.endlessroll.entities.tools;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.Player;
import de.frajul.endlessroll.entities.collision.geometry.Geometry;
import de.frajul.endlessroll.entities.collision.geometry.Quad;
import de.frajul.endlessroll.main.game.Timer;
/**
* Created by Julian on 04.01.2016.
*/
public class Spring extends Tool {
private boolean hasYetCollided = false;
public Spring(Vector position) {
super(ToolType.SPRING, position, .3f, .35f, true, true);
animation.setIndexSequence(new int[]{1, 0, 0, 3, 3, 3, 1});
animation.setRequiredDelta(80);
}
@Override
public void update(Timer timer) {
if (hasYetCollided)
super.update(timer);
}
@Override
public void onPlayerCollision(Player player, Timer timer) {
if (!hasYetCollided) {
hasYetCollided = true;
player.clearAllForces();
player.getMovement().setY(0);
player.addForce(.0022f);
}
}
@Override
protected Geometry createWorldCollisionBounds() {
return this;
}
@Override
protected Geometry createPlayerCollisionBounds() {
return new Quad(super.getPosition(), .2f, .1f);
}
}

View File

@ -0,0 +1,57 @@
package de.frajul.endlessroll.entities.tools;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.AnimatedEntity;
import de.frajul.endlessroll.entities.Player;
import de.frajul.endlessroll.entities.collision.geometry.Geometry;
import de.frajul.endlessroll.main.game.Timer;
/**
* Created by Julian on 04.01.2016.
*/
public abstract class Tool extends AnimatedEntity {
private boolean placedByRightEdge;
private boolean updateBounds;
private Geometry worldCollisionBounds;
private Geometry playerCollisionBounds;
private boolean floating = false;
public Tool(ToolType type, Vector position, float width, float height, boolean updateBounds, boolean placedByRightEdge) {
super(type.getToolTexture(), position, width, height);
this.updateBounds = updateBounds;
this.placedByRightEdge = placedByRightEdge;
worldCollisionBounds = createWorldCollisionBounds();
playerCollisionBounds = createPlayerCollisionBounds();
}
public abstract void onPlayerCollision(Player player, Timer timer);
protected abstract Geometry createWorldCollisionBounds();
protected abstract Geometry createPlayerCollisionBounds();
public Geometry getWorldCollisionBounds() {
if (updateBounds)
return createWorldCollisionBounds();
return worldCollisionBounds;
}
public Geometry getPlayerCollisionBounds() {
if (updateBounds)
return createPlayerCollisionBounds();
return playerCollisionBounds;
}
public void setFloating(boolean floating) {
this.floating = floating;
}
public boolean isFloating() {
return floating;
}
public boolean isPlacedByRightEdge() {
return placedByRightEdge;
}
}

View File

@ -0,0 +1,42 @@
package de.frajul.endlessroll.entities.tools;
import de.frajul.endlessroll.R;
/**
* Created by Julian on 16.07.2016.
*/
public class ToolSlot {
private ToolType toolType;
private boolean locked;
public ToolSlot(ToolType toolType, boolean locked) {
this.toolType = toolType;
this.locked = locked;
}
public ToolType getToolType() {
return toolType;
}
public int getDrawable() {
if (locked)
return R.drawable.tools_button_locked;
else if(toolType != null)
return toolType.getButtonDrawable();
else
return R.drawable.tools_button_empty;
}
public void setToolType(ToolType toolType) {
this.toolType = toolType;
}
public boolean isLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
}

View File

@ -0,0 +1,194 @@
package de.frajul.endlessroll.entities.tools;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import java.util.Arrays;
import java.util.List;
import de.frajul.endlessroll.R;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.particles.ParticleSystem;
import de.frajul.endlessroll.entities.textures.Texture;
import de.frajul.endlessroll.entities.textures.TexturePack;
import de.frajul.endlessroll.sounds.SoundManager;
public enum ToolType {
//Check newInstance when new Tool is added!
RAMP(R.string.tool_name_ramp, R.string.tool_description_ramp, R.drawable.tools_ramp,
R.drawable.tools_ramp_button, R.raw.ramp, 0, 1, 5,
new ToolUpgrade(ToolUpgradeType.COOLDOWN, 3000, 1000)),
SPRING(R.string.tool_name_spring, R.string.tool_description_spring, R.drawable.tools_spring,
R.drawable.tools_spring_button, R.raw.ramp, 5, 2, 5,
new ToolUpgrade(ToolUpgradeType.COOLDOWN, 4000, 2000)),
BOMB(R.string.tool_name_bomb, R.string.tool_description_bomb, R.drawable.tools_bomb,
R.drawable.tools_bomb_button, R.raw.ramp, 12, 4, 5,
new ToolUpgrade(ToolUpgradeType.COOLDOWN, 6000, 4000),
new ToolUpgrade(ToolUpgradeType.DURATION, 1200, 400),
new ToolUpgrade(ToolUpgradeType.RANGE, 100, 200)),
MAGNET(R.string.tool_name_magnet, R.string.tool_description_magnet, R.drawable.tools_magnet,
R.drawable.tools_magnet_button, R.raw.ramp, 10, 4, 5,
new ToolUpgrade(ToolUpgradeType.COOLDOWN, 6000, 4000),
new ToolUpgrade(ToolUpgradeType.FORCE, 100, 500)),
POWER_MUSHROOM(R.string.tool_name_power_mushroom, R.string.tool_description_power_mushroom,
R.drawable.tools_power_mushroom, R.drawable.tools_power_mushroom_button, R.raw.ramp, 5,
5, 7, new ToolUpgrade(ToolUpgradeType.COOLDOWN, 15000, 11000),
new ToolUpgrade(ToolUpgradeType.DURATION, 5000, 10000)),
STASIS(R.string.tool_name_stasis, R.string.tool_description_stasis, R.drawable.tools_stasis,
R.drawable.tools_stasis_button, R.raw.ramp, 15, 6, 6,
new ToolUpgrade(ToolUpgradeType.COOLDOWN, 8000, 5000),
new ToolUpgrade(ToolUpgradeType.FORCE, 1, 2),
new ToolUpgrade(ToolUpgradeType.SIZE, 100, 200));
@StringRes
private final int name;
@StringRes
private final int description;
private final int toolTextureId;
private final int buttonDrawable;
private final int placingSoundId;
private final int buyPrice;
private final int upgradePrice;
private final int maxUpgradeLevel;
private final List<ToolUpgrade> upgrades;
private Texture toolTexture = null;
private int placingSound = -1;
private boolean bought;
private int currentUpgradeLevel = 1;
ToolType(@StringRes int name, @StringRes int description, int toolTextureId, int buttonDrawable, int placingSoundId, int buyPrice, int upgradePrice, int maxUpgradeLevel, ToolUpgrade... upgrades) {
this.name = name;
this.description = description;
this.toolTextureId = toolTextureId;
this.buttonDrawable = buttonDrawable;
this.placingSoundId = placingSoundId;
this.buyPrice = buyPrice;
this.upgradePrice = upgradePrice;
this.maxUpgradeLevel = maxUpgradeLevel;
this.upgrades = Arrays.asList(upgrades);
}
@Nullable
public Tool newInstance(Vector position, ParticleSystem particleSystem) {
Tool tool = null;
switch (this) {
case RAMP:
tool = new Ramp(position);
break;
case SPRING:
tool = new Spring(position);
break;
case MAGNET:
tool = new Magnet(position, particleSystem);
break;
case BOMB:
tool = new Bomb(position);
break;
case POWER_MUSHROOM:
tool = new PowerMushroom(position);
break;
case STASIS:
tool = new Stasis(position,particleSystem);
break;
}
if (tool != null && tool.isPlacedByRightEdge())
tool.move(new Vector(-tool.getWidth() / 2, 0));
return tool;
}
public static void loadAllPlacingSounds(SoundManager soundManager) {
for (ToolType type : values())
type.loadPlacingSound(soundManager);
}
public static void loadAllToolTextures(TexturePack texturePack) {
for (ToolType type : values())
type.loadToolTexture(texturePack);
}
private void loadPlacingSound(SoundManager soundManager) {
if (placingSoundId == -1)
return;
placingSound = soundManager.loadSound(placingSoundId);
}
private void loadToolTexture(TexturePack texturePack) {
if (toolTextureId == -1)
return;
if (this != POWER_MUSHROOM)
toolTexture = texturePack.loadAtlas(toolTextureId, 2, 2);
else
toolTexture = texturePack.loadTexture(toolTextureId);
}
public Texture getToolTexture() {
return toolTexture;
}
public int getButtonDrawable() {
return buttonDrawable;
}
public int getPlacingSound() {
return placingSound;
}
@StringRes
public int getName() {
return name;
}
@StringRes
public int getDescription() {
return description;
}
public void setBought(boolean bought) {
this.bought = bought;
}
public boolean isBought() {
if (this == RAMP)
bought = true;
return bought;
}
public void upgrade() {
currentUpgradeLevel++;
}
public void reset() {
setBought(false);
currentUpgradeLevel = 1;
}
public int getBuyPrice() {
return buyPrice;
}
public int getUpgradePrice() {
return upgradePrice + currentUpgradeLevel - 1;
}
public int getCurrentUpgradeLevel() {
return currentUpgradeLevel;
}
public void setCurrentUpgradeLevel(int currentUpgradeLevel) {
this.currentUpgradeLevel = currentUpgradeLevel;
}
public float getCurrentUpgradeValue(ToolUpgradeType type) {
for (ToolUpgrade upgrade : upgrades)
if (upgrade.getType().equals(type))
return upgrade.getValueAtLevel(currentUpgradeLevel, maxUpgradeLevel);
return -1;
}
public boolean isAtMaxUpgradeLevel() {
return currentUpgradeLevel == maxUpgradeLevel;
}
}

View File

@ -0,0 +1,22 @@
package de.frajul.endlessroll.levels;
import org.simpleframework.xml.Attribute;
/**
* Created by Julian on 27.11.2015.
*/
public class Gap {
@Attribute
private float leftEdge;
@Attribute
private float rightEdge;
public float getLeftEdge() {
return leftEdge;
}
public float getRightEdge() {
return rightEdge;
}
}

View File

@ -0,0 +1,147 @@
package de.frajul.endlessroll.levels;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import java.util.List;
/**
* Created by Julian on 07.12.2015.
*/
public class Level {
@Attribute
private int packId;
@Attribute
private int id;
@Attribute
private float goalX;
@Attribute
private float startSpeed;
@Attribute
private float endSpeed;
@Attribute
private float terrainEdge;
@Attribute
private float ceilingEdge;
@ElementList
private List<TileData> terrainTiles;
@ElementList
private List<TileData> ceilingTiles;
@ElementList
private List<ObstacleData> obstacles;
@ElementList
private List<PositionData> stars;
@Element(required = false)
private PositionData energy;
private boolean finished = false;
private boolean locked = true;
private boolean[] collectedStars = {false, false, false};
private boolean energyCollected = false;
public int getPackId() {
return packId;
}
public int getId() {
return id;
}
public float getGoalX() {
return goalX;
}
public float getStartSpeed() {
return startSpeed;
}
public float getEndSpeed() {
return endSpeed;
}
public float getTerrainEdge() {
return terrainEdge;
}
public float getCeilingEdge() {
return ceilingEdge;
}
public List<TileData> getTerrainTiles() {
return terrainTiles;
}
public List<TileData> getCeilingTiles() {
return ceilingTiles;
}
public List<ObstacleData> getObstacles() {
return obstacles;
}
public List<PositionData> getStars() {
return stars;
}
public PositionData getEnergyData() {
return energy;
}
public boolean isLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
public boolean isFinished() {
return finished;
}
public void setFinished(boolean finished) {
this.finished = finished;
}
public boolean isStarCollected(int index) {
return collectedStars[index];
}
public void setStarCollected(int index, boolean collected) {
collectedStars[index] = collected;
}
public String getCollectedStarCodeForSQL() {
String code = "";
for (int i = 0; i < 3; i++)
code += collectedStars[i] ? (i + 1) + "" : "";
return code;
}
public void setCollectedStarsFromSQL(String code) {
for (int i = 0; i < 3; i++)
collectedStars[i] = code.contains((i + 1) + "");
}
public boolean[] getCollectedStars() {
return collectedStars;
}
public boolean isEnergyCollected() {
return energyCollected;
}
public void setEnergyCollected(boolean collected) {
this.energyCollected = collected;
}
public void reset() {
finished = false;
locked = true;
collectedStars = new boolean[]{false, false, false};
energyCollected = false;
}
}

View File

@ -0,0 +1,117 @@
package de.frajul.endlessroll.levels;
import android.content.Context;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import de.frajul.endlessroll.R;
import de.frajul.endlessroll.main.DataStorageHandler;
import de.frajul.endlessroll.main.GameLog;
import de.frajul.endlessroll.sqlDatabase.MyDatabase;
public class LevelManager extends ArrayList<LevelPack> {
public LevelManager(Context context, DataStorageHandler dataStorageHandler) throws Exception {
String[] worldNames = context.getResources().getStringArray(R.array.world_names);
String[] assets = context.getAssets().list("levelpacks");
for (String asset : assets) {
try {
LevelPack pack = loadLevelPack(context, "levelpacks/" + asset);
pack.setName(worldNames[pack.getId()]);
MyDatabase database = dataStorageHandler.getDatabase();
database.open();
for (Level level : pack.getLevels())
database.readLevelProgress(level);
database.readLevelPackLocked(pack);
database.close();
pack.tryToUnlockFirstLevel();
if (pack.getId() == 1)
pack.setLocked(false);
super.add(pack);
} catch (Exception e) {
GameLog.e(e);
}
}
sortPacks();
}
private void sortPacks() {
Collections.sort(this, packComparator);
}
private LevelPack loadLevelPack(Context context, String name) throws Exception {
try {
InputStream source = context.getAssets().open(name);
Serializer serializer = new Persister();
return serializer.read(LevelPack.class, source);
} catch (Exception e) {
throw new Exception("Could not load levelPack \"" + name + "\"", e);
}
}
public int getTotalCollectedStarCount(){
int count = 0;
for(LevelPack levelPack : this)
count += levelPack.getCollectedStarCount();
return count;
}
public int getTotalCollectedEnergyCount(){
int count = 0;
for(LevelPack levelPack : this)
count += levelPack.getCollectedEnergyCount();
return count;
}
public LevelPack getNextLevelPack(LevelPack currentPack) {
int searchedId = currentPack.getId() + 1;
for (LevelPack pack : this) {
if (pack.getId() == searchedId)
return pack;
}
return null;
}
public LevelPack getPackWithId(int id) {
for (LevelPack pack : this)
if (pack.getId() == id)
return pack;
return null;
}
public void reset() {
for (LevelPack pack : this) {
pack.reset();
if (pack.getId() == 1)
pack.setLocked(false);
}
}
private Comparator<LevelPack> packComparator = new Comparator<LevelPack>() {
@Override
public int compare(LevelPack lhs, LevelPack rhs) {
return lhs.getId() - rhs.getId();
}
};
//CHEAT
public void unlockAllPacks() {
for (LevelPack levelPack : this)
levelPack.setLocked(false);
}
public void unlockAllLevels() {
for (LevelPack levelPack : this) {
for (Level level : levelPack.getLevels())
level.setLocked(false);
}
}
}

View File

@ -0,0 +1,120 @@
package de.frajul.endlessroll.levels;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import java.util.List;
import de.frajul.endlessroll.levels.worlds.World;
/**
* Created by Julian on 07.12.2015.
*/
@Root
public class LevelPack {
@Attribute
private int id;
@Element
private World world;
@ElementList
private List<Level> levels;
private String name;
private boolean locked = true;
public int getId() {
return id;
}
public List<Level> getLevels() {
return levels;
}
public World getWorld() {
return world;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getFinishedLevelCount() {
int count = 0;
for (Level level : levels)
if (level.isFinished())
count++;
return count;
}
public int getCollectedStarCount() {
int count = 0;
for (Level level : levels)
count += level.getCollectedStarCodeForSQL().length();
return count;
}
public int getAvailableStars() {
return levels.size() * 3;
}
public int getCollectedEnergyCount() {
int count = 0;
for (Level level : levels)
count += level.isEnergyCollected() ? 1 : 0;
return count;
}
public int getAvailableEnergy() {
return levels.size();
}
public void tryToUnlockFirstLevel() {
Level firstLevel = getLevel(1);
if (firstLevel != null)
firstLevel.setLocked(false);
}
public Level getLevel(int id) {
for (Level level : levels)
if (level.getId() == id)
return level;
return null;
}
public Level getNextLevel(Level currentLevel) {
return getLevel(currentLevel.getId() + 1);
}
public boolean isAllLevelsFinished() {
for (Level level : levels)
if (!level.isFinished())
return false;
return true;
}
public boolean isLastLevel(Level level) {
return getNextLevel(level) == null;
}
public void reset() {
for (Level level : levels)
level.reset();
setLocked(true);
tryToUnlockFirstLevel();
}
public void setLocked(boolean locked) {
this.locked = locked;
}
public boolean isLocked() {
return locked;
}
}

View File

@ -0,0 +1,56 @@
package de.frajul.endlessroll.levels;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.Vertex;
import org.simpleframework.xml.Attribute;
public class MoveComponent {
@Attribute
private float width;
@Attribute
private float height;
@Attribute
private float x;
@Attribute
private float y;
@Attribute
private float speed;
public float getWidth() {
return width;
}
public float getHeight() {
return height;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getSpeed() {
return speed;
}
public Vector getPositionOfVertex(Vertex vertex) {
float x = this.x + (width / 2f) * vertex.getX();
float y = this.y + (height / 2f) * vertex.getY();
return new Vector(x, y);
}
public void shrink(Vector value) {
this.width -= value.getX();
this.height -= value.getY();
if (width < 0)
width = 0;
if (height < 0)
height = 0;
}
}

View File

@ -0,0 +1,93 @@
package de.frajul.endlessroll.levels;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
/**
* Created by Julian on 07.12.2015.
*/
public class ObstacleData {
@Attribute
private boolean floating;
@Attribute
private boolean moving;
@Attribute
private boolean deadly;
@Attribute
private float leftEdge;
@Attribute
private float rightEdge;
@Attribute
private float height;
@Attribute
private float y;
@Element(required = false)
private MoveComponent moveComponent;
public boolean isFloating() {
return floating;
}
public boolean isMoving() {
return moving;
}
public boolean isDeadly() {
return deadly;
}
public float getX() {
return leftEdge + getWidth() / 2;
}
public float getWidth() {
return rightEdge - leftEdge;
}
public float getHeight() {
return height;
}
public float getY() {
return y;
}
public MoveComponent getMoveComponent() {
return moveComponent;
}
//Only for glTestScreen
public void setFloating(boolean floating) {
this.floating = floating;
}
public void setMoving(boolean moving) {
this.moving = moving;
}
public void setDeadly(boolean deadly) {
this.deadly = deadly;
}
public void setLeftEdge(float leftEdge) {
this.leftEdge = leftEdge;
}
public void setRightEdge(float rightEdge) {
this.rightEdge = rightEdge;
}
public void setHeight(float height) {
this.height = height;
}
public void setY(float y) {
this.y = y;
}
public void setMoveComponent(MoveComponent moveComponent) {
this.moveComponent = moveComponent;
}
}

View File

@ -0,0 +1,23 @@
package de.frajul.endlessroll.levels;
import org.simpleframework.xml.Attribute;
/**
* Created by Julian on 27.01.2017.
*/
public class PositionData {
@Attribute
private float x;
@Attribute
private float y;
public float getX() {
return x;
}
public float getY() {
return y;
}
}

View File

@ -0,0 +1,19 @@
package de.frajul.endlessroll.levels;
import org.simpleframework.xml.Attribute;
public class TileData {
@Attribute
private float x;
@Attribute
private float width;
public float getX() {
return x;
}
public float getWidth() {
return width;
}
}

View File

@ -0,0 +1,80 @@
package de.frajul.endlessroll.levels.worlds;
import android.support.annotation.DrawableRes;
import de.frajul.endlessroll.R;
import de.frajul.endlessroll.entities.textures.Texture;
import de.frajul.endlessroll.entities.textures.TexturePack;
/**
* Created by Julian on 14.11.2016.
*/
public enum World {
GRASSLANDS("Grasslands", R.drawable.world_previews_grass, R.drawable.backgrounds_game_grass, R.drawable.terrain_t_grass, R.drawable.terrain_c_grass, R.drawable.obstacles_grass),
TESTCAVE("Testcave", R.drawable.world_previews_grass, R.drawable.backgrounds_game_cave, R.drawable.terrain_t_grass, R.drawable.terrain_c_grass, R.drawable.obstacles_grass),
ICY_MOUNTAINS("Icy Mountains", R.drawable.world_previews_grass, R.drawable.backgrounds_game_mountains, R.drawable.terrain_t_grass, R.drawable.terrain_c_grass, R.drawable.obstacles_grass);
private String name;
@DrawableRes
private int previewId;
@DrawableRes
private int backgroundId;
@DrawableRes
private int terrainId;
@DrawableRes
private int ceilingId;
@DrawableRes
private int obstacleId;
private Texture background;
private Texture terrain;
private Texture ceiling;
private Texture obstacle;
World(String name, @DrawableRes int previewId, @DrawableRes int backgroundId, @DrawableRes int terrainId, @DrawableRes int ceilingId, @DrawableRes int obstacleId) {
this.name = name;
this.previewId = previewId;
this.backgroundId = backgroundId;
this.terrainId = terrainId;
this.ceilingId = ceilingId;
this.obstacleId = obstacleId;
}
public static void loadAllSpecificTextures(TexturePack texturePack) {
for (World world : values())
world.loadSpecificTextures(texturePack);
}
private void loadSpecificTextures(TexturePack texturePack) {
background = texturePack.loadTexture(backgroundId);
terrain = texturePack.loadTexture(terrainId);
ceiling = texturePack.loadTexture(ceilingId);
obstacle = texturePack.loadAtlas(obstacleId, 8, 8);
}
public String getName() {
return name;
}
public int getPreviewId() {
return previewId;
}
public Texture getBackgroundTexture() {
return background;
}
public Texture getTerrainTexture() {
return terrain;
}
public Texture getCeilingTexture() {
return ceiling;
}
public Texture getObstacleTexture() {
return obstacle;
}
}

View File

@ -0,0 +1,12 @@
package de.frajul.endlessroll.main;
import de.frajul.endlessroll.user.User;
/**
* Created by Julian on 15.07.2016.
*/
public class DataSafer {
private User user;
}

View File

@ -0,0 +1,105 @@
package de.frajul.endlessroll.main;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import de.frajul.endlessroll.entities.shapes.PlayerShape;
import de.frajul.endlessroll.entities.tools.ToolType;
import de.frajul.endlessroll.sqlDatabase.MyDatabase;
import de.frajul.endlessroll.user.ToolSlotSettings;
import de.frajul.endlessroll.user.User;
/**
* Created by Julian on 25.04.2016.
*/
public class DataStorageHandler {
private final String PREFERENCES_NAME = "GamePreferences";
private final String SOUND_ON = "Sound";
private final String USER_EP = "EP";
private final String USER_LEVEL = "Level";
private final String USER_STARS = "Stars";
private final String USER_ENERGY = "Energy";
private final String USER_TOOL_1 = "Tool1";
private final String USER_TOOL_2 = "Tool2";
private final String USER_TOOL_3 = "Tool3";
private final String USER_TOOL_4 = "Tool4";
private final String USER_TOOLS_LOCKED = "ToolsLocked";
private final String USER_PLAYER_SHAPE = "PlayerShape";
private final String TOOL_SHOP_TUTORIAL_PART_1_FINISHED = "ToolShopTutorialPart1Finished";
private SharedPreferences preferences;
private MyDatabase database;
public DataStorageHandler(Activity activity) {
preferences = activity.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
database = new MyDatabase(activity);
}
public boolean readIsSoundOn() {
return preferences.getBoolean(SOUND_ON, false);
}
public void writeSoundOn(boolean soundOn) {
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(SOUND_ON, soundOn);
editor.apply();
}
public User readUserData(User.LvUpListener lvUpListener) throws Exception {
int ep = preferences.getInt(USER_EP, 0);
int level = preferences.getInt(USER_LEVEL, 1);
int stars = preferences.getInt(USER_STARS, 0);
int energy = preferences.getInt(USER_ENERGY, 0);
int toolsLocked = preferences.getInt(USER_TOOLS_LOCKED, 3);
String tool1 = preferences.getString(USER_TOOL_1, ToolType.RAMP.name());
String tool2 = preferences.getString(USER_TOOL_2, "null");
String tool3 = preferences.getString(USER_TOOL_3, "null");
String tool4 = preferences.getString(USER_TOOL_4, "null");
ToolSlotSettings toolSlotSettings = new ToolSlotSettings(tool1, tool2, tool3, tool4,
toolsLocked);
String playerShapeName = preferences.getString(USER_PLAYER_SHAPE, PlayerShape.BALL.name());
PlayerShape playerShape;
try{
playerShape = PlayerShape.valueOf(playerShapeName);
}catch (Exception e){
playerShape = PlayerShape.BALL;
}
return new User(lvUpListener, ep, level, stars, energy, toolSlotSettings, playerShape);
}
public void writeUserData(User user) {
SharedPreferences.Editor editor = preferences.edit();
editor.putInt(USER_EP, user.getEp());
editor.putInt(USER_LEVEL, user.getLevel());
editor.putInt(USER_STARS, user.getStarCount());
editor.putInt(USER_ENERGY, user.getEnergyCount());
editor.putString(USER_TOOL_1, toolSlotToString(user.getToolSlotSettings(), 0));
editor.putString(USER_TOOL_2, toolSlotToString(user.getToolSlotSettings(), 1));
editor.putString(USER_TOOL_3, toolSlotToString(user.getToolSlotSettings(), 2));
editor.putString(USER_TOOL_4, toolSlotToString(user.getToolSlotSettings(), 3));
editor.putInt(USER_TOOLS_LOCKED, user.getToolSlotSettings().getLockedSlotCount());
editor.putString(USER_PLAYER_SHAPE, user.getCurrentPlayerShape().name());
editor.apply();
}
private String toolSlotToString(ToolSlotSettings toolSlotSettings, int index) {
ToolType toolType = toolSlotSettings.get(index).getToolType();
return toolType == null ? "null" : toolType.toString();
}
public void writeToolShopTutorialPart1Finished(boolean finished) {
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(TOOL_SHOP_TUTORIAL_PART_1_FINISHED, finished);
editor.apply();
}
public boolean readToolShopTutorialPart1Finished() {
return preferences.getBoolean(TOOL_SHOP_TUTORIAL_PART_1_FINISHED, false);
}
public MyDatabase getDatabase() {
return database;
}
}

View File

@ -0,0 +1,10 @@
package de.frajul.endlessroll.main;
/**
* Created by Julian on 06.02.2016.
*/
public interface ExceptionHandler {
void onException(Exception e);
}

View File

@ -0,0 +1,292 @@
package de.frajul.endlessroll.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.graphics.Typeface;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Window;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import java.util.List;
import de.frajul.endlessroll.entities.shapes.PlayerShape;
import de.frajul.endlessroll.entities.tools.ToolType;
import de.frajul.endlessroll.levels.Level;
import de.frajul.endlessroll.levels.LevelManager;
import de.frajul.endlessroll.levels.LevelPack;
import de.frajul.endlessroll.main.screens.GLTestScreen;
import de.frajul.endlessroll.main.screens.GameScreen;
import de.frajul.endlessroll.main.screens.LevelsScreen;
import de.frajul.endlessroll.main.screens.PlayerShapeShopScreen;
import de.frajul.endlessroll.main.screens.PreStartScreen;
import de.frajul.endlessroll.main.screens.Screen;
import de.frajul.endlessroll.main.screens.ScreenFlipper;
import de.frajul.endlessroll.main.screens.SettingsScreen;
import de.frajul.endlessroll.main.screens.StartScreen;
import de.frajul.endlessroll.main.screens.ToolShopScreen;
import de.frajul.endlessroll.main.screens.WorldsScreen;
import de.frajul.endlessroll.main.tutorial.BreakPoint;
import de.frajul.endlessroll.main.tutorial.TutorialManager;
import de.frajul.endlessroll.main.tutorial.TutorialView;
import de.frajul.endlessroll.rendering.renderer.GameRenderer;
import de.frajul.endlessroll.sounds.SoundManager;
import de.frajul.endlessroll.sqlDatabase.MyDatabase;
import de.frajul.endlessroll.user.User;
import de.frajul.endlessroll.views.GoalMessage;
import de.frajul.endlessroll.views.LevelupMessage;
import de.frajul.endlessroll.views.TaskCompletedMessage;
/**
* Created by Julian on 06.02.2016.
*/
public class GameActivity extends Activity implements ExceptionHandler, User.LvUpListener {
private DataStorageHandler dataStorageHandler;
private LevelManager levelManager;
private SoundManager soundManager;
private User user;
private Typeface typeface;
private TutorialManager tutorialManager;
private MyGlSurfaceView glSurfaceView;
private ScreenFlipper flipper;
private PreStartScreen preStartScreen;
private StartScreen startScreen;
private GLTestScreen glTestScreen;
private WorldsScreen worldsScreen;
private LevelsScreen levelsScreen;
private ToolShopScreen toolShopScreen;
private PlayerShapeShopScreen shapeShopScreen;
private GameScreen gameScreen;
private SettingsScreen settingsScreen;
private LevelupMessage levelupMessage;
private TaskCompletedMessage taskCompletedMessage;
private TutorialView tutorialView;
@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");
dataStorageHandler = new DataStorageHandler(this);
dataStorageHandler.getDatabase().open();
dataStorageHandler.getDatabase().readToolData();
dataStorageHandler.getDatabase().close();
user = dataStorageHandler.readUserData(this);
soundManager = new SoundManager(this);
soundManager.setSoundOn(dataStorageHandler.readIsSoundOn());
soundManager.backgroundMusic.getPlayer().setLooping(true);
soundManager.backgroundMusic.start();
levelManager = new LevelManager(this, dataStorageHandler);
tutorialManager = new TutorialManager();
this.glSurfaceView = new MyGlSurfaceView(this, new GameRenderer(this));
typeface = Typeface.createFromAsset(getAssets(), "fontBaron.ttf");
preStartScreen = new PreStartScreen(this);
startScreen = new StartScreen(this, glSurfaceView);
glTestScreen = new GLTestScreen(this, glSurfaceView);
worldsScreen = new WorldsScreen(this);
levelsScreen = new LevelsScreen(this);
toolShopScreen = new ToolShopScreen(this);
shapeShopScreen = new PlayerShapeShopScreen(this);
gameScreen = new GameScreen(this, glSurfaceView);
settingsScreen = new SettingsScreen(this);
levelupMessage = new LevelupMessage(this);
taskCompletedMessage = new TaskCompletedMessage(this);
tutorialView = new TutorialView(this);
flipper = new ScreenFlipper(this, preStartScreen, startScreen, worldsScreen,
levelsScreen, gameScreen, toolShopScreen, glTestScreen, settingsScreen,
shapeShopScreen);
RelativeLayout relativeLayout = new RelativeLayout(this);
relativeLayout.addView(glSurfaceView);
relativeLayout.addView(flipper);
relativeLayout.addView(levelupMessage.getLayout());
relativeLayout.addView(taskCompletedMessage.getLayout());
relativeLayout.addView(tutorialView.getLayout());
setContentView(relativeLayout);
} catch (Exception e) {
onException(e);
return;
}
}
public void exitGame() {
super.finish();
}
public void flipToScreen(final Screen.ScreenType screen) {
if (screen != Screen.ScreenType.NONE) {
runOnUiThread(new Runnable() {
@Override
public void run() {
flipper.showScreen(screen, flipper.getCurrentScreen().getType());
}
});
}
}
public void onSurfaceChanged() {
if (flipper.getCurrentScreen().getType() == Screen.ScreenType.PRE_START)
flipToScreen(Screen.ScreenType.START);
}
public void onWorldSelected(LevelPack levelPack) {
levelsScreen.onLevelPackSelected(levelPack);
}
public void startGame(final LevelPack levelPack, final Level level) {
flipToScreen(Screen.ScreenType.GAME);
gameScreen.startGame(levelPack, level);
}
@Override
public void onLvUp(final int level) {
runOnUiThread(new Runnable() {
@Override
public void run() {
levelupMessage.show(level);
}
});
}
public void onTasksCompleted(final List<PlayerShape> shapes) {
runOnUiThread(new Runnable() {
@Override
public void run() {
taskCompletedMessage.show(shapes);
}
});
}
public void showTutorialScreen(final List<BreakPoint> breakPoints) {
runOnUiThread(new Runnable() {
@Override
public void run() {
tutorialView.show(breakPoints);
}
});
}
public void onTutorialViewHidden() {
if (!gameScreen.isLevelFinished())
gameScreen.onResume();
}
public void resetData() {
user.clearData();
dataStorageHandler.writeUserData(user);
dataStorageHandler.writeToolShopTutorialPart1Finished(false);
levelManager.reset();
tutorialManager.getToolShopTutorial().reset();
MyDatabase database = dataStorageHandler.getDatabase();
database.open();
database.clearLevelProgess();
database.clearLevelPackLocked();
for (ToolType type : ToolType.values())
type.reset();
database.writeToolData();
database.close();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
try {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (tutorialView.isShowingTutorial())
tutorialView.onClick(null);
else
flipper.getCurrentScreen().onBackKeyDown();
return true;
}
} catch (Exception e) {
onException(e);
}
return super.onKeyDown(keyCode, event);
}
@Override
public void onException(Exception e) {
GameLog.e(e);
super.finish();
}
@Override
protected void onPause() {
GameLog.d("OnPause");
glSurfaceView.onPause();
if (flipper.getCurrentScreen() == gameScreen)
gameScreen.onPause();
soundManager.pause();
super.onPause();
}
@Override
protected void onResume() {
GameLog.d("OnResume");
glSurfaceView.onResume();
soundManager.resume();
super.onResume();
}
@Override
protected void onDestroy() {
GameLog.d("OnDestroy");
soundManager.destroy();
dataStorageHandler.writeSoundOn(soundManager.isSoundOn());
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;
}
public User getUser() {
return user;
}
public DataStorageHandler getDataStorageHandler() {
return dataStorageHandler;
}
public SoundManager getSoundManager() {
return soundManager;
}
public Typeface getTypeface() {
return typeface;
}
public LevelManager getLevelManager() {
return levelManager;
}
public TutorialManager getTutorialManager() {
return tutorialManager;
}
}

View File

@ -0,0 +1,23 @@
package de.frajul.endlessroll.main;
import android.widget.RelativeLayout;
import de.frajul.endlessroll.main.screens.Screen;
import de.frajul.endlessroll.main.tutorial.BreakPoint;
import java.util.List;
/**
* Created by Julian on 08.12.2015.
*/
public interface GameHandler extends ExceptionHandler {
void startInUiThread(Runnable runnable);
void toScreen(Screen.ScreenType screen);
RelativeLayout getRootLayout();
void showTutorialScreen(List<BreakPoint> breakPoints);
}

View File

@ -0,0 +1,44 @@
package de.frajul.endlessroll.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

@ -0,0 +1,45 @@
package de.frajul.endlessroll.main;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;
import android.view.View;
import de.frajul.endlessroll.rendering.Rendering;
import de.frajul.endlessroll.rendering.renderer.GameRenderer;
/**
* Created by Julian on 30.07.2016.
*/
public class MyGlSurfaceView extends GLSurfaceView {
private GameRenderer renderer;
public MyGlSurfaceView(Context context, GameRenderer gameRenderer) throws Exception {
super(context);
this.renderer = gameRenderer;
super.setEGLContextClientVersion(2);
super.setRenderer(renderer);
}
public void addRendering(Rendering rendering) {
renderer.addRendering(rendering);
}
public void setCurrentRendering(Rendering currentRendering) {
super.setOnTouchListener(currentRendering);
renderer.setCurrentRendering(currentRendering);
}
@Override
public void onResume() {
GameLog.i("GLSurfaceView: onResume");
super.onResume();
}
@Override
public void onPause() {
GameLog.i("GLSurfaceView: onPause");
super.onPause();
}
}

View File

@ -0,0 +1,45 @@
package de.frajul.endlessroll.main.game;
/**
* Created by Julian on 22.05.2017.
*/
public class Camera {
private final float MOVE_SPEED_UP = 0.7f;
private final float MOVE_SPEED_DOWN = 0.7f;
private final float MAX_Y = 0.5f;
private final float MIN_Y = 0;
private float x, y;
public void update(float playerY, Timer timer){
float frameTime = timer.getFrameTimeSeconds() / 1000f;
float maxY = Math.min(playerY - 1 + 0.6f, MAX_Y);
if(playerY >= 0.5f){
y += MOVE_SPEED_UP * frameTime;
if(y > maxY)
y = maxY;
} else if(y > MIN_Y){
y -= MOVE_SPEED_DOWN * frameTime;
if(y < MIN_Y)
y = MIN_Y;
}
}
public void moveX(float move){
x += move;
}
public void reset(){
x = 0;
y = 0;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
}

View File

@ -0,0 +1,337 @@
package de.frajul.endlessroll.main.game;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.DestroyEffect;
import de.frajul.endlessroll.entities.Player;
import de.frajul.endlessroll.entities.collectables.Energy;
import de.frajul.endlessroll.entities.collectables.Star;
import de.frajul.endlessroll.entities.collision.CollisionManager;
import de.frajul.endlessroll.entities.particles.Firework;
import de.frajul.endlessroll.entities.particles.ParticleSystem;
import de.frajul.endlessroll.entities.shapes.PlayerShape;
import de.frajul.endlessroll.entities.shapes.Task;
import de.frajul.endlessroll.entities.textures.TexturePack;
import de.frajul.endlessroll.entities.tools.ToolType;
import de.frajul.endlessroll.levels.Level;
import de.frajul.endlessroll.levels.LevelPack;
import de.frajul.endlessroll.main.GameActivity;
import de.frajul.endlessroll.main.GameHandler;
import de.frajul.endlessroll.main.GameLog;
import de.frajul.endlessroll.main.physics.Physics;
import de.frajul.endlessroll.main.screens.Screen;
import de.frajul.endlessroll.main.tutorial.Tutorial;
import de.frajul.endlessroll.rendering.Rendering;
import de.frajul.endlessroll.sqlDatabase.MyDatabase;
import de.frajul.endlessroll.views.ToolButton;
import de.frajul.endlessroll.views.ToolButtonBar;
import de.frajul.endlessroll.views.ViewManager;
/**
* Created by Julian on 26.11.2015.
*/
public class Game extends Rendering<GameScene> {
private GameActivity gameActivity;
private GameHandler handler;
private ViewManager viewManager;
private LevelPack levelPack;
private ParticleSystem particleSystem;
private Firework firework;
private ToolType currentTool;
private Player player;
private Physics physics;
private CollisionManager collisionManager;
private Timer timer;
private GameState gameState = GameState.COUNTDOWN;
private Level level;
private List<Integer> collectedStars = new ArrayList<>();
private boolean energyCollected;
private Tutorial currentTutorial;
public Game(GameHandler handler, GameActivity gameActivity) throws Exception {
super(gameActivity);
this.handler = handler;
this.gameActivity = gameActivity;
physics = new Physics();
collisionManager = new CollisionManager(this);
particleSystem = new ParticleSystem(getContext());
viewManager = new ViewManager(this, handler, gameActivity);
}
@Override
public GameScene init(TexturePack texturePack, Timer timer, boolean isFirstTime) {
GameLog.d("init Game");
this.timer = timer;
try {
if (isFirstTime) {
scene = new GameScene(texturePack, particleSystem);
firework = new Firework(particleSystem.firework, scene.getCamera());
if (level != null)
startGame(levelPack, level);
} else {
scene.setTexturePack(texturePack);
}
particleSystem.loadTextures();
} catch (Exception e) {
onException(e);
}
return scene;
}
public void startGame(LevelPack levelPack, Level level) {
GameLog.d("Start game");
try {
this.level = level;
this.levelPack = levelPack;
if (scene != null) {
gameState = GameState.COUNTDOWN;
gameActivity.getTutorialManager().resetGameTutorials();
currentTutorial = gameActivity.getTutorialManager().getGameTutorial(level);
if (level.isFinished())
currentTutorial = null;
collectedStars.clear();
energyCollected = false;
particleSystem.deleteAllSources();
scene.loadLevel(level, levelPack.getWorld(),
gameActivity.getUser().getCurrentPlayerShape());
player = scene.getPlayer();
viewManager.resetViews(gameActivity.getUser());
currentTool = viewManager.toolButtonBar.getActiveButton().getToolType();
viewManager.startCountdown();
}
} catch (Exception e) {
onException(e);
}
}
public void countdownFinished() {
gameState = GameState.RUNNING;
}
@Override
public void setScreenSize(int width, int height) {
Vector screenSize = new Vector(width, height);
scene.setScreenSize(screenSize);
}
@Override
public void update() {
try {
particleSystem.update(timer);
if (scene == null || player == null)
return;
float playerProgress = player.getProgress();
float playerSpeed = player.getMovement().getX();
viewManager.update(gameState == GameState.RUNNING, timer, playerProgress, playerSpeed);
switch (gameState) {
case RUNNING:
if (player.getPosition().y < -2f) {
onGameOver(false);
return;
}
if (player.getPosition().x >= scene.getGoalX()) {
onGoalReached();
return;
}
scene.getCamera().update(player.getPosition().y, timer);
if (currentTutorial != null) {
currentTutorial.update(playerProgress);
if (currentTutorial.isOverNewBreakPoints()) {
gameState = GameState.PAUSED;
handler.showTutorialScreen(currentTutorial.getCurrentBreakPoints());
return;
}
}
physics.applyGravity(scene, timer);
scene.update(timer);
collisionManager.update(physics, scene, timer);
break;
}
} catch (Exception e) {
onException(e);
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (gameState == GameState.RUNNING) {
ToolButtonBar bar = viewManager.toolButtonBar;
ToolButton button = bar.getByToolType(currentTool);
if (button != null && button.finishedLoading()) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
button.setProgress(0);
addTool(event.getX(), event.getY());
}
}
return true;
}
return false;
}
public void resetViews() {
viewManager.resetViews(gameActivity.getUser());
}
public void continueGame() {
viewManager.hideShortMenu();
gameState = GameState.COUNTDOWN;
viewManager.startCountdown();
}
public void startNextLevel() {
level = levelPack.getNextLevel(level);
startGame(levelPack, level);
}
public void restartLevel() {
startGame(levelPack, level);
}
public void toLevelsScreen() {
handler.toScreen(Screen.ScreenType.LEVELS);
}
public void toToolShop() {
handler.toScreen(Screen.ScreenType.TOOL_SHOP);
}
public void setCurrentTool(ToolType toolType) {
currentTool = toolType;
}
public void tryToPause() {
if (gameState == GameState.GAME_OVER || gameState == GameState.LEVEL_FINISHED || gameState == GameState.PAUSED)
return;
viewManager.showShortMenu();
if (gameState == GameState.COUNTDOWN)
viewManager.stopCountdown();
gameState = GameState.PAUSED;
}
public void onGoalMessageKeyBack(){
viewManager.onGoalMessageKeyBack();
}
public void setRunning() {
gameState = GameState.RUNNING;
}
private void addTool(float x, float y) {
try {
gameActivity.getSoundManager().playSound(currentTool.getPlacingSound());
scene.addTool(currentTool, x, y, physics);
} catch (Exception e) {
onException(e);
}
}
public void onGameOver(boolean playerExplode) {
if (playerExplode) {
scene.getUncategorizedEntities().remove(player);
DestroyEffect.EXPLOSION.createEffect(particleSystem, player.getPosition(),
new Vector(player.getWidth(), player.getHeight())).start();
}
gameState = GameState.GAME_OVER;
viewManager.showGameOverMessage();
}
private void onGoalReached() {
List<PlayerShape> alreadyUnlockedShapes = new ArrayList<>();
for (PlayerShape shape : PlayerShape.values()) {
Task task = shape.getUnlockTask();
task.update(gameActivity.getLevelManager());
if (task.isConditionFulfilled())
alreadyUnlockedShapes.add(shape);
}
gameState = GameState.LEVEL_FINISHED;
if (!level.isFinished())
gameActivity.getUser().gainLvFinishedEp();
level.setFinished(true);
for (int i = 0; i <= 2; i++) {
if (collectedStars.contains(i)) {
level.setStarCollected(i, true);
gameActivity.getUser().onStarCollected();
}
}
if (energyCollected) {
level.setEnergyCollected(true);
gameActivity.getUser().onEnergyCollected();
}
firework.start();
//viewManager.showGameOverMessage(levelPack.isLastLevel(level), MessageType.WIN);
//TODO: fadeInWithDelay something
viewManager.showGoalMessage(levelPack, level);
MyDatabase database = gameActivity.getDataStorageHandler().getDatabase();
database.open();
database.writeLevelProgress(level);
List<PlayerShape> newUnlockedShapes = new ArrayList<>();
for (PlayerShape shape : PlayerShape.values()) {
Task task = shape.getUnlockTask();
task.update(gameActivity.getLevelManager());
if (task.isConditionFulfilled() && !alreadyUnlockedShapes.contains(shape))
newUnlockedShapes.add(shape);
}
if (!newUnlockedShapes.isEmpty())
gameActivity.onTasksCompleted(newUnlockedShapes);
Level nextLevel = levelPack.getNextLevel(level);
if (nextLevel != null) {
nextLevel.setLocked(false);
database.writeLevelProgress(nextLevel);
} else {
LevelPack nextLevelPack = gameActivity.getLevelManager().getNextLevelPack(levelPack);
if (nextLevelPack != null) {
nextLevelPack.setLocked(false);
database.writeLevelPackLocked(nextLevelPack);
}
}
database.close();
gameActivity.getDataStorageHandler().writeUserData(gameActivity.getUser());
if (currentTutorial != null) {
currentTutorial.onLevelFinished();
if (currentTutorial.isOverNewBreakPoints())
handler.showTutorialScreen(currentTutorial.getCurrentBreakPoints());
}
}
public void onStarCollision(Star star) {
scene.onStarCollision(star);
collectedStars.add(star.getIndex());
}
public void onEnergyCollision(Energy energy) {
scene.onEnergyCollision(energy);
energyCollected = true;
}
@Override
public void onException(Exception e) {
handler.onException(e);
}
public GameState getGameState() {
return gameState;
}
}

View File

@ -0,0 +1,112 @@
package de.frajul.endlessroll.main.game;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.DestroyEffect;
import de.frajul.endlessroll.entities.Goal;
import de.frajul.endlessroll.entities.Obstacle;
import de.frajul.endlessroll.entities.collectables.Energy;
import de.frajul.endlessroll.entities.collectables.Star;
import de.frajul.endlessroll.entities.collision.CollisionDetector;
import de.frajul.endlessroll.entities.particles.ParticleSystem;
import de.frajul.endlessroll.entities.shapes.PlayerShape;
import de.frajul.endlessroll.entities.textures.TexturePack;
import de.frajul.endlessroll.entities.tools.Bomb;
import de.frajul.endlessroll.entities.tools.Tool;
import de.frajul.endlessroll.entities.tools.ToolType;
import de.frajul.endlessroll.levels.Level;
import de.frajul.endlessroll.levels.ObstacleData;
import de.frajul.endlessroll.levels.worlds.World;
import de.frajul.endlessroll.main.GameLog;
import de.frajul.endlessroll.main.physics.Physics;
/**
* Created by Julian on 27.11.2015.
*/
public class GameScene extends Scene {
private World currentWorld;
private CollisionDetector collisionDetector;
private Goal goal;
private float goalX;
public GameScene(TexturePack texturePack, ParticleSystem particleSystem) throws Exception {
super(texturePack, particleSystem);
collisionDetector = new CollisionDetector();
goal = new Goal(textures.goal);
}
public void loadLevel(Level level, World world, PlayerShape playerPlayerShape) throws Exception {
this.currentWorld = world;
super.reset();
background.changeTexture(world.getBackgroundTexture());
terrain.loadData(world, level.getTerrainEdge(), level.getTerrainTiles());
ceiling.loadData(world, level.getCeilingEdge(), level.getCeilingTiles());
uncategorizedEntities.add(goal);
player.init(playerPlayerShape, terrain.getEdge(), level.getStartSpeed(), level.getEndSpeed(), particleSystem);
uncategorizedEntities.add(player);
collectables.init(level, textures);
for (ObstacleData data : level.getObstacles())
addObstacle(data);
goalX = level.getGoalX();
goal.setGoalX(goalX);
GameLog.d("Level " + level.getId() + " successfully loaded");
}
public void onStarCollision(Star collisionStar) {
collisionStar.destroy(DestroyEffect.STAR_EXPLOSION);
}
public void onEnergyCollision(Energy energy) {
energy.destroy(DestroyEffect.ENERGY_COLLECT);
}
public void addObstacle(ObstacleData data) {
Obstacle obstacle = new Obstacle(currentWorld, data, terrain.getEdge());
obstacles.add(obstacle);
}
public void addTool(ToolType type, float screenX, float screenY, Physics physics) throws Exception {
Vector position = calcWorldFromScreenCoords(screenX, screenY);
Tool tool = type.newInstance(position, particleSystem);
physics.checkSingleToolCollision(tool, this);
if (tool == null)
throw new Exception(
"Current ToolType(" + type + ") returns null at method newInstance()");
tools.add(tool);
}
public void update(Timer timer) {
player.setSpeedByProgress(player.getProgress() / goalX);
player.preMoveUpdate(timer);
if (player.hasSuperPower() && player.getBottomEdge() < terrain.getEdge()) {
player.setToTerrain(terrain.getEdge());
if (player.getMovement().y < 0)
player.getMovement().setY(0);
}
super.update(timer);
player.postMoveUpdate();
synchronized (tools) {
for (Tool tool : tools) {
if (tool instanceof Bomb) {
Bomb bomb = (Bomb) tool;
if (bomb.isExploding())
bomb.explode(obstacles, collisionDetector);
}
}
}
}
public float getGoalX() {
return goalX;
}
}

View File

@ -0,0 +1,10 @@
package de.frajul.endlessroll.main.game;
/**
* Created by Julian on 02.02.2016.
*/
public enum GameState {
RUNNING, PAUSED, GAME_OVER, LEVEL_FINISHED, COUNTDOWN
}

View File

@ -0,0 +1,191 @@
package de.frajul.endlessroll.main.game;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.AnimatedEntity;
import de.frajul.endlessroll.entities.Background;
import de.frajul.endlessroll.entities.collectables.Collectables;
import de.frajul.endlessroll.entities.collectables.Energy;
import de.frajul.endlessroll.entities.Entity;
import de.frajul.endlessroll.entities.Obstacle;
import de.frajul.endlessroll.entities.Player;
import de.frajul.endlessroll.entities.collectables.Star;
import de.frajul.endlessroll.entities.particles.ParticleSystem;
import de.frajul.endlessroll.entities.textures.TexturePack;
import de.frajul.endlessroll.entities.tileLists.Ceiling;
import de.frajul.endlessroll.entities.tileLists.Terrain;
import de.frajul.endlessroll.entities.tools.Tool;
import de.frajul.endlessroll.levels.worlds.World;
/**
* Created by Julian on 20.07.2016.
*/
public abstract class Scene {
//Not sure if needed, this why set on very high value
private final float MAX_Y_MOVEMENT = -1f;
protected Camera camera;
private Vector screenSize;
private Entity playerArrow;
protected ParticleSystem particleSystem;
protected TexturePack textures;
protected Background background;
protected Terrain terrain;
protected Ceiling ceiling;
protected Player player;
protected List<Entity> uncategorizedEntities = Collections.synchronizedList(new ArrayList<Entity>());
protected List<Obstacle> obstacles = Collections.synchronizedList(new ArrayList<Obstacle>());
protected List<Tool> tools = Collections.synchronizedList(new ArrayList<Tool>());
protected Collectables collectables = new Collectables();
public Scene(TexturePack texturePack, ParticleSystem particleSystem) {
this.particleSystem = particleSystem;
setTexturePack(texturePack);
camera = new Camera();
playerArrow = new Entity(textures.playerArrow, new Vector(0, 0.9f), .2f, .2f);
background = new Background(World.GRASSLANDS.getBackgroundTexture());
terrain = new Terrain(World.GRASSLANDS.getTerrainTexture());
ceiling = new Ceiling(World.GRASSLANDS.getTerrainTexture());
player = new Player();
}
public void setTexturePack(TexturePack texturePack) {
this.textures = texturePack;
}
public void reset(){
uncategorizedEntities.clear();
obstacles.clear();
tools.clear();
collectables.reset();
camera.reset();
background.resetPosition();
}
public void update(Timer timer) {
updateEntityList(uncategorizedEntities, timer);
updateEntityList(obstacles, timer);
updateEntityList(tools, timer);
updateEntityList(collectables, timer);
if (player.getPosition().y >= player.RADIUS + 1 + camera.getY()) {
playerArrow.getPosition().x = player.getPosition().x;
playerArrow.getPosition().y = camera.getY() + 0.9f;
if (!uncategorizedEntities.contains(playerArrow)) {
uncategorizedEntities.add(playerArrow);
}
} else
uncategorizedEntities.remove(playerArrow);
}
private void updateEntityList(List<? extends Entity> list, Timer timer){
synchronized (list){
Iterator<? extends Entity> iterator = list.iterator();
while(iterator.hasNext()) {
Entity entity = iterator.next();
if(entity instanceof Obstacle){
Obstacle obstacle = (Obstacle) entity;
if (obstacle.isMoving())
obstacle.moveWithMoveComponent(timer.getFrameTimeSeconds());
}
boolean remove = updateEntity(entity, timer);
if (remove)
iterator.remove();
}
}
}
private boolean updateEntity(Entity entity, Timer timer){
if (entity instanceof AnimatedEntity)
((AnimatedEntity) entity).update(timer);
Vector movement = entity.getMovement();
Vector finalMovement = new Vector(movement).mul(timer.getFrameTimeSeconds());
if(finalMovement.y < MAX_Y_MOVEMENT)
finalMovement.y = MAX_Y_MOVEMENT;
entity.move(finalMovement);
if (entity.equals(player))
moveEnviroment(finalMovement.x);
if (entity.isDestroyed() && entity.getDestroyEffect() != null)
entity.getDestroyEffect()
.createEffect(particleSystem, new Vector(entity.getPosition()),
new Vector(entity.getWidth(), entity.getHeight())).start();
if (entity.getRightEdge() - camera.getX() < -3f || entity.isDestroyed()) {
return true;
}
return false;
}
private void moveEnviroment(float x) {
camera.moveX(x);
background.move(x * 0.95f, camera.getX());
terrain.update(camera.getX());
ceiling.update(camera.getX());
}
protected 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 += camera.getX();
float y = -((screenY / screenSize.y) * 2f - 1f);
y += camera.getY();
return new Vector(x, y);
}
public void setScreenSize(Vector screenSize) {
this.screenSize = screenSize;
}
public synchronized Background getBackground() {
return background;
}
public synchronized Terrain getTerrain() {
return terrain;
}
public synchronized Ceiling getCeiling() {
return ceiling;
}
public synchronized List<Entity> getUncategorizedEntities() {
return uncategorizedEntities;
}
public synchronized List<Obstacle> getObstacles() {
return obstacles;
}
public synchronized List<Tool> getTools() {
return tools;
}
public synchronized Collectables getCollectables() {
return collectables;
}
public Player getPlayer() {
return player;
}
public TexturePack getTextures() {
return textures;
}
public ParticleSystem getParticleSystem() {
return particleSystem;
}
public Camera getCamera() {
return camera;
}
}

View File

@ -0,0 +1,17 @@
package de.frajul.endlessroll.main.game;
import de.frajul.endlessroll.entities.particles.ParticleSystem;
import de.frajul.endlessroll.entities.shapes.PlayerShape;
import de.frajul.endlessroll.entities.textures.TexturePack;
import de.frajul.endlessroll.levels.worlds.World;
public class StartScene extends Scene {
public StartScene(TexturePack texturePack, ParticleSystem particleSystem) {
super(texturePack, particleSystem);
terrain.createEndless(World.ICY_MOUNTAINS, -.8f);
player.init(PlayerShape.BALL, terrain.getEdge(), 0.5f, 0.5f, null);
uncategorizedEntities.add(player);
}
}

View File

@ -0,0 +1,46 @@
package de.frajul.endlessroll.main.game;
/**
* 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 getFrameTimeSeconds() {
return delta;
}
public int getFps() {
return fps;
}
public long getCurrentTime() {
return System.currentTimeMillis();
}
}

View File

@ -0,0 +1,199 @@
package de.frajul.endlessroll.main.physics;
import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import de.frajul.endlessroll.entities.Entity;
import de.frajul.endlessroll.entities.Obstacle;
import de.frajul.endlessroll.entities.collectables.Collectables;
import de.frajul.endlessroll.entities.collectables.Energy;
import de.frajul.endlessroll.entities.collectables.Star;
import de.frajul.endlessroll.entities.collision.CollisionDetector;
import de.frajul.endlessroll.entities.collision.collisionData.EntityCollisionData;
import de.frajul.endlessroll.entities.collision.collisionData.ObstacleCollisionData;
import de.frajul.endlessroll.entities.collision.collisionData.PlayerCollisionData;
import de.frajul.endlessroll.entities.collision.collisionData.ToolCollisionData;
import de.frajul.endlessroll.entities.collision.geometry.Circle;
import de.frajul.endlessroll.entities.tileLists.Ceiling;
import de.frajul.endlessroll.entities.tileLists.Terrain;
import de.frajul.endlessroll.entities.tileLists.Tile;
import de.frajul.endlessroll.entities.tools.Bomb;
import de.frajul.endlessroll.entities.tools.Tool;
import de.frajul.endlessroll.main.game.GameScene;
import de.frajul.endlessroll.main.game.Scene;
import de.frajul.endlessroll.main.game.Timer;
/**
* Created by Julian on 27.11.2015.
*/
public class Physics {
public final float GRAVITY_FORCE = .0000025f;
private final float TOOL_ON_OBSTACLE_LEFT_EDGE_TOLERANCE = 0.05f;
private CollisionDetector detector;
public Physics() {
detector = new CollisionDetector();
}
public void applyGravity(GameScene scene, Timer timer) {
float gravity = GRAVITY_FORCE * timer.getFrameTimeSeconds();
scene.getPlayer().setGravityForce(-gravity);
synchronized (scene.getTools()) {
for (Tool tool : scene.getTools()) {
if (tool.isFloating())
continue;
tool.getMovement().y -= gravity * 2;
}
}
}
public synchronized void checkToolCollision(Scene scene) {
synchronized (scene.getTools()) {
for (Tool tool : scene.getTools()) {
checkSingleToolCollision(tool, scene);
}
}
}
public synchronized void checkSingleToolCollision(Tool tool, Scene scene) {
if(tool.isFloating())
return;
float terrainEdge = getTerrainEdge(tool, scene.getTerrain());
Obstacle toolIsCollidingWith = getHighestObstacleToolIsCollidingWith(tool, scene);
if (toolIsCollidingWith != null) {
float distObstTool = tool.getRightEdge() - toolIsCollidingWith.getLeftEdge();
if (distObstTool < TOOL_ON_OBSTACLE_LEFT_EDGE_TOLERANCE) {
tool.getPosition().x -= TOOL_ON_OBSTACLE_LEFT_EDGE_TOLERANCE;
terrainEdge = getTerrainEdge(tool, scene.getTerrain());
toolIsCollidingWith = getHighestObstacleToolIsCollidingWith(tool, scene);
}
}
float orientingHeight = terrainEdge;
if (toolIsCollidingWith != null)
orientingHeight = Math.max(toolIsCollidingWith.getTopEdge(), terrainEdge);
if (tool.getBottomEdge() <= orientingHeight) {
tool.getMovement().y = 0;
if (tool instanceof Bomb)
tool.setFloating(true);
else
tool.setToTerrain(orientingHeight);
}
}
@Nullable
private Obstacle getHighestObstacleToolIsCollidingWith(Tool tool, Scene scene) {
List<Obstacle> collisionObstacles = new ArrayList<>();
synchronized (scene.getObstacles()) {
for (Obstacle obstacle : scene.getObstacles()) {
if (tool.getWorldCollisionBounds().isCollisionWithQuad(obstacle, detector)) {
collisionObstacles.add(obstacle);
}
}
}
Obstacle highest = null;
for (Obstacle obstacle : collisionObstacles)
if (highest == null || highest.getTopEdge() < obstacle.getTopEdge())
highest = obstacle;
return highest;
}
private float getTerrainEdge(Entity tool, Terrain terrain) {
for (Tile instance : terrain) {
if ((tool.getLeftEdge() >= instance.getLeftEdge() && tool.getLeftEdge() <= instance
.getRightEdge()) || (tool.getRightEdge() <= instance.getRightEdge() && tool
.getRightEdge() >= instance.getLeftEdge()) || (instance.getLeftEdge() >= tool
.getLeftEdge() && instance.getLeftEdge() <= tool.getRightEdge()) || (instance
.getRightEdge() <= tool.getRightEdge() && instance.getRightEdge() >= tool
.getLeftEdge()))
return terrain.getEdge();
}
return -10;
}
public PlayerCollisionData getPlayerCollisionData(GameScene scene) {
EntityCollisionData terrainData = playerCollidesWithTerrain(scene);
EntityCollisionData ceilingData = playerCollidesWithCeiling(scene);
ObstacleCollisionData obstacleData = playerCollidesWithObstacle(scene);
ToolCollisionData toolData = playerCollidesWithTool(scene);
EntityCollisionData starData = playerCollidesWithStar(scene);
EntityCollisionData energyData = playerCollidesWithEnergy(scene);
return new PlayerCollisionData(terrainData, ceilingData, obstacleData, toolData, starData,
energyData);
}
private EntityCollisionData playerCollidesWithTerrain(GameScene scene) {
Terrain terrain = scene.getTerrain();
for (Tile terrainTile : terrain) {
EntityCollisionData data = detector
.playerEntityCollision(scene.getPlayer(), terrainTile);
if (data.isCollision())
return data;
}
return new EntityCollisionData(null, null);
}
private EntityCollisionData playerCollidesWithCeiling(GameScene scene) {
Ceiling ceiling = scene.getCeiling();
for (Tile ceilingTile : ceiling) {
EntityCollisionData data = detector
.playerEntityCollision(scene.getPlayer(), ceilingTile);
if (data.isCollision())
return data;
}
return new EntityCollisionData(null, null);
}
private ObstacleCollisionData playerCollidesWithObstacle(GameScene scene) {
List<EntityCollisionData> collisions = new ArrayList<>();
synchronized (scene.getObstacles()) {
for (Obstacle obstacle : scene.getObstacles()) {
EntityCollisionData data = detector
.playerEntityCollision(scene.getPlayer(), obstacle);
if (data.isCollision())
collisions.add(data);
}
}
return new ObstacleCollisionData(collisions);
}
private ToolCollisionData playerCollidesWithTool(GameScene scene) {
List<Tool> tools = new ArrayList<>();
Circle circle = new Circle(scene.getPlayer());
synchronized (scene.getTools()) {
for (Tool tool : scene.getTools()) {
if (tool.getPlayerCollisionBounds().isCollisionWithCircle(circle, detector))
tools.add(tool);
}
}
return new ToolCollisionData(tools);
}
private EntityCollisionData playerCollidesWithStar(GameScene scene) {
Collectables collectables = scene.getCollectables();
synchronized (collectables.getStars()) {
for (Star star : collectables.getStars()) {
EntityCollisionData data = detector.playerEntityCollision(scene.getPlayer(), star);
if (data.isCollision())
return data;
}
}
return new EntityCollisionData(null, null);
}
private EntityCollisionData playerCollidesWithEnergy(GameScene scene) {
Energy energy = scene.getCollectables().getEnergy();
if (energy != null) {
EntityCollisionData data = detector.playerEntityCollision(scene.getPlayer(), energy);
return data;
} else
return new EntityCollisionData(null, null);
}
}

View File

@ -0,0 +1,21 @@
package de.frajul.endlessroll.main.screens;
import android.support.annotation.LayoutRes;
import android.view.ViewGroup;
import de.frajul.endlessroll.main.GameActivity;
import de.frajul.endlessroll.main.MyGlSurfaceView;
/**
* Created by Julian on 30.07.2016.
*/
public abstract class GLScreen<V extends ViewGroup> extends Screen<V> {
protected MyGlSurfaceView glView;
public GLScreen(ScreenType type, GameActivity gameActivity, @LayoutRes int layoutId, MyGlSurfaceView glView) {
super(type, gameActivity, layoutId);
this.glView = glView;
}
}

View File

@ -0,0 +1,88 @@
package de.frajul.endlessroll.main.screens;
import android.widget.RelativeLayout;
import java.util.List;
import de.frajul.endlessroll.R;
import de.frajul.endlessroll.levels.Level;
import de.frajul.endlessroll.levels.LevelPack;
import de.frajul.endlessroll.main.GameActivity;
import de.frajul.endlessroll.main.GameHandler;
import de.frajul.endlessroll.main.MyGlSurfaceView;
import de.frajul.endlessroll.main.game.Game;
import de.frajul.endlessroll.main.game.GameState;
import de.frajul.endlessroll.main.tutorial.BreakPoint;
/**
* Created by Julian on 08.02.2016.
*/
public class GameScreen extends GLScreen<RelativeLayout> {
private Game game;
public GameScreen(GameActivity gameActivity, MyGlSurfaceView glSurfaceView) throws Exception {
super(ScreenType.GAME, gameActivity, R.layout.game, glSurfaceView);
game = new Game(gameViewHandler, gameActivity);
glView.addRendering(game);
}
@Override
public void prepareToBeShown() {
glView.setCurrentRendering(game);
}
public void onPause() {
game.tryToPause();
}
public void onResume() {
game.setRunning();
}
public boolean isLevelFinished() {
return game.getGameState() == GameState.LEVEL_FINISHED;
}
@Override
public void onBackKeyDown() {
game.tryToPause();
if(isLevelFinished())
game.onGoalMessageKeyBack();
}
public void startGame(LevelPack levelPack, Level level) {
game.resetViews();
game.startGame(levelPack, level);
}
private GameHandler gameViewHandler = new GameHandler() {
@Override
public void startInUiThread(Runnable runnable) {
gameActivity.runOnUiThread(runnable);
}
@Override
public void toScreen(ScreenType screen) {
glView.setCurrentRendering(null);
gameActivity.flipToScreen(screen);
}
@Override
public RelativeLayout getRootLayout() {
return layout;
}
@Override
public void showTutorialScreen(List<BreakPoint> breakPoints) {
gameActivity.showTutorialScreen(breakPoints);
}
@Override
public void onException(Exception e) {
gameActivity.onException(e);
}
};
}

View File

@ -0,0 +1,80 @@
package de.frajul.endlessroll.main.screens;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import de.frajul.endlessroll.R;
import de.frajul.endlessroll.levels.Level;
import de.frajul.endlessroll.levels.LevelPack;
import de.frajul.endlessroll.main.GameActivity;
import de.frajul.endlessroll.views.LevelButton;
import de.frajul.endlessroll.views.LevelButtonOnClickListener;
import de.frajul.endlessroll.views.TopBar;
/**
* Created by Julian on 23.04.2016.
*/
public class LevelsScreen extends Screen<LinearLayout> implements LevelButtonOnClickListener {
private LevelPack levelPack;
private TopBar topBar;
private LinearLayout topRow;
private LinearLayout bottomRow;
public LevelsScreen(GameActivity gameActivity) {
super(ScreenType.LEVELS, gameActivity, R.layout.levels);
topBar = super.createTopBar(R.id.levels_topbar);
topRow = (LinearLayout) layout.findViewById(R.id.levels_top_row);
bottomRow = (LinearLayout) layout.findViewById(R.id.levels_bottom_row);
}
public void onLevelPackSelected(LevelPack levelPack) {
this.levelPack = levelPack;
}
private void build() {
topRow.removeAllViews();
bottomRow.removeAllViews();
int levelCount = levelPack.getLevels().size();
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(15, 15, 15, 15);
for (Level level : levelPack.getLevels())
createButton(level, levelCount, params);
}
private void createButton(Level level, int levelCount, LinearLayout.LayoutParams params) {
LevelButton button = new LevelButton(gameActivity, this, R.layout.levelbutton);
button.init(level);
int halfLevelCount = levelCount / 2;
if (levelCount % 2 == 1)
halfLevelCount++;
if (level.getId() <= halfLevelCount)
topRow.addView(button.getView(), params);
else
bottomRow.addView(button.getView(), params);
}
@Override
public void prepareToBeShown() {
topBar.update();
build();
}
@Override
public void onBackKeyDown() {
flipTo(ScreenType.WORLDS);
}
@Override
public void onClick(LevelButton levelButton) {
Level level = levelButton.getLevel();
if (!level.isLocked())
gameActivity.startGame(levelPack, level);
}
}

View File

@ -0,0 +1,85 @@
package de.frajul.endlessroll.main.screens;
import android.content.Context;
import android.support.annotation.IdRes;
import android.support.annotation.LayoutRes;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import de.frajul.endlessroll.main.GameActivity;
import de.frajul.endlessroll.views.TopBar;
/**
* Created by Julian on 13.02.2016.
*/
public abstract class Screen<V extends ViewGroup> {
public enum ScreenType {
NONE(-1),
PRE_START(0),
START(1),
WORLDS(2),
LEVELS(3),
GAME(4),
TOOL_SHOP(5),
GL_TEST(6),
SETTINGS(7),
SHAPE_SHOP(8);
private int inFlipperPosition;
ScreenType(int inFlipperPosition) {
this.inFlipperPosition = inFlipperPosition;
}
public int getInFlipperPosition() {
return inFlipperPosition;
}
}
private ScreenType type;
protected ScreenType caller;
protected V layout;
protected GameActivity gameActivity;
public Screen(ScreenType type, GameActivity gameActivity, @LayoutRes int layoutId) {
this.type = type;
this.gameActivity = gameActivity;
layout = inflateLayout(gameActivity, layoutId);
}
private V inflateLayout(Context context, @LayoutRes int layoutId) {
LayoutInflater inflater = LayoutInflater.from(context);
return (V) inflater.inflate(layoutId, null);
}
protected TopBar createTopBar(@IdRes int id) {
return new TopBar(gameActivity, type, layout.findViewById(id));
}
public void setCaller(ScreenType caller) {
this.caller = caller;
}
public abstract void prepareToBeShown();
public abstract void onBackKeyDown();
protected void flipToCaller() {
if (caller != null)
gameActivity.flipToScreen(caller);
}
protected void flipTo(ScreenType type) {
gameActivity.flipToScreen(type);
}
public ScreenType getType() {
return type;
}
public V get() {
return layout;
}
}

View File

@ -0,0 +1,54 @@
package de.frajul.endlessroll.main.screens;
import android.content.Context;
import android.widget.ViewFlipper;
/**
* Created by Julian on 13.02.2016.
*/
public class ScreenFlipper extends ViewFlipper {
private Screen[] screens;
private Screen currentScreen;
public ScreenFlipper(Context context, Screen... screens) {
super(context);
this.screens = screens;
for (Screen screen : screens)
addView(screen);
currentScreen = screens[0];
showScreen(currentScreen.getType(), Screen.ScreenType.NONE);
}
private void addView(Screen screen) {
super.addView(screen.get(), screen.getType().getInFlipperPosition());
}
public Screen getCurrentScreen() {
return currentScreen;
}
public void showScreen(Screen.ScreenType type, Screen.ScreenType caller) {
Screen screen = findScreen(type);
screen.setCaller(caller);
screen.prepareToBeShown();
int positionDifference = type.getInFlipperPosition() - currentScreen.getType().getInFlipperPosition();
if (positionDifference < 0)
for (; positionDifference != 0; positionDifference++)
super.showPrevious();
else if (positionDifference > 0)
for (; positionDifference != 0; positionDifference--)
super.showNext();
currentScreen = screen;
}
private Screen findScreen(Screen.ScreenType type) {
for (Screen screen : screens)
if (screen.getType().equals(type)) {
return screen;
}
return null;
}
}

View File

@ -0,0 +1,87 @@
package de.frajul.endlessroll.main.screens;
import android.app.AlertDialog;
import android.app.Dialog;
import android.graphics.Typeface;
import android.support.annotation.IdRes;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.ToggleButton;
import de.frajul.endlessroll.R;
import de.frajul.endlessroll.main.GameActivity;
import de.frajul.endlessroll.main.MyGlSurfaceView;
import de.frajul.endlessroll.rendering.Rendering;
import de.frajul.endlessroll.views.ExitConfirmDialog;
/**
* Created by Julian on 07.07.2016.
*/
public class StartScreen extends GLScreen<RelativeLayout> implements View.OnClickListener {
private Rendering rendering;
private Button play;
private Button unlockLevels;
private Button gain90EP;
private Button toGlTestScreen;
private Button settings;
private ExitConfirmDialog exitConfirmDialog;
public StartScreen(GameActivity gameActivity, MyGlSurfaceView glSurfaceView) throws Exception {
super(ScreenType.START, gameActivity, R.layout.start_screen, glSurfaceView);
Typeface typeface = gameActivity.getTypeface();
play = createButton(R.id.startscreen_play, typeface);
play.startAnimation(AnimationUtils.loadAnimation(gameActivity, R.anim.rotate));
unlockLevels = createButton(R.id.startscreen_unlock_levels, typeface);
gain90EP = createButton(R.id.startscreen_gain_90_ep, typeface);
toGlTestScreen = createButton(R.id.startscreen_to_gl_test_screen, typeface);
settings = (Button) layout.findViewById(R.id.startscreen_settings);
settings.setOnClickListener(this);
exitConfirmDialog = new ExitConfirmDialog(gameActivity);
rendering = new StartScreenRendering(gameActivity);
glView.addRendering(rendering);
}
private Button createButton(@IdRes int id, Typeface typeface) {
Button button = (Button) layout.findViewById(id);
button.setTypeface(typeface);
button.setOnClickListener(this);
return button;
}
@Override
public void prepareToBeShown() {
glView.setCurrentRendering(rendering);
}
@Override
public void onBackKeyDown() {
exitConfirmDialog.show();
}
@Override
public void onClick(View v) {
if (v.equals(play)) {
gameActivity.flipToScreen(ScreenType.WORLDS);
glView.setCurrentRendering(null);
} else if (v.equals(settings)) {
gameActivity.flipToScreen(ScreenType.SETTINGS);
glView.setCurrentRendering(null);
} else if (v.equals(gain90EP)) {
gameActivity.getUser().gainEp(90);
} else if (v.equals(unlockLevels)) {
gameActivity.getLevelManager().unlockAllLevels();
gameActivity.getLevelManager().unlockAllPacks();
} else if (v.equals(toGlTestScreen))
gameActivity.flipToScreen(ScreenType.GL_TEST);
}
}

View File

@ -0,0 +1,53 @@
package de.frajul.endlessroll.main.screens;
import android.view.MotionEvent;
import android.view.View;
import de.frajul.endlessroll.entities.particles.ParticleSystem;
import de.frajul.endlessroll.entities.textures.TexturePack;
import de.frajul.endlessroll.main.GameActivity;
import de.frajul.endlessroll.main.GameLog;
import de.frajul.endlessroll.main.game.StartScene;
import de.frajul.endlessroll.main.game.Timer;
import de.frajul.endlessroll.rendering.Rendering;
/**
* Created by Julian on 20.07.2016.
*/
public class StartScreenRendering extends Rendering<StartScene> {
private Timer timer;
private ParticleSystem particleSystem;
public StartScreenRendering(GameActivity gameActivity) throws Exception {
super(gameActivity);
this.particleSystem = new ParticleSystem(gameActivity);
}
@Override
public StartScene init(TexturePack texturePack, Timer timer, boolean isFirstTime) {
GameLog.d("init Start Screen Rendering");
this.timer = timer;
if (isFirstTime)
scene = new StartScene(texturePack, particleSystem);
else
scene.setTexturePack(texturePack);
try {
particleSystem.loadTextures();
} catch (Exception e) {
}
return scene;
}
@Override
public void update() {
particleSystem.update(timer);
scene.update(timer);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
}

View File

@ -0,0 +1,171 @@
package de.frajul.endlessroll.main.screens;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import java.util.ArrayList;
import java.util.List;
import de.frajul.endlessroll.R;
import de.frajul.endlessroll.entities.tools.ToolSlot;
import de.frajul.endlessroll.entities.tools.ToolType;
import de.frajul.endlessroll.main.DataStorageHandler;
import de.frajul.endlessroll.main.GameActivity;
import de.frajul.endlessroll.main.tutorial.ToolShopTutorial;
import de.frajul.endlessroll.user.LevelUpBounties;
import de.frajul.endlessroll.user.ToolSlotSettings;
import de.frajul.endlessroll.views.ToolInspector;
import de.frajul.endlessroll.views.ToolOfferSlot;
import de.frajul.endlessroll.views.TopBar;
/**
* Created by Julian on 08.07.2016.
*/
public class ToolShopScreen extends Screen<RelativeLayout> implements View.OnClickListener {
private LevelUpBounties levelUpBounties;
private ToolSlotSettings slotSettings;
private ToolOfferSlot selectedToolOfferSlot;
private TopBar topBar;
private LinearLayout toolOfferTopRow;
private LinearLayout toolOfferBottomRow;
private List<ImageView> toolSlotViews = new ArrayList<>();
private List<ToolOfferSlot> toolOfferSlots = new ArrayList<>();
private ToolInspector toolInspector;
private ToolShopTutorial tutorial;
public ToolShopScreen(GameActivity gameActivity) {
super(ScreenType.TOOL_SHOP, gameActivity, R.layout.toolshop);
this.levelUpBounties = new LevelUpBounties(0);
this.slotSettings = gameActivity.getUser().getToolSlotSettings();
this.tutorial = gameActivity.getTutorialManager().getToolShopTutorial();
tutorial.setFirstPartShown(
gameActivity.getDataStorageHandler().readToolShopTutorialPart1Finished());
topBar = super.createTopBar(R.id.toolshop_topbar);
toolSlotViews.add(getToolSlotView(R.id.toolshop_slot1));
toolSlotViews.add(getToolSlotView(R.id.toolshop_slot2));
toolSlotViews.add(getToolSlotView(R.id.toolshop_slot3));
toolSlotViews.add(getToolSlotView(R.id.toolshop_slot4));
toolOfferTopRow = (LinearLayout) layout.findViewById(R.id.toolshop_tool_offer_top_row);
toolOfferBottomRow = (LinearLayout) layout
.findViewById(R.id.toolshop_tool_offer_bottom_row);
toolInspector = new ToolInspector(this, gameActivity,
layout.findViewById(R.id.toolshop_toolinspector));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(10, 0, 10, 0);
int i = 0;
for (ToolType type : ToolType.values()) {
i++;
ToolOfferSlot slot = new ToolOfferSlot(this, gameActivity, gameActivity.getTypeface(),
type);
toolOfferSlots.add(slot);
if (i > 5)
toolOfferBottomRow.addView(slot.getLayout(), params);
else
toolOfferTopRow.addView(slot.getLayout(), params);
}
}
private ImageView getToolSlotView(int id) {
FrameLayout slotLayout = (FrameLayout) layout.findViewById(id);
ImageView imageView = (ImageView) slotLayout.findViewById(R.id.toolslot_image);
imageView.setOnClickListener(this);
return imageView;
}
@Override
public void prepareToBeShown() {
topBar.update();
levelUpBounties.loadAllForLevel(gameActivity.getUser().getLevel());
slotSettings.unlockSlotsIfLevelReached(levelUpBounties);
onToolOfferSlotSelected(toolOfferSlots.get(0));
for (int i = 0; i < toolSlotViews.size(); i++) {
ToolSlot toolSlot = slotSettings.get(i);
ImageView toolSlotView = toolSlotViews.get(i);
toolSlotView.setImageResource(toolSlot.getDrawable());
}
for (ToolOfferSlot toolOfferSlot : toolOfferSlots) {
boolean locked = levelUpBounties.isToolLocked(toolOfferSlot.getToolType());
toolOfferSlot.setLocked(locked);
toolOfferSlot.updateBackgroundColor();
}
tutorial.onToolShopPrepare(!levelUpBounties.isToolLocked(ToolType.SPRING));
if (tutorial.isOverNewBreakPoints()) {
gameActivity.showTutorialScreen(tutorial.getCurrentBreakPoints());
gameActivity.getDataStorageHandler()
.writeToolShopTutorialPart1Finished(tutorial.isFirstPartShown());
}
}
public void onToolBought(int price, ToolType toolType) {
topBar.showStarcountDecrease(-price);
gameActivity.getUser().increaseStarCount(-price, false);
topBar.update();
DataStorageHandler dataStorageHandler = gameActivity.getDataStorageHandler();
dataStorageHandler.getDatabase().open();
dataStorageHandler.getDatabase().writeToolData();
dataStorageHandler.getDatabase().close();
for (ToolOfferSlot toolOfferSlot : toolOfferSlots) {
toolOfferSlot.updateBackgroundColor();
}
tutorial.onToolBought(toolType);
if (tutorial.isOverNewBreakPoints())
gameActivity.showTutorialScreen(tutorial.getCurrentBreakPoints());
}
public void onToolUpgraded(int price) {
topBar.showEnergycountDecrease(-price);
gameActivity.getUser().increaseEnergyCount(-price, false);
topBar.update();
DataStorageHandler dataStorageHandler = gameActivity.getDataStorageHandler();
dataStorageHandler.getDatabase().open();
dataStorageHandler.getDatabase().writeToolData();
dataStorageHandler.getDatabase().close();
}
public void onToolOfferSlotSelected(ToolOfferSlot slot) {
selectedToolOfferSlot = slot;
for (ToolOfferSlot toolOfferSlot : toolOfferSlots)
toolOfferSlot.setSelected(toolOfferSlot.equals(slot));
toolInspector.update(slot.getToolType(), slot.isLocked());
}
@Override
public void onBackKeyDown() {
gameActivity.getDataStorageHandler().writeUserData(gameActivity.getUser());
flipToCaller();
}
@Override
public void onClick(View v) {
ImageView toolSlotView = (ImageView) v;
int index = toolSlotViews.indexOf(toolSlotView);
if (canSelectedToolBePutInSlot(index)) {
slotSettings.changeToolSlotType(index, selectedToolOfferSlot.getToolType());
for (int i = 0; i < toolSlotViews.size(); i++) {
ToolSlot toolSlot = slotSettings.get(i);
ImageView view = toolSlotViews.get(i);
view.setImageResource(toolSlot.getDrawable());
}
}
}
private boolean canSelectedToolBePutInSlot(int slotIndex) {
return slotIndex != -1 && !slotSettings.get(slotIndex)
.isLocked() && selectedToolOfferSlot != null && selectedToolOfferSlot.getToolType()
.isBought();
}
}

View File

@ -0,0 +1,61 @@
package de.frajul.endlessroll.main.screens;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import java.util.ArrayList;
import java.util.List;
import de.frajul.endlessroll.R;
import de.frajul.endlessroll.levels.LevelPack;
import de.frajul.endlessroll.main.GameActivity;
import de.frajul.endlessroll.views.TopBar;
import de.frajul.endlessroll.views.WorldButton;
import de.frajul.endlessroll.views.WorldButtonOnClickListener;
/**
* Created by Julian on 07.07.2016.
*/
public class WorldsScreen extends Screen<RelativeLayout> implements WorldButtonOnClickListener {
private List<WorldButton> worldButtons = new ArrayList<>();
private TopBar topBar;
private LinearLayout buttonLayout;
public WorldsScreen(GameActivity gameActivity) {
super(ScreenType.WORLDS, gameActivity, R.layout.worlds);
topBar = super.createTopBar(R.id.worlds_topbar);
buttonLayout = (LinearLayout) layout.findViewById(R.id.worlds_layout);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(25, 0, 25, 0);
for (LevelPack levelPack : gameActivity.getLevelManager()) {
WorldButton button = new WorldButton(gameActivity, levelPack, this);
buttonLayout.addView(button.getView(), params);
worldButtons.add(button);
}
}
@Override
public void prepareToBeShown() {
topBar.update();
for (WorldButton button : worldButtons)
button.update();
}
@Override
public void onBackKeyDown() {
flipTo(ScreenType.START);
}
@Override
public void onClick(WorldButton worldButton) {
LevelPack levelPack = worldButton.getLevelPack();
if (!levelPack.isLocked()) {
gameActivity.onWorldSelected(levelPack);
gameActivity.flipToScreen(ScreenType.LEVELS);
}
}
}

View File

@ -0,0 +1,47 @@
package de.frajul.endlessroll.main.tutorial;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
/**
* Created by Julian on 14.03.2017.
*/
public class BreakPoint {
public final static float LEVEL_FINISHED_X = -1;
private float x;
private boolean alreadyShown = false;
@StringRes
private int textId;
@DrawableRes
private int imageId;
public BreakPoint(float x, @StringRes int textId, @DrawableRes int imageId) {
this.x = x;
this.textId = textId;
this.imageId = imageId;
}
public float getX() {
return x;
}
public int getTextId() {
return textId;
}
public int getImageId() {
return imageId;
}
public void setAlreadyShown(boolean alreadyShown) {
this.alreadyShown = alreadyShown;
}
public boolean isAlreadyShown() {
return alreadyShown;
}
}

View File

@ -0,0 +1,72 @@
package de.frajul.endlessroll.main.tutorial;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created by Julian on 14.03.2017.
*/
public class Tutorial {
private int levelId, levelPackId;
private List<BreakPoint> breakPoints;
protected List<BreakPoint> currentBreakPoints = new ArrayList<>();
public Tutorial(int levelId, int levelPackId, BreakPoint... breakPoints) {
this.levelId = levelId;
this.levelPackId = levelPackId;
this.breakPoints = Arrays.asList(breakPoints);
}
public void reset() {
for (BreakPoint breakPoint : breakPoints)
breakPoint.setAlreadyShown(false);
currentBreakPoints.clear();
}
public void onLevelFinished() {
currentBreakPoints.clear();
for (BreakPoint breakPoint : breakPoints) {
if (breakPoint.getX() == BreakPoint.LEVEL_FINISHED_X) {
breakPoint.setAlreadyShown(true);
currentBreakPoints.add(breakPoint);
}
}
}
public void update(float playerProgress) {
playerProgress *= 2f;
currentBreakPoints.clear();
for (BreakPoint breakPoint : breakPoints) {
if (!breakPoint.isAlreadyShown() && playerProgress >= breakPoint.getX() && breakPoint
.getX() != BreakPoint.LEVEL_FINISHED_X) {
breakPoint.setAlreadyShown(true);
currentBreakPoints.add(breakPoint);
}
}
}
public boolean isOverNewBreakPoints() {
return !currentBreakPoints.isEmpty();
}
public List<BreakPoint> getCurrentBreakPoints() {
return currentBreakPoints;
}
public List<BreakPoint> getBreakPoints() {
return breakPoints;
}
public int getLevelId() {
return levelId;
}
public int getLevelPackId() {
return levelPackId;
}
}

View File

@ -0,0 +1,56 @@
package de.frajul.endlessroll.main.tutorial;
import java.util.Arrays;
import java.util.List;
import de.frajul.endlessroll.R;
import de.frajul.endlessroll.levels.Level;
/**
* Created by Julian on 17.03.2017.
*/
public class TutorialManager {
private List<Tutorial> gameTutorials;
private ToolShopTutorial toolShopTutorial;
public TutorialManager() {
Tutorial t11 = new Tutorial(1, 1, new BreakPoint(0, R.string.tutorial_welcome, -1),
new BreakPoint(0, R.string.tutorial_place_tools, R.drawable.tutorial_place_tools),
new BreakPoint(7, R.string.tutorial_place_ramp_gap,
R.drawable.tutorial_place_ramp_gap),
new BreakPoint(21, R.string.tutorial_place_ramp_obstacle,
R.drawable.tutorial_place_ramp_obstacle));
Tutorial t21 = new Tutorial(2, 1, new BreakPoint(11, R.string.tutorial_place_ramp_air,
R.drawable.tutorial_place_ramp_air_1),
new BreakPoint(33, R.string.tutorial_place_ramp_air_2,
R.drawable.tutorial_place_ramp_air_2));
Tutorial t51 = new Tutorial(5, 1,
new BreakPoint(BreakPoint.LEVEL_FINISHED_X, R.string.tutorial_leveled_up, -1),
new BreakPoint(BreakPoint.LEVEL_FINISHED_X, R.string.tutorial_to_toolshop,
R.drawable.tutorial_to_toolshop));
gameTutorials = Arrays.asList(t11, t21, t51);
toolShopTutorial = new ToolShopTutorial();
}
public void resetGameTutorials() {
for (Tutorial tutorial : gameTutorials)
tutorial.reset();
}
public Tutorial getGameTutorial(Level level) {
for (Tutorial tutorial : gameTutorials) {
if (tutorial.getLevelPackId() == level.getPackId() && tutorial.getLevelId() == level
.getId())
return tutorial;
}
return null;
}
public ToolShopTutorial getToolShopTutorial() {
return toolShopTutorial;
}
}

Some files were not shown because too many files have changed in this diff Show More