Completely new continuous collision system to prevent piercing

This commit is contained in:
Anuken
2018-03-03 01:14:14 -05:00
parent 94f6c1b902
commit 2122d04f78
15 changed files with 113 additions and 83 deletions

View File

@ -1,7 +1,7 @@
#Autogenerated file. Do not modify.
#Fri Mar 02 14:57:27 EST 2018
#Sat Mar 03 01:13:15 EST 2018
version=release
androidBuildCode=321
androidBuildCode=328
name=Mindustry
code=3.4
build=custom build

View File

@ -139,6 +139,6 @@ public class Vars{
public static final EntityGroup<Enemy> enemyGroup = Entities.addGroup(Enemy.class).enableMapping();
public static final EntityGroup<TileEntity> tileGroup = Entities.addGroup(TileEntity.class, false);
public static final EntityGroup<Bullet> bulletGroup = Entities.addGroup(Bullet.class);
public static final EntityGroup<Shield> shieldGroup = Entities.addGroup(Shield.class);
public static final EntityGroup<EffectEntity> effectGroup = Entities.addGroup(EffectEntity.class);
public static final EntityGroup<Shield> shieldGroup = Entities.addGroup(Shield.class, false);
public static final EntityGroup<EffectEntity> effectGroup = Entities.addGroup(EffectEntity.class, false);
}

View File

@ -151,8 +151,8 @@ public class Logic extends Module {
Entities.update(shieldGroup);
Entities.update(playerGroup);
Entities.collideGroups(enemyGroup, bulletGroup);
Entities.collideGroups(playerGroup, bulletGroup);
Entities.collideGroups(bulletGroup, enemyGroup);
Entities.collideGroups(bulletGroup, playerGroup);
}
}
}

View File

@ -29,7 +29,7 @@ public class ThreadHandler {
Timers.setDeltaProvider(() ->{
float result = impl.isOnThread() ? delta : Gdx.graphics.getDeltaTime()*60f;
return Float.isNaN(result) ? 1f : result;
return Math.min(Float.isNaN(result) ? 1f : result, 12f);
});
}

View File

@ -126,6 +126,10 @@ public class World extends Module{
public Tile tileWorld(float x, float y){
return tile(Mathf.scl2(x, tilesize), Mathf.scl2(y, tilesize));
}
public int toTile(float coord){
return Mathf.scl2(coord, tilesize);
}
public Tile[][] getTiles(){
return tiles;
@ -319,4 +323,37 @@ public class World extends Module{
}
return null;
}
public void raycastEach(int x0f, int y0f, int x1, int y1, Raycaster cons){
int x0 = x0f;
int y0 = y0f;
int dx = Math.abs(x1 - x0);
int dy = Math.abs(y1 - y0);
int sx = x0 < x1 ? 1 : -1;
int sy = y0 < y1 ? 1 : -1;
int err = dx - dy;
int e2;
while(true){
if(cons.accept(x0, y0)) break;
if(x0 == x1 && y0 == y1) break;
e2 = 2 * err;
if(e2 > -dy){
err = err - dy;
x0 = x0 + sx;
}
if(e2 < dx){
err = err + dx;
y0 = y0 + sy;
}
}
}
public interface Raycaster{
boolean accept(int x, int y);
}
}

View File

@ -1,10 +1,10 @@
package io.anuke.mindustry.entities;
import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.entities.BulletEntity;
import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.entities.SolidEntity;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Timer;
import static io.anuke.mindustry.Vars.*;
@ -36,49 +36,38 @@ public class Bullet extends BulletEntity{
public float drawSize(){
return 8;
}
public boolean collidesTiles(){
return owner instanceof Enemy;
}
@Override
public void update(){
int tilex = Mathf.scl2(x, tilesize);
int tiley = Mathf.scl2(y, tilesize);
Tile tile = world.tile(tilex, tiley);
TileEntity targetEntity = null;
if(tile != null){
if(tile.entity != null && tile.entity.collide(this) && !tile.entity.dead){
targetEntity = tile.entity;
}else{
//make sure to check for linked block collisions
Tile linked = tile.getLinked();
if(linked != null &&
linked.entity != null && linked.entity.collide(this) && !linked.entity.dead){
targetEntity = linked.entity;
}
}
}
if(targetEntity != null){
targetEntity.collision(this);
remove();
type.removed(this);
}
super.update();
if (collidesTiles()) {
world.raycastEach(world.toTile(lastX), world.toTile(lastY), world.toTile(x), world.toTile(y), (x, y) -> {
Tile tile = world.tile(x, y);
if (tile == null) return false;
tile = tile.target();
if (tile.entity != null && tile.entity.collide(this) && !tile.entity.dead) {
tile.entity.collision(this);
remove();
type.hit(this);
return true;
}
return false;
});
}
}
@Override
public boolean collides(SolidEntity other){
if(owner instanceof TileEntity && other instanceof Player)
return false;
return super.collides(other);
}
@Override
public void collision(SolidEntity other){
super.collision(other);
type.removed(this);
return true;
}
@Override
@ -90,5 +79,4 @@ public class Bullet extends BulletEntity{
public Bullet add(){
return super.add(bulletGroup);
}
}

View File

@ -79,10 +79,10 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
}
public void despawned(Bullet b){
removed(b);
hit(b);
}
public void removed(Bullet b){
public void hit(Bullet b, float hitx, float hity){
Timers.run(5f, ()-> new EMP(b.x, b.y, b.getDamage()).add());
Effects.effect(Fx.empshockwave, b);
Effects.shake(3f, 3f, b);
@ -113,10 +113,10 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
}
public void despawned(Bullet b){
removed(b);
hit(b);
}
public void removed(Bullet b){
public void hit(Bullet b, float hitx, float hity){
Effects.shake(3f, 3f, b);
Effects.effect(Fx.shellsmoke, b);
@ -146,16 +146,16 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
Draw.reset();
}
public void removed(Bullet b) {
despawned(b);
public void hit(Bullet b, float hitx, float hity) {
Effects.effect(shellsmoke, b);
for(int i = 0; i < 3; i ++){
Bullet bullet = new Bullet(flakspark, b.owner, hitx, hity, b.angle() + Mathf.range(120f));
bullet.add();
}
}
public void despawned(Bullet b) {
Effects.effect(shellsmoke, b);
for(int i = 0; i < 3; i ++){
Bullet bullet = new Bullet(flakspark, b.owner, b.x, b.y, b.angle() + Mathf.range(120f));
bullet.add();
}
hit(b, b.x, b.y);
}
},
flakspark = new BulletType(2f, 2) {
@ -193,10 +193,10 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
}
public void despawned(Bullet b){
removed(b);
hit(b);
}
public void removed(Bullet b){
public void hit(Bullet b, float hitx, float hity){
Effects.shake(3f, 3f, b);
Effects.effect(Fx.shellsmoke, b);
@ -224,10 +224,10 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
}
public void despawned(Bullet b){
removed(b);
hit(b);
}
public void removed(Bullet b){
public void hit(Bullet b, float hitx, float hity){
Effects.shake(3f, 3f, b);
Effects.effect(Fx.shellsmoke, b);
@ -244,19 +244,19 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
}
public void despawned(Bullet b){
removed(b);
hit(b);
}
public void removed(Bullet b){
public void hit(Bullet b, float hitx, float hity){
Effects.shake(3f, 3f, b);
Effects.effect(Fx.blastsmoke, b);
Effects.effect(Fx.blastexplosion, b);
//TODO remove translation() usage
Angles.circleVectors(30, 6f, (x, y) -> {
float ang = Mathf.atan2(x, y);
Bullet o = new Bullet(blastshot, b.owner, b.x + x, b.y + y, ang).add();
Angles.circleVectors(30, 6f, (nx, ny) -> {
float ang = Mathf.atan2(nx, ny);
Bullet o = new Bullet(blastshot, b.owner, b.x + nx, b.y + ny, ang).add();
o.damage = b.damage/9;
});
}
@ -363,10 +363,10 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
}
public void despawned(Bullet b){
removed(b);
hit(b);
}
public void removed(Bullet b){
public void hit(Bullet b, float hitx, float hity){
Effects.shake(1.5f, 1.5f, b);
Effects.effect(Fx.clusterbomb, b);
@ -415,10 +415,10 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
}
public void despawned(Bullet b) {
removed(b);
hit(b);
}
public void removed(Bullet b) {
public void hit(Bullet b, float hitx, float hity) {
for(int i = 0; i < 4; i ++){
Bullet bullet = new Bullet(scrap, b.owner, b.x, b.y, b.angle() + Mathf.range(80f));
bullet.add();
@ -479,7 +479,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
}
@Override
public void removed(Bullet b){
Effects.effect(Fx.hit, b);
public void hit(Bullet b, float hitx, float hity){
Effects.effect(Fx.hit, hitx, hity);
}
}

View File

@ -150,7 +150,7 @@ public class Player extends SyncEntity{
public void update(){
if(!isLocal || isAndroid){
if(isAndroid && isLocal){
angle = Mathf.lerpAngDelta(angle, targetAngle, 0.2f);
angle = Mathf.slerpDelta(angle, targetAngle, 0.2f);
}
if(!isLocal) interpolate();
return;
@ -216,10 +216,10 @@ public class Player extends SyncEntity{
if(!shooting){
if(!movement.isZero())
angle = Mathf.lerpAngDelta(angle, movement.angle(), 0.13f);
angle = Mathf.slerpDelta(angle, movement.angle(), 0.13f);
}else{
float angle = Angles.mouseAngle(x, y);
this.angle = Mathf.lerpAngDelta(this.angle, angle, 0.1f);
this.angle = Mathf.slerpDelta(this.angle, angle, 0.1f);
}
x = Mathf.clamp(x, 0, world.width() * tilesize);

View File

@ -59,7 +59,7 @@ public abstract class SyncEntity extends DestructibleEntity{
this.x = spos.x = Mathf.lerpDelta(spos.x, x, 0.2f);
this.y = spos.y = Mathf.lerpDelta(spos.y, y, 0.2f);
this.angle = spos.z = Mathf.lerpAngDelta(spos.z, angle, 0.3f);
this.angle = spos.z = Mathf.slerpDelta(spos.z, angle, 0.3f);
}
drawSmooth();
@ -124,7 +124,7 @@ public abstract class SyncEntity extends DestructibleEntity{
Mathf.lerp2(pos.set(last), target, time);
angle = Mathf.lerpAngDelta(angle, targetrot, 0.6f);
angle = Mathf.slerpDelta(angle, targetrot, 0.6f);
if(target.dst(pos) > 128){
pos.set(target);

View File

@ -1,6 +1,5 @@
package io.anuke.mindustry.entities;
import io.anuke.mindustry.entities.enemies.Enemy;
import io.anuke.mindustry.graphics.Fx;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetEvents;
@ -22,7 +21,7 @@ import static io.anuke.mindustry.Vars.tileGroup;
import static io.anuke.mindustry.Vars.world;
public class TileEntity extends Entity{
private static final boolean friendlyFire = false;
private static final boolean friendlyFire = true;
public Tile tile;
public int[] items = new int[Item.getAllItems().size];
@ -101,7 +100,7 @@ public class TileEntity extends Entity{
}
public boolean collide(Bullet other){
return other.owner instanceof Enemy || friendlyFire;
return true;
}
@Override

View File

@ -144,9 +144,9 @@ public class EnemyType {
}
if(enemy.target == null || alwaysRotate){
enemy.angle = Mathf.slerp(enemy.angle, enemy.velocity.angle(), rotatespeed * Timers.delta());
enemy.angle = Mathf.slerpDelta(enemy.angle, enemy.velocity.angle(), rotatespeed);
}else{
enemy.angle = Mathf.slerp(enemy.angle, enemy.angleTo(enemy.target), turretrotatespeed * Timers.delta());
enemy.angle = Mathf.slerpDelta(enemy.angle, enemy.angleTo(enemy.target), turretrotatespeed);
}
enemy.x = Mathf.clamp(enemy.x, 0, world.width() * tilesize);

View File

@ -235,6 +235,12 @@ public class Tile{
}
}
public Tile target(){
Tile link = getLinked();
return link == null ? this : link;
}
public Tile getNearby(int rotation){
if(rotation == 0) return world.tile(x + 1, y);
if(rotation == 1) return world.tile(x, y + 1);

View File

@ -56,7 +56,7 @@ public class RepairTurret extends PowerTurret{
}
float target = entity.angleTo(entity.blockTarget);
entity.rotation = Mathf.slerp(entity.rotation, target, 0.16f*Timers.delta());
entity.rotation = Mathf.slerpDelta(entity.rotation, target, 0.16f);
int maxhealth = entity.blockTarget.tile.block().health;

View File

@ -72,7 +72,7 @@ public class NuclearReactor extends LiquidPowerGenerator{
float fullness = (float)fuel / itemCapacity;
if(fuel > 0){
entity.heat += fullness * heating * Timers.delta();
entity.heat += fullness * heating * Math.min(Timers.delta(), 4f);
entity.power += powerMultiplier * fullness * Timers.delta();
entity.power = Mathf.clamp(entity.power, 0f, powerCapacity);
if(entity.timer.get(timerFuel, fuelUseTime)){