Changed bomb completely

This commit is contained in:
=
2018-03-18 12:54:41 +01:00
parent 1417d98169
commit 7684692e53
22 changed files with 403 additions and 207 deletions

View File

@ -6,6 +6,8 @@ uniform vec2 texAtlasSize;
uniform vec2 gridSize;
uniform float deadly;
uniform float floating;
uniform float bombSelected;
uniform float bombExplosionState;
varying vec2 pass_TexCoords;
@ -59,6 +61,13 @@ void main() {
gl_FragColor.a = min(gl_FragColor.a, alpha);
gl_FragColor.rgb = gl_FragColor.rgb / gl_FragColor.a;
if(bombSelected == 1.0 || bombExplosionState >= 0.0){
vec3 red = vec3(1.0, 0.0, 0.0);
float mixValue = 0.4;
gl_FragColor.r += 0.2 * bombExplosionState;
gl_FragColor.rgb = mix(gl_FragColor.rgb, red, mixValue);
}
}
float itermod(in float x, in float y){

View File

@ -21,6 +21,8 @@ public class Obstacle extends Entity {
private float moveProgress;
private float moveDirection;
private int bombExplosionState = -1;
public Obstacle(World world, ObstacleData data, float terrainEdge, Player player) {
super(world.getObstacleTexture(), new Vector(data.getX(), data.getY()), data.getWidth(),
data.getHeight());
@ -98,4 +100,11 @@ public class Obstacle extends Entity {
return gridSize;
}
public int getBombExplosionState() {
return bombExplosionState;
}
public void setBombExplosionState(int bombExplosionState) {
this.bombExplosionState = bombExplosionState;
}
}

View File

@ -19,6 +19,15 @@ public class CollisionDetector {
triangleDetector = new CircleTriangleCollisionDetector();
}
public boolean isPointQuadCollision(Vector point, Quad quad) {
if (point.getX() >= quad.getLeftEdge() && point.getX() <= quad.getRightEdge()) {
if (point.getY() >= quad.getBottomEdge() && point.getY() <= quad.getTopEdge()) {
return true;
}
}
return false;
}
public boolean isCircleCircleCollision(Circle c1, Circle c2) {
float distance = Math.abs(c1.getCenter().vectorTo(c2.getCenter()).length());
float radiusSum = c1.getRadius() + c2.getRadius();

View File

@ -1,14 +1,11 @@
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.GameLog;
import de.frajul.endlessroll.main.game.Timer;
/**
@ -16,29 +13,36 @@ import de.frajul.endlessroll.main.game.Timer;
*/
public class Bomb extends Tool {
public final float RANGE = 1;
private float delta;
private boolean exploding = false;
private Obstacle attachedObstacle;
private Vector offsetToObstaclePosition = new Vector();
public Bomb(Vector position) {
super(ToolType.BOMB, position, .29f, .29f, false, false);
super(ToolType.BOMB, position, .2f, .2f, false, false);
animation.setIndexSequence(new int[]{0, 1, 2});
animation.setLooping(false);
animation.setRequiredDelta(
(int) (ToolType.BOMB.getCurrentUpgradeValue(ToolUpgradeType.DURATION) / 3));
(int) (ToolType.BOMB.getCurrentUpgradeValue(ToolUpgradeType.DURATION) / 3f));
}
@Override
public void update(Timer timer) {
super.update(timer);
float explosionDuration = ToolType.BOMB.getCurrentUpgradeValue(ToolUpgradeType.DURATION);
delta += timer.getFrameTimeSeconds();
if (delta >= ToolType.BOMB.getCurrentUpgradeValue(ToolUpgradeType.DURATION))
int currentExplosionState = Math.min((int) (delta / (explosionDuration / 3f)), 3);
if (attachedObstacle != null) {
if(attachedObstacle.isMoving())
super.setPosition(new Vector(attachedObstacle.getPosition()).translate(offsetToObstaclePosition));
attachedObstacle.setBombExplosionState(currentExplosionState);
}
if (delta >= explosionDuration)
exploding = true;
}
@Override
public void onPlayerCollision(Player player, Timer timer) {
}
@Override
@ -51,17 +55,19 @@ public class Bomb extends Tool {
return this;
}
public void setAttachedObstacle(Obstacle attachedObstacle) {
this.attachedObstacle = attachedObstacle;
offsetToObstaclePosition = attachedObstacle.getPosition().vectorTo(super.getPosition());
attachedObstacle.setBombExplosionState(0);
}
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);
}
public void explode() {
if (attachedObstacle != null)
attachedObstacle.destroy(DestroyEffect.EXPLOSION);
super.destroy(DestroyEffect.EXPLOSION);
}
}

View File

@ -24,9 +24,8 @@ public enum ToolType {
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, 12, 4, 5,
new ToolUpgrade(ToolUpgradeType.COOLDOWN, 6000, 4000),
new ToolUpgrade(ToolUpgradeType.DURATION, 1200, 400),
new ToolUpgrade(ToolUpgradeType.RANGE, 100, 200)),
new ToolUpgrade(ToolUpgradeType.COOLDOWN, 5000, 2000),
new ToolUpgrade(ToolUpgradeType.DURATION, 1200, 500)),
MAGNET(R.string.tool_name_magnet, R.string.tool_description_magnet, R.drawable.tools_magnet,
R.drawable.tools_magnet_button, 10, 2, 5,
new ToolUpgrade(ToolUpgradeType.COOLDOWN, 5000, 3000),

View File

@ -6,6 +6,6 @@ package de.frajul.endlessroll.entities.tools;
public enum ToolUpgradeType {
COOLDOWN, DURATION, FORCE, RANGE, SIZE;
COOLDOWN, DURATION, FORCE, SIZE;
}

View File

@ -8,6 +8,7 @@ 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.collectables.Energy;
import de.frajul.endlessroll.entities.collectables.Star;
@ -15,6 +16,8 @@ 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.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.LevelPack;
@ -100,7 +103,7 @@ public class Game extends Rendering<GameScene> {
gameActivity.getUser().getCurrentPlayerShape());
player = scene.getPlayer();
viewManager.resetViews(gameActivity.getUser());
currentTool = viewManager.toolButtonBar.getActiveButton().getToolType();
setCurrentTool(viewManager.toolButtonBar.getActiveButton().getToolType(), true);
viewManager.startCountdown();
}
} catch (Exception e) {
@ -161,6 +164,27 @@ public class Game extends Rendering<GameScene> {
ToolButton button = bar.getByToolType(currentTool);
if (button != null && button.finishedLoading()) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (currentTool == ToolType.BOMB) {
try {
Vector touchPoint = scene
.calcWorldFromScreenCoords(event.getX(), event.getY());
Obstacle selectedObstacle = scene.getObstacleAtPoint(touchPoint);
if (selectedObstacle == null) {
viewManager.showBombErrorMessage(event.getX(), event.getY());
return true;
} else {
button.setProgress(0);
scene.getBombSelected().set(false);
Tool tool = addTool(event.getX(), event.getY());
if (tool != null && tool instanceof Bomb)
((Bomb) tool).setAttachedObstacle(selectedObstacle);
return true;
}
} catch (Exception e) {
onException(e);
return true;
}
}
button.setProgress(0);
addTool(event.getX(), event.getY());
}
@ -193,12 +217,18 @@ public class Game extends Rendering<GameScene> {
handler.toScreen(Screen.ScreenType.LEVELS);
}
public void toToolShop() {
handler.toScreen(Screen.ScreenType.TOOL_SHOP);
public void onToolButtonFinishedLoading(ToolType toolType){
if(currentTool == ToolType.BOMB && toolType == ToolType.BOMB)
scene.getBombSelected().set(true);
}
public void setCurrentTool(ToolType toolType) {
public void setCurrentTool(ToolType toolType, boolean toolButtonFinishedLoading) {
currentTool = toolType;
if (currentTool == ToolType.BOMB && toolButtonFinishedLoading) {
scene.getBombSelected().set(true);
} else {
scene.getBombSelected().set(false);
}
}
public void pauseWithoutMenu() {
@ -224,13 +254,14 @@ public class Game extends Rendering<GameScene> {
gameState = GameState.RUNNING;
}
private void addTool(float x, float y) {
private Tool addTool(float x, float y) {
try {
gameActivity.getSoundManager().playSound(gameActivity.getSoundManager().placeToolSound);
scene.addTool(currentTool, x, y, physics);
return scene.addTool(currentTool, x, y, physics);
} catch (Exception e) {
onException(e);
}
return null;
}
public void onGameOver(boolean playerExplode) {
@ -271,8 +302,6 @@ public class Game extends Rendering<GameScene> {
firework.start();
gameActivity.getSoundManager().playSound(gameActivity.getSoundManager().fireworkSound);
//viewManager.showGameOverMessage(levelPack.isLastLevel(level), MessageType.WIN);
//TODO: fadeInWithDelay something
viewManager.showGoalMessage(levelPack, level);
MyDatabase database = gameActivity.getDataStorageHandler().getDatabase();

View File

@ -81,7 +81,7 @@ public class GameScene extends Scene {
obstacles.add(obstacle);
}
public void addTool(ToolType type, float screenX, float screenY, Physics physics) throws Exception {
public Tool addTool(ToolType type, float screenX, float screenY, Physics physics) throws Exception {
Vector position = calcWorldFromScreenCoords(screenX, screenY);
Tool tool = type.newInstance(position, particleSystem, gameActivity.getSoundManager());
physics.checkSingleToolCollision(tool, this);
@ -90,8 +90,18 @@ public class GameScene extends Scene {
throw new Exception(
"Current ToolType(" + type + ") returns null at method newInstance()");
tools.add(tool);
return tool;
}
public Obstacle getObstacleAtPoint(Vector point) {
synchronized (obstacles) {
for (Obstacle obstacle : obstacles) {
if (collisionDetector.isPointQuadCollision(point, obstacle))
return obstacle;
}
}
return null;
}
public void update(Timer timer) {
player.setSpeedByProgress(player.getProgress() / goalX);
@ -125,12 +135,11 @@ public class GameScene extends Scene {
if (tool instanceof Bomb) {
Bomb bomb = (Bomb) tool;
if (bomb.isExploding())
bomb.explode(obstacles, collisionDetector);
}
else if (tool instanceof Stasis) {
bomb.explode();
} else if (tool instanceof Stasis) {
Stasis stasis = (Stasis) tool;
stasis.updateSoundVolume(player);
} else if(tool instanceof Magnet){
} else if (tool instanceof Magnet) {
Magnet magnet = (Magnet) tool;
magnet.updateSoundVolume(player);
}

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.AnimatedEntity;
@ -43,11 +44,12 @@ public abstract class Scene {
protected Ceiling ceiling;
protected Player player;
protected ParticleSource enviromentParticles;
protected AtomicBoolean bombSelected;
protected List<Entity> uncategorizedEntities = Collections
protected final 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 final List<Obstacle> obstacles = Collections.synchronizedList(new ArrayList<Obstacle>());
protected final List<Tool> tools = Collections.synchronizedList(new ArrayList<Tool>());
protected Collectables collectables = new Collectables();
public Scene(GameActivity gameActivity, TexturePack texturePack, ParticleSystem particleSystem) {
@ -60,6 +62,7 @@ public abstract class Scene {
terrain = new Terrain(World.GRASSLANDS.getTerrainTexture());
ceiling = new Ceiling(World.GRASSLANDS.getTerrainTexture());
player = new Player();
bombSelected = new AtomicBoolean(false);
}
public void setTexturePack(TexturePack texturePack) {
@ -204,4 +207,8 @@ public abstract class Scene {
public Camera getCamera() {
return camera;
}
public synchronized AtomicBoolean getBombSelected() {
return bombSelected;
}
}

View File

@ -138,6 +138,7 @@ public class GameRenderer implements GLSurfaceView.Renderer {
List<Obstacle> obstacles = scene.getObstacles();
obstacleShader.start();
obstacleShader.loadMVPMatrix(matrixCreator, scene.getCamera());
obstacleShader.loadBombSelected(scene.getBombSelected().get());
synchronized (obstacles) {
for (Obstacle obstacle : obstacles)
renderObstacle(gl, obstacle);
@ -155,6 +156,7 @@ public class GameRenderer implements GLSurfaceView.Renderer {
obstacleShader.loadGridSize(obstacle.getGridSize());
obstacleShader.loadDeadly(obstacle.isDeadly());
obstacleShader.loadFloating(obstacle.isFloating());
obstacleShader.loadBombExplosionState(obstacle.getBombExplosionState());
quad.draw();
}

View File

@ -21,6 +21,8 @@ public class ObstacleShader extends ShaderProgram {
private int location_gridSize;
private int location_deadly;
private int location_floating;
private int location_bombSelected;
private int location_bombExplosionState;
public ObstacleShader(Context context) throws Exception {
super(context, "shader/entityVertexShader.glsl", "shader/obstacleFragmentShader.glsl");
@ -35,6 +37,8 @@ public class ObstacleShader extends ShaderProgram {
location_gridSize = super.getUniformLocation("gridSize");
location_deadly = super.getUniformLocation("deadly");
location_floating = super.getUniformLocation("floating");
location_bombSelected = super.getUniformLocation("bombSelected");
location_bombExplosionState = super.getUniformLocation("bombExplosionState");
}
public void loadMVPMatrix(MatrixCreator matrixCreator, Camera camera) {
@ -68,4 +72,12 @@ public class ObstacleShader extends ShaderProgram {
GLES20.glUniform1f(location_floating, floating ? 1 : 0);
}
public void loadBombSelected(boolean bombSelected){
GLES20.glUniform1f(location_bombSelected, bombSelected ? 1 : 0);
}
public void loadBombExplosionState(int explosionState){
GLES20.glUniform1f(location_bombExplosionState, explosionState);
}
}

View File

@ -0,0 +1,56 @@
package de.frajul.endlessroll.views;
import android.view.LayoutInflater;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
import de.frajul.endlessroll.R;
import de.frajul.endlessroll.main.GameActivity;
/**
* Created by Julian on 18.03.2018.
*/
public class BombErrorMessage implements Animation.AnimationListener{
private TextView view;
private Animation animation;
private boolean animationRunning = false;
public BombErrorMessage(GameActivity gameActivity){
LayoutInflater inflater = LayoutInflater.from(gameActivity);
view = (TextView) inflater.inflate(R.layout.bomb_error_message, null);
view.setTypeface(gameActivity.getTypeface());
animation = AnimationUtils.loadAnimation(gameActivity, R.anim.fade_out_accelerating);
animation.setAnimationListener(this);
}
public void show(float xPos, float yPos){
animationRunning = true;
view.setX(xPos - (float) view.getWidth() / 2);
view.setY(yPos);
view.startAnimation(animation);
}
@Override
public void onAnimationEnd(Animation animation) {
animationRunning = false;
}
public TextView getView() {
return view;
}
public boolean isAnimationRunning() {
return animationRunning;
}
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
}

View File

@ -13,12 +13,14 @@ import de.frajul.endlessroll.R;
import de.frajul.endlessroll.entities.tools.ToolSlot;
import de.frajul.endlessroll.entities.tools.ToolType;
import de.frajul.endlessroll.entities.tools.ToolUpgradeType;
import de.frajul.endlessroll.main.game.Game;
/**
* Created by Julian on 15.01.2016.
*/
public class ToolButton {
private Game game;
private boolean locked;
private ToolType toolType;
private Context context;
@ -31,8 +33,9 @@ public class ToolButton {
private ImageView animationView;
private Animation scaleAnimation;
public ToolButton(ToolSlot slot, Context context, RelativeLayout layout) {
public ToolButton(ToolSlot slot, Game game, Context context, RelativeLayout layout) {
this.context = context;
this.game = game;
this.layout = layout;
progressBar = (ProgressBar) layout.findViewById(R.id.tool_button_progress_bar);
@ -80,9 +83,10 @@ public class ToolButton {
progressBar.setProgress(100 - (int) progress);
if (!locked && toolType != null) {
if (active) {
if (progress == 100)
if (progress == 100) {
game.onToolButtonFinishedLoading(toolType);
setColor(R.color.toolbuttonActiveReady);
else
}else
setColor(R.color.toolbuttonActiveNotReady);
} else {
if (progress == 100)

View File

@ -59,10 +59,10 @@ public class ToolButtonBar implements View.OnClickListener, Animation.AnimationL
button3.setOnClickListener(this);
button4 = (RelativeLayout) layout1.findViewById(R.id.toolbutton_4);
button4.setOnClickListener(this);
buttons.add(new ToolButton(toolSlotSettings.get(0), context, button1));
buttons.add(new ToolButton(toolSlotSettings.get(1), context, button2));
buttons.add(new ToolButton(toolSlotSettings.get(2), context, button3));
buttons.add(new ToolButton(toolSlotSettings.get(3), context, button4));
buttons.add(new ToolButton(toolSlotSettings.get(0), game, context, button1));
buttons.add(new ToolButton(toolSlotSettings.get(1), game, context, button2));
buttons.add(new ToolButton(toolSlotSettings.get(2), game, context, button3));
buttons.add(new ToolButton(toolSlotSettings.get(3), game, context, button4));
}
public void setTopPrimary() {
@ -130,19 +130,19 @@ public class ToolButtonBar implements View.OnClickListener, Animation.AnimationL
@Override
public void onClick(View v) {
if (game.getGameState() == GameState.RUNNING) {
ToolType clickedType = null;
ToolButton clickedButton = null;
if (v.equals(button1) && !buttons.get(0).isLocked()) {
clickedType = buttons.get(0).getToolType();
clickedButton = buttons.get(0);
} else if (v.equals(button2) && !buttons.get(1).isLocked()) {
clickedType = buttons.get(1).getToolType();
clickedButton = buttons.get(1);
} else if (v.equals(button3) && !buttons.get(2).isLocked()) {
clickedType = buttons.get(2).getToolType();
clickedButton = buttons.get(2);
} else if (v.equals(button4) && !buttons.get(3).isLocked()) {
clickedType = buttons.get(3).getToolType();
clickedButton = buttons.get(3);
}
if (clickedType != null) {
game.setCurrentTool(clickedType);
setActive(clickedType);
if (clickedButton != null) {
game.setCurrentTool(clickedButton.getToolType(), clickedButton.finishedLoading());
setActive(clickedButton.getToolType());
}
}
}

View File

@ -6,6 +6,9 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import de.frajul.endlessroll.R;
import de.frajul.endlessroll.levels.Level;
import de.frajul.endlessroll.levels.LevelPack;
@ -23,6 +26,7 @@ public class ViewManager implements View.OnClickListener {
private GameHandler gameViewHandler;
private Game game;
private GameActivity gameActivity;
private TextView fpsView;
private TextView playerProgress;
@ -34,11 +38,14 @@ public class ViewManager implements View.OnClickListener {
public ShortMenu shortMenu;
private Countdown countdown;
private List<BombErrorMessage> bombErrorMessages = new ArrayList<>();
private String fpsFormat, playerProgressFormat, playerSpeedFormat;
public ViewManager(final Game game, final GameScreen gameScreen, final GameHandler gameViewHandler, final GameActivity gameActivity) {
this.game = game;
this.gameViewHandler = gameViewHandler;
this.gameActivity = gameActivity;
final RelativeLayout layout = gameViewHandler.getRootLayout();
gameViewHandler.startInUiThread(new Runnable() {
@ -61,8 +68,11 @@ public class ViewManager implements View.OnClickListener {
pauseButton = (ImageView) layout.findViewById(R.id.game_pausebutton);
pauseButton.setOnClickListener(this);
playerProgress = (TextView) layout.findViewById(R.id.game_playerprogress);
playerProgress.setTypeface(gameActivity.getTypeface());
playerSpeed = (TextView) layout.findViewById(R.id.game_playerspeed);
playerSpeed.setTypeface(gameActivity.getTypeface());
fpsView = (TextView) layout.findViewById(R.id.game_fps);
fpsView.setTypeface(gameActivity.getTypeface());
fpsFormat = game.getContext().getString(R.string.game_fps_format_d);
playerProgressFormat = game.getContext().getString(R.string.game_playerprogress_format_f);
@ -78,6 +88,19 @@ public class ViewManager implements View.OnClickListener {
goalMessage.prepareToBeShown();
}
public void showBombErrorMessage(float xPos, float yPos) {
for (BombErrorMessage bombErrorMessage : bombErrorMessages) {
if (!bombErrorMessage.isAnimationRunning()) {
bombErrorMessage.show(xPos, yPos);
return;
}
}
BombErrorMessage bombErrorMessage = new BombErrorMessage(gameActivity);
bombErrorMessage.show(xPos, yPos);
gameViewHandler.getRootLayout().addView(bombErrorMessage.getView());
bombErrorMessages.add(bombErrorMessage);
}
@Override
public void onClick(View v) {
game.tryToPause();

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<alpha
android:duration="1000"
android:fromAlpha="1"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="0" />
</set>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/game_bomb_error_message"
android:textColor="@color/red"
android:textSize="20sp"
android:visibility="invisible"/>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="game_bomb_error_message">Setze die Bombe auf ein Hindernis</string>
<string name="placeholder_button">Drück mich!</string>
<string name="placeholder_textview">Ich bin ein Text!</string>
<string name="message_level_finished">ZIEL ERREICHT</string>

View File

@ -4,6 +4,7 @@
<string name="placeholder_textview">I\'m a text!</string>
<string name="placeholder_number" translatable="false">997.5</string>
<string name="game_bomb_error_message">Set the bomb on an obstacle</string>
<string name="game_playerprogress_placeholder" translatable="false">0.0m</string>
<string name="game_playerprogress_format_f" translatable="false">%.1fm</string>
<string name="game_playerspeed_placeholder" translatable="false">0.0m/s</string>
@ -110,7 +111,7 @@
<string name="credits_testers_title">TESTERS</string>
<string name="credits_testers" translatable="false">Tester1\nTester2\nTester3\nTester4</string>
<string name="credits_sounds_title" translatable="false">SOUNDS</string>
<string name="credits_sounds" translatable="false">www.noiseforfun.com</string>
<string name="credits_sounds" translatable="false">„Fruit-collected“, „Glocken-good“, „Carillon-02-a“, „Carillon-02-b“,„Fireball-02“, „Fruit-appearance“, „Voltage-hum“ (noiseforfun.com)</string>
<string name="credits_music_title">MUSIC</string>
<string name="credits_music" translatable="false">\"Balloon Game\", \"Bit Shift\", \"Digital Lemonade\"\nKevin MacLeod (incompetech.com)\nLicensed under Creative Commons: By Attribution 3.0\nhttp://creativecommons.org/licenses/by/3.0/</string>
</resources>