Added new SFX, dashing, made generation FPS-independent

This commit is contained in:
Anuken 2017-12-10 17:01:14 -05:00
parent 347cae23e5
commit 5ea8f0b8e2
27 changed files with 110 additions and 44 deletions

View File

@ -2,12 +2,12 @@ _Keep in mind that this is just a basic outline of planned features, and will be
### 3.0 Release
- New tutorial with the power blocks
- New SFX for specific blocks, especially turrets
- [DONE] New SFX for specific blocks, especially turrets
- [DONE] Block drawing layers. Refactor/remove `Block#drawOver()`, add `Layer` enum. Should fix 'glitchy' lasers and conveyor clipping
- [DONE] Balance nuclear reactor, improve effectiveness as they are currently underpowered
- Make generation frame independent
- Investigate issue #5 (enemies stuck in blocks)
- Faster mech movement, possibly with a "boost" key
- [DONE] Make generation frame independent
- [DONE/MOVED] Investigate issue #5 (enemies stuck in blocks) - looks like it's caused by map loading lag, needs to be fixed with a slightly different physics system
- [DONE] Faster mech movement, possibly with a "boost" key
- Balance enemy difficulty
### 3.x Planned

View File

@ -13,19 +13,20 @@ import android.util.DisplayMetrics;
import io.anuke.mindustry.io.Formatter;
import io.anuke.ucore.scene.ui.layout.Unit;
public class AndroidLauncher extends AndroidApplication {
public class AndroidLauncher extends AndroidApplication{
boolean doubleScaleTablets = false;
@SuppressLint("SimpleDateFormat")
@Override
protected void onCreate (Bundle savedInstanceState) {
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
config.useImmersiveMode = true;
Mindustry.formatter = new Formatter(){
@SuppressLint("SimpleDateFormat")
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm");
@Override
public String format(Date date){
return format.format(date);
@ -36,23 +37,25 @@ public class AndroidLauncher extends AndroidApplication {
return NumberFormat.getIntegerInstance().format(number);
}
};
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
float yInches= metrics.heightPixels/metrics.ydpi;
float xInches= metrics.widthPixels/metrics.xdpi;
double diagonalInches = Math.sqrt(xInches*xInches + yInches*yInches);
if (diagonalInches>=6.5){
// 6.5inch device or bigger
Unit.dp.multiplier = 2f;
}else{
// smaller device
Unit.dp.multiplier = 1f;
if(doubleScaleTablets){
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
float yInches = metrics.heightPixels / metrics.ydpi;
float xInches = metrics.widthPixels / metrics.xdpi;
double diagonalInches = Math.sqrt(xInches * xInches + yInches * yInches);
if(diagonalInches >= 6.5){
// 6.5inch device or bigger
Unit.dp.multiplier = 2f;
}else{
// smaller device
Unit.dp.multiplier = 1f;
}
}
//Mindustry.args.add("-debug");
initialize(new Mindustry(), config);
}
}

BIN
core/assets/sounds/bang.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
core/assets/sounds/ping.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -22,8 +22,10 @@ public class Vars{
public static final float respawnduration = 60*4;
//time between waves in frames (on normal mode)
public static final float wavespace = 50*60*(android ? 1 : 1);
//waves can last no longer than 6 minutes, otherwise the next one spawns
public static final float maxwavespace = 60*60*6;
//waves can last no longer than 5 minutes, otherwise the next one spawns
public static final float maxwavespace = 60*60*5;
//advance time the pathfinding starts at
public static final float aheadPathfinding = 60*20;
//how far away from spawn points the player can't place blocks
public static final float enemyspawnspace = 65;
//scale of the font
@ -43,7 +45,7 @@ public class Vars{
//whether to draw chunk borders
public static boolean debugChunks = false;
//whether turrets have infinite ammo (only with debug)
public static boolean infiniteAmmo = false;
public static boolean infiniteAmmo = true;
//whether to show paths of enemies
public static boolean showPaths = false;
//if false, player is always hidden

View File

@ -109,6 +109,15 @@ public class Pathfind{
}
}
public boolean finishedUpdating(){
for(SpawnPoint point : Vars.control.getSpawnPoints()){
if(point.pathTiles == null){
return false;
}
}
return true;
}
public void updatePath(){
for(SpawnPoint point : Vars.control.getSpawnPoints()){
point.finder = new IndexedAStarPathFinder<Tile>(graph);

View File

@ -50,6 +50,7 @@ public class Control extends Module{
Array<EnemySpawn> spawns = new Array<>();
int wave = 1;
int lastUpdated = -1;
float wavetime;
float extrawavetime;
int enemies = 0;
@ -90,7 +91,8 @@ public class Control extends Module{
Sounds.load("shoot.wav", "place.wav", "explosion.wav", "enemyshoot.wav",
"corexplode.wav", "break.wav", "spawn.wav", "flame.wav", "die.wav",
"respawn.wav", "purchase.wav", "flame2.wav");
"respawn.wav", "purchase.wav", "flame2.wav", "bigshot.wav", "laser.wav", "lasershot.wav",
"ping.wav", "tesla.wav", "waveend.wav", "railgun.wav", "blast.wav", "bang2.wav");
Sounds.setFalloff(9000f);
@ -103,7 +105,8 @@ public class Control extends Module{
"right", Keys.D,
"zoom_hold", Keys.CONTROL_LEFT,
"menu", Gdx.app.getType() == ApplicationType.Android ? Keys.BACK : Keys.ESCAPE,
"pause", Keys.SPACE
"pause", Keys.SPACE,
"dash", Keys.SHIFT_LEFT
);
for(int i = 0; i < Vars.saveSlots; i ++){
@ -129,6 +132,7 @@ public class Control extends Module{
weapons.add(Weapon.blaster);
player.weapon = weapons.first();
lastUpdated = -1;
wave = 1;
extrawavetime = maxwavespace;
wavetime = waveSpacing();
@ -232,7 +236,10 @@ public class Control extends Module{
public void runWave(){
Sounds.play("spawn");
world.pathfinder().updatePath();
if(lastUpdated < wave + 1){
world.pathfinder().updatePath();
lastUpdated = wave + 1;
}
for(EnemySpawn spawn : spawns){
for(int lane = 0; lane < spawnpoints.size; lane ++){
@ -471,6 +478,15 @@ public class Control extends Module{
if(enemies <= 0){
wavetime -= delta();
if(Vars.debug && Inputs.keyDown(Keys.I)){
wavetime -= delta() * 10f;
}
if(lastUpdated < wave + 1 && wavetime < Vars.aheadPathfinding){ //start updatingbeforehand
world.pathfinder().updatePath();
lastUpdated = wave + 1;
}
}
}

View File

@ -280,8 +280,8 @@ public class Renderer extends RendererModule{
Graphics.end();
int crangex = Math.round(camera.viewportWidth * camera.zoom / (chunksize * tilesize));
int crangey = Math.round(camera.viewportHeight * camera.zoom / (chunksize * tilesize));
int crangex = (int)(camera.viewportWidth * camera.zoom / (chunksize * tilesize))+1;
int crangey = (int)(camera.viewportHeight * camera.zoom / (chunksize * tilesize))+1;
drawCache(0, crangex, crangey);

View File

@ -3,7 +3,6 @@ package io.anuke.mindustry.entities;
import static io.anuke.mindustry.Vars.*;
import com.badlogic.gdx.Input.Buttons;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
@ -26,7 +25,8 @@ public class Player extends DestructibleEntity{
public int rotation;
private Vector2 direction = new Vector2();
private float speed = 1f;
private float speed = 1.1f;
private float dashSpeed = 1.8f;
public Player(){
hitbox.setSize(5);
@ -71,8 +71,13 @@ public class Player extends DestructibleEntity{
float speed = this.speed;
if(Vars.debug && Inputs.keyDown(Keys.SHIFT_LEFT))
speed *= 3f;
if(Inputs.keyDown("dash")){
speed = dashSpeed;
if(Vars.debug){
// speed *= 3f;
}
}
if(health < maxhealth && Timers.get(this, "regen", 50))
health ++;
@ -88,13 +93,18 @@ public class Player extends DestructibleEntity{
if(Inputs.keyDown("right"))
vector.x += speed;
boolean shooting = Inputs.buttonDown(Buttons.LEFT) && recipe == null && !ui.hasMouse() && !Input.onConfigurable();
boolean shooting = !Inputs.keyDown("dash") && Inputs.buttonDown(Buttons.LEFT) && recipe == null && !ui.hasMouse() && !Input.onConfigurable();
if(shooting && Timers.get(this, "reload", weapon.reload)){
weapon.shoot(this);
Sounds.play(weapon.shootsound);
}
if(Inputs.keyDown("dash") && Timers.get(this, "dashfx", 3) && vector.len() > 0){
Angles.translation(direction.angle() + 180, 3f);
Effects.effect(Fx.dashsmoke, x + Angles.x(), y + Angles.y());
}
vector.limit(speed);
if(!Vars.noclip){

View File

@ -438,6 +438,14 @@ public class Fx{
Draw.reset();
}),
dashsmoke = new Effect(30, e -> {
Draw.color(Color.CORAL, Color.GRAY, e.ifract());
//Draw.alpha(e.fract());
float size = e.fract()*4f;
Draw.rect("circle", e.x, e.y, size, size);
Draw.reset();
}),
spawn = new Effect(23, e -> {
Draw.thickness(2f);
Draw.color(Color.DARK_GRAY, Color.SCARLET, e.ifract());

View File

@ -203,7 +203,7 @@ public class Enemy extends DestructibleEntity{
public void onDeath(){
Effects.effect(Fx.explosion, this);
Effects.shake(3f, 4f, this);
Effects.sound("explosion", this);
Effects.sound("bang2", this);
remove();
dead = true;
}

View File

@ -83,7 +83,7 @@ public class HealerEnemy extends Enemy{
void explode(){
Bullet b = new Bullet(BulletType.blast, this, x, y, 0).add();
b.damage = BulletType.blast.damage + (tier-1) * 40;
b.damage = BulletType.blast.damage + (tier-1) * 30;
damage(999);
}

View File

@ -69,6 +69,10 @@ public enum Weapon{
},
railgun(40, BulletType.sniper, "Shoots one long-range bullet.", stack(Item.steel, 60), stack(Item.iron, 60)){
{
shootsound = "railgun";
}
@Override
public void shoot(Player p){
float ang = mouseAngle(p);
@ -79,6 +83,10 @@ public enum Weapon{
},
mortar(100, BulletType.shell, "Shoots a slow, but damaging shell.", stack(Item.titanium, 40), stack(Item.steel, 60)){
{
shootsound = "bigshot";
}
@Override
public void shoot(Player p){
float ang = mouseAngle(p);

View File

@ -99,6 +99,7 @@ public class WeaponBlocks{
sniperturret = new Turret("sniperturret"){
{
shootsound = "railgun";
formalName = "railgun turret";
range = 120;
reload = 50f;
@ -113,6 +114,7 @@ public class WeaponBlocks{
mortarturret = new Turret("mortarturret"){
{
shootsound = "bigshot";
rotatespeed = 0.1f;
formalName = "flak turret";
range = 120;
@ -131,6 +133,7 @@ public class WeaponBlocks{
laserturret = new LaserTurret("laserturret"){
{
shootsound = "laser";
beamColor = Color.SKY;
formalName = "laser turret";
range = 60;
@ -145,6 +148,7 @@ public class WeaponBlocks{
teslaturret = new PowerTurret("waveturret"){
{
shootsound = "tesla";
formalName = "tesla turret";
range = 70;
reload = 15f;
@ -166,6 +170,7 @@ public class WeaponBlocks{
plasmaturret = new Turret("plasmaturret"){
{
shootsound = "flame2";
inaccuracy = 7f;
formalName = "plasma turret";
range = 60f;
@ -181,6 +186,7 @@ public class WeaponBlocks{
chainturret = new Turret("chainturret"){
{
shootsound = "bigshot";
inaccuracy = 8f;
formalName = "chain turret";
range = 80f;
@ -219,6 +225,7 @@ public class WeaponBlocks{
titanturret = new Turret("titancannon"){
{
shootsound = "blast";
formalName = "titan cannon";
range = 120f;
reload = 23f;

View File

@ -25,6 +25,7 @@ public class LaserTurret extends PowerTurret{
super(name);
shootsound = null;
layer2 = Layer.laser;
soundReload = 20;
}
@Override

View File

@ -33,6 +33,7 @@ public class Turret extends Block{
protected final int timerTarget = timers++;
protected final int timerReload = timers++;
protected final int timerSound = timers++;
protected float range = 50f;
protected float reload = 10f;
@ -48,6 +49,7 @@ public class Turret extends Block{
protected float shootCone = 5f;
protected Effect shootEffect = null;
protected float shootShake = 0f;
protected int soundReload = 0;
public Turret(String name) {
super(name);
@ -161,7 +163,7 @@ public class Turret extends Block{
float reload = Vars.multiplier*this.reload;
if(Angles.angleDist(entity.rotation, targetRot) < shootCone && entity.timer.get(timerReload, reload)){
if(shootsound != null) Effects.sound(shootsound, entity);
if(shootsound != null && entity.timer.get(timerSound, soundReload)) Effects.sound(shootsound, entity);
shoot(tile);
consumeAmmo(tile);
entity.ammo --;

View File

@ -72,8 +72,8 @@ public class ItemPowerGenerator extends Generator{
public void update(Tile tile){
PowerEntity entity = tile.entity();
float maxPower = Math.min(powerCapacity - entity.power, powerOutput);
float mfract = maxPower/powerOutput;
float maxPower = Math.min(powerCapacity - entity.power, powerOutput * Timers.delta());
float mfract = maxPower/(powerOutput * Timers.delta());
if(entity.time > 0f){
entity.time -= 1f/itemDuration*mfract;

View File

@ -65,9 +65,8 @@ public class LiquidPowerGenerator extends Generator implements LiquidAcceptor{
public void update(Tile tile){
LiquidPowerEntity entity = tile.entity();
//TODO don't generate when full of energy
if(entity.liquidAmount > 0){
float used = Math.min(entity.liquidAmount, maxLiquidGenerate);
float used = Math.min(entity.liquidAmount, maxLiquidGenerate * Timers.delta());
used = Math.min(used, (powerCapacity - entity.power)/powerPerLiquid);
entity.liquidAmount -= used;

View File

@ -54,7 +54,8 @@ public class NuclearReactor extends LiquidItemPowerGenerator{
if(fuel > 0){
entity.heat += fullness * heating;
entity.power += powerMultiplier * fullness;
entity.power += powerMultiplier * fullness * Timers.delta();
entity.power = Mathf.clamp(entity.power);
if(entity.timer.get(timerFuel, fuelUseTime)){
entity.removeItem(generateItem, 1);
}