v0.5.0: fixed many vfx alignment issues

This commit is contained in:
Evan Debenham 2017-01-04 19:09:54 -05:00
parent cc2b0a0cb8
commit 26daff58b2
28 changed files with 383 additions and 244 deletions

View File

@ -147,6 +147,14 @@ public class Visual extends Gizmo {
y = p.y - height / 2;
return p;
}
//returns the point needed to center the argument visual on this visual
public PointF center( Visual v ) {
return new PointF(
x + (width() - v.width())/2f,
y + (height() - v.height())/2f
);
}
public float width() {
return width * scale.x;

View File

@ -45,7 +45,7 @@ public class WaterOfAwareness extends WellWater {
protected boolean affectHero( Hero hero ) {
Sample.INSTANCE.play( Assets.SND_DRINK );
emitter.parent.add( new Identification( DungeonTilemap.tileCenterToWorld( pos ) ) );
emitter.parent.add( new Identification( hero.sprite.center() ) );
hero.belongings.observe();

View File

@ -108,7 +108,7 @@ public class Guard extends Mob {
} else {
final int newPosFinal = newPos;
yell( Messages.get(this, "scorpion") );
sprite.parent.add(new Chains(pos, enemy.pos, new Callback() {
sprite.parent.add(new Chains(sprite.center(), enemy.sprite.center(), new Callback() {
public void call() {
Actor.addDelayed(new Pushing(enemy, enemy.pos, newPosFinal, new Callback(){
public void call() {

View File

@ -48,6 +48,18 @@ public class Lightning extends Group {
public Lightning(int from, int to, Callback callback){
this(Arrays.asList(new Arc(from, to)), callback);
}
public Lightning(PointF from, int to, Callback callback){
this(Arrays.asList(new Arc(from, to)), callback);
}
public Lightning(int from, PointF to, Callback callback){
this(Arrays.asList(new Arc(from, to)), callback);
}
public Lightning(PointF from, PointF to, Callback callback){
this(Arrays.asList(new Arc(from, to)), callback);
}
public Lightning( List<Arc> arcs, Callback callback ) {
@ -104,8 +116,21 @@ public class Lightning extends Group {
private PointF start, end;
public Arc(int from, int to){
start = DungeonTilemap.tileCenterToWorld(from);
end = DungeonTilemap.tileCenterToWorld(to);
this( DungeonTilemap.tileCenterToWorld(from),
DungeonTilemap.tileCenterToWorld(to));
}
public Arc(PointF from, int to){
this( from, DungeonTilemap.tileCenterToWorld(to));
}
public Arc(int from, PointF to){
this( DungeonTilemap.tileCenterToWorld(from), to);
}
public Arc(PointF from, PointF to){
start = from;
end = to;
arc1 = new Image(Effects.get(Effects.Type.LIGHTNING));
arc1.x = start.x - arc1.origin.x;
@ -116,7 +141,6 @@ public class Lightning extends Group {
arc2 = new Image(Effects.get(Effects.Type.LIGHTNING));
arc2.origin.set( 0, arc2.height()/2 );
add( arc2 );
}
public void alpha(float alpha) {

View File

@ -20,6 +20,7 @@
*/
package com.shatteredpixel.shatteredpixeldungeon.effects;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.LeafParticle;
@ -30,6 +31,7 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.WoolParticle;
import com.watabou.noosa.Game;
import com.watabou.noosa.Group;
import com.watabou.noosa.Visual;
import com.watabou.noosa.particles.Emitter;
import com.watabou.noosa.particles.PixelParticle;
import com.watabou.utils.Callback;
@ -46,29 +48,102 @@ public class MagicMissile extends Emitter {
private float sx;
private float sy;
private float time;
//missile types
public static final int MAGIC_MISSILE = 0;
public static final int FROST = 1;
public static final int FIRE = 2;
public static final int POISON = 3;
public static final int FOLIAGE = 4;
public static final int FORCE = 5;
public static final int BEACON = 6;
public static final int SHADOW = 7;
public static final int RAINBOW = 8;
public static final int FIRE_CONE = 100;
public static final int FOLIAGE_CONE = 101;
public void reset( int from, int to, Callback callback ) {
reset( from, to, SPEED, callback );
public void reset( int type, int from, int to, Callback callback ) {
reset( type,
DungeonTilemap.tileCenterToWorld( from ),
DungeonTilemap.tileCenterToWorld( to ),
callback );
}
public void reset( int from, int to, float velocity, Callback callback ) {
public void reset( int type, Visual from, Visual to, Callback callback ) {
reset( type,
from.center(),
to.center(),
callback);
}
public void reset( int type, Visual from, int to, Callback callback ) {
reset( type,
from.center(),
DungeonTilemap.tileCenterToWorld( to ),
callback);
}
public void reset( int type, PointF from, PointF to, Callback callback ) {
this.callback = callback;
revive();
PointF pf = DungeonTilemap.tileCenterToWorld( from );
PointF pt = DungeonTilemap.tileCenterToWorld( to );
x = pf.x;
y = pf.y;
x = from.x;
y = from.y;
width = 0;
height = 0;
PointF d = PointF.diff( pt, pf );
PointF speed = new PointF( d ).normalize().scale( velocity );
PointF d = PointF.diff( to, from );
PointF speed = new PointF( d ).normalize().scale( SPEED );
sx = speed.x;
sy = speed.y;
time = d.length() / velocity;
time = d.length() / SPEED;
switch(type){
case MAGIC_MISSILE: default:
size( 4 );
pour( WhiteParticle.FACTORY, 0.01f );
break;
case FROST:
pour( MagicParticle.FACTORY, 0.01f );
break;
case FIRE:
size( 4 );
pour( FlameParticle.FACTORY, 0.01f );
break;
case POISON:
size( 3 );
pour( PoisonParticle.MISSILE, 0.01f );
break;
case FOLIAGE:
size( 4 );
pour( LeafParticle.GENERAL, 0.01f );
break;
case FORCE:
pour( SlowParticle.FACTORY, 0.01f );
break;
case BEACON:
pour( ForceParticle.FACTORY, 0.01f );
break;
case SHADOW:
size( 4 );
pour( ShadowParticle.MISSILE, 0.01f );
break;
case RAINBOW:
size( 4 );
pour( RainbowParticle.BURST, 0.01f );
break;
case FIRE_CONE:
size( 10 );
pour( FlameParticle.FACTORY, 0.03f );
break;
case FOLIAGE_CONE:
size( 10 );
pour( LeafParticle.GENERAL, 0.03f );
break;
}
}
public void size( float size ) {
@ -76,94 +151,15 @@ public class MagicMissile extends Emitter {
y -= size / 2;
width = height = size;
}
public static void blueLight( Group group, int from, int to, Callback callback ) {
MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class ));
missile.reset( from, to, callback );
missile.pour( MagicParticle.FACTORY, 0.01f );
}
public static void fire( Group group, int from, int to, Callback callback ) {
MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class ));
missile.reset( from, to, callback );
missile.size( 10 );
missile.pour( FlameParticle.FACTORY, 0.03f );
}
public static void earth( Group group, int from, int to, Callback callback ) {
MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class ));
missile.reset( from, to, callback );
missile.size( 2 );
missile.pour( EarthParticle.FACTORY, 0.01f );
}
public static void purpleLight( Group group, int from, int to, Callback callback ) {
MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class ));
missile.reset( from, to, callback );
missile.size( 2 );
missile.pour( PurpleParticle.MISSILE, 0.01f );
}
public static void whiteLight( Group group, int from, int to, Callback callback ) {
MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class ));
missile.reset( from, to, callback );
missile.size( 4 );
missile.pour( WhiteParticle.FACTORY, 0.01f );
}
public static void wool( Group group, int from, int to, Callback callback ) {
MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class ));
missile.reset( from, to, callback );
missile.size( 3 );
missile.pour( WoolParticle.FACTORY, 0.01f );
}
public static void poison( Group group, int from, int to, Callback callback ) {
MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class ));
missile.reset( from, to, callback );
missile.size( 3 );
missile.pour( PoisonParticle.MISSILE, 0.01f );
}
public static void foliage( Group group, int from, int to, Callback callback ) {
MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class ));
missile.reset( from, to, callback );
missile.size( 10 );
missile.pour( LeafParticle.GENERAL, 0.03f );
}
public static void slowness( Group group, int from, int to, Callback callback ) {
MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class ));
missile.reset( from, to, callback );
missile.pour( SlowParticle.FACTORY, 0.01f );
}
public static void force( Group group, int from, int to, Callback callback ) {
MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class ));
missile.reset( from, to, callback );
missile.size( 0 );
missile.pour( ForceParticle.FACTORY, 0.01f );
}
public static void coldLight( Group group, int from, int to, Callback callback ) {
MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class ));
missile.reset( from, to, callback );
missile.size( 4 );
missile.pour( ColdParticle.FACTORY, 0.01f );
}
public static void shadow( Group group, int from, int to, Callback callback ) {
MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class ));
missile.reset( from, to, callback );
missile.size( 4 );
missile.pour( ShadowParticle.MISSILE, 0.01f );
}
public static void rainbow( Group group, int from, int to, Callback callback ) {
//convenience method for the common case of a bolt going from a character to a tile or enemy
public static void boltFromChar(Group group, int type, Visual sprite, int to, Callback callback){
MagicMissile missile = ((MagicMissile)group.recycle( MagicMissile.class ));
missile.reset( from, to, callback );
missile.size( 4 );
missile.pour( RainbowParticle.BURST, 0.01f );
if (Actor.findChar(to) != null){
missile.reset(type, sprite, Actor.findChar(to).sprite, callback);
} else {
missile.reset(type, sprite, to, callback);
}
}
@Override

View File

@ -26,6 +26,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.watabou.noosa.Game;
import com.watabou.noosa.Group;
import com.watabou.noosa.Image;
import com.watabou.noosa.Visual;
public class Surprise extends Image {
@ -47,6 +48,14 @@ public class Surprise extends Image {
time = TIME_TO_FADE;
}
public void reset(Visual v) {
revive();
point(v.center(this));
time = TIME_TO_FADE;
}
@Override
public void update() {
super.update();
@ -68,7 +77,7 @@ public class Surprise extends Image {
if (ch.sprite.parent != null) {
Surprise s = (Surprise) ch.sprite.parent.recycle(Surprise.class);
ch.sprite.parent.bringToFront(s);
s.reset(ch.pos);
s.reset(ch.sprite);
s.angle = angle;
}
}
@ -79,9 +88,9 @@ public class Surprise extends Image {
public static void hit(int pos, float angle) {
Group parent = Dungeon.hero.sprite.parent;
Wound w = (Wound) parent.recycle(Wound.class);
parent.bringToFront(w);
w.reset(pos);
w.angle = angle;
Surprise s = (Surprise) parent.recycle(Surprise.class);
parent.bringToFront(s);
s.reset(pos);
s.angle = angle;
}
}

View File

@ -26,6 +26,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.watabou.noosa.Game;
import com.watabou.noosa.Group;
import com.watabou.noosa.Image;
import com.watabou.noosa.Visual;
public class Wound extends Image {
@ -46,6 +47,14 @@ public class Wound extends Image {
time = TIME_TO_FADE;
}
public void reset(Visual v) {
revive();
point(v.center(this));
time = TIME_TO_FADE;
}
@Override
public void update() {
@ -68,7 +77,7 @@ public class Wound extends Image {
if (ch.sprite.parent != null) {
Wound w = (Wound) ch.sprite.parent.recycle(Wound.class);
ch.sprite.parent.bringToFront(w);
w.reset(ch.pos);
w.reset(ch.sprite);
w.angle = angle;
}
}

View File

@ -39,6 +39,7 @@ import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.MissileSprite;
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.audio.Sample;
@ -499,15 +500,32 @@ public class Item implements Bundlable {
}
}
final float finalDelay = delay;
((MissileSprite)user.sprite.parent.recycle( MissileSprite.class )).
reset( user.pos, cell, this, new Callback() {
@Override
public void call() {
Item.this.detach( user.belongings.backpack ).onThrow( cell );
user.spendAndNext( finalDelay );
}
} );
if (enemy != null) {
((MissileSprite) user.sprite.parent.recycle(MissileSprite.class)).
reset(user.sprite,
enemy.sprite,
this,
new Callback() {
@Override
public void call() {
Item.this.detach(user.belongings.backpack).onThrow(cell);
user.spendAndNext(finalDelay);
}
});
} else {
((MissileSprite) user.sprite.parent.recycle(MissileSprite.class)).
reset(user.sprite,
dst,
this,
new Callback() {
@Override
public void call() {
Item.this.detach(user.belongings.backpack).onThrow(cell);
user.spendAndNext(finalDelay);
}
});
}
}
protected static Hero curUser = null;

View File

@ -35,6 +35,7 @@ import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Callback;
@ -132,7 +133,7 @@ public class EtherealChains extends Artifact {
updateQuickslot();
}
curUser.busy();
curUser.sprite.parent.add(new Chains(curUser.pos, affected.pos, new Callback() {
curUser.sprite.parent.add(new Chains(curUser.sprite.center(), affected.sprite.center(), new Callback() {
public void call() {
Actor.add(new Pushing(affected, affected.pos, newMobPos, new Callback() {
public void call() {
@ -169,7 +170,7 @@ public class EtherealChains extends Artifact {
updateQuickslot();
}
curUser.busy();
curUser.sprite.parent.add(new Chains(curUser.pos, target, new Callback() {
curUser.sprite.parent.add(new Chains(curUser.sprite.center(), DungeonTilemap.tileCenterToWorld(target), new Callback() {
public void call() {
Actor.add(new Pushing(curUser, curUser.pos, newHeroPos, new Callback() {
public void call() {

View File

@ -32,7 +32,6 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
@ -205,40 +204,43 @@ public class LloydsBeacon extends Artifact {
curUser.sprite.zap(bolt.collisionPos);
curUser.busy();
MagicMissile.force(curUser.sprite.parent, bolt.sourcePos, bolt.collisionPos, new Callback() {
@Override
public void call() {
if (ch != null) {
MagicMissile.boltFromChar(curUser.sprite.parent,
MagicMissile.BEACON,
curUser.sprite,
bolt.collisionPos,
new Callback() {
@Override
public void call() {
if (ch != null) {
int count = 10;
int pos;
do {
pos = Dungeon.level.randomRespawnCell();
if (count-- <= 0) {
break;
int count = 10;
int pos;
do {
pos = Dungeon.level.randomRespawnCell();
if (count-- <= 0) {
break;
}
} while (pos == -1);
if (pos == -1 || Dungeon.bossLevel()) {
GLog.w( Messages.get(ScrollOfTeleportation.class, "no_tele") );
} else if (ch.properties().contains(Char.Property.IMMOVABLE)) {
GLog.w( Messages.get(LloydsBeacon.class, "tele_fail") );
} else {
ch.pos = pos;
ch.sprite.place(ch.pos);
ch.sprite.visible = Dungeon.visible[pos];
}
}
} while (pos == -1);
if (pos == -1 || Dungeon.bossLevel()) {
GLog.w( Messages.get(ScrollOfTeleportation.class, "no_tele") );
} else if (ch.properties().contains(Char.Property.IMMOVABLE)) {
GLog.w( Messages.get(LloydsBeacon.class, "tele_fail") );
} else {
ch.pos = pos;
ch.sprite.place(ch.pos);
ch.sprite.visible = Dungeon.visible[pos];
curUser.spendAndNext(1f);
}
}
curUser.spendAndNext(1f);
}
});
});
}

View File

@ -300,16 +300,20 @@ public class Potion extends Item {
}
protected void splash( int cell ) {
final int color = ItemSprite.pick( image, 8, 10 );
Splash.at( cell, color, 5 );
Fire fire = (Fire)Dungeon.level.blobs.get( Fire.class );
if (fire != null)
fire.clear( cell );
final int color = ItemSprite.pick( image, 8, 10 );
Char ch = Actor.findChar(cell);
if (ch != null)
Buff.detach( ch, Burning.class );
if (ch != null) {
Buff.detach(ch, Burning.class);
Splash.at( ch.sprite.center(), color, 5 );
} else {
Splash.at( cell, color, 5 );
}
}
@Override

View File

@ -53,7 +53,6 @@ import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TimekeepersHourg
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRecharging;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.CursingTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.LightningTrap;
@ -443,7 +442,11 @@ public class CursedWand {
}
private static void cursedFX(final Hero user, final Ballistica bolt, final Callback callback){
MagicMissile.rainbow(user.sprite.parent, bolt.sourcePos, bolt.collisionPos, callback);
MagicMissile.boltFromChar( user.sprite.parent,
MagicMissile.RAINBOW,
user.sprite,
bolt.collisionPos,
callback);
Sample.INSTANCE.play( Assets.SND_ZAP );
}

View File

@ -234,7 +234,11 @@ public abstract class Wand extends Item {
}
protected void fx( Ballistica bolt, Callback callback ) {
MagicMissile.whiteLight( curUser.sprite.parent, bolt.sourcePos, bolt.collisionPos, callback );
MagicMissile.boltFromChar( curUser.sprite.parent,
MagicMissile.MAGIC_MISSILE,
curUser.sprite,
bolt.collisionPos,
callback);
Sample.INSTANCE.play( Assets.SND_ZAP );
}

View File

@ -159,7 +159,11 @@ public class WandOfBlastWave extends DamageWand {
@Override
protected void fx(Ballistica bolt, Callback callback) {
MagicMissile.slowness(curUser.sprite.parent, bolt.sourcePos, bolt.collisionPos, callback);
MagicMissile.boltFromChar( curUser.sprite.parent,
MagicMissile.FORCE,
curUser.sprite,
bolt.collisionPos,
callback);
Sample.INSTANCE.play(Assets.SND_ZAP);
}

View File

@ -103,7 +103,11 @@ public class WandOfCorruption extends Wand {
@Override
protected void fx(Ballistica bolt, Callback callback) {
MagicMissile.shadow(curUser.sprite.parent, bolt.sourcePos, bolt.collisionPos, callback);
MagicMissile.boltFromChar( curUser.sprite.parent,
MagicMissile.SHADOW,
curUser.sprite,
bolt.collisionPos,
callback);
Sample.INSTANCE.play( Assets.SND_ZAP );
}

View File

@ -159,9 +159,18 @@ public class WandOfFireblast extends DamageWand {
for (int cell : visualCells){
//this way we only get the cells at the tip, much better performance.
MagicMissile.fire(curUser.sprite.parent, bolt.sourcePos, cell, null);
((MagicMissile)curUser.sprite.parent.recycle( MagicMissile.class )).reset(
MagicMissile.FIRE_CONE,
curUser.sprite,
cell,
null
);
}
MagicMissile.fire( curUser.sprite.parent, bolt.sourcePos, bolt.path.get(dist), callback );
MagicMissile.boltFromChar( curUser.sprite.parent,
MagicMissile.FIRE_CONE,
curUser.sprite,
bolt.path.get(dist/2),
callback );
Sample.INSTANCE.play( Assets.SND_ZAP );
}

View File

@ -91,7 +91,11 @@ public class WandOfFrost extends DamageWand {
@Override
protected void fx(Ballistica bolt, Callback callback) {
MagicMissile.blueLight(curUser.sprite.parent, bolt.sourcePos, bolt.collisionPos, callback);
MagicMissile.boltFromChar(curUser.sprite.parent,
MagicMissile.FROST,
curUser.sprite,
bolt.collisionPos,
callback);
Sample.INSTANCE.play(Assets.SND_ZAP);
}

View File

@ -110,7 +110,7 @@ public class WandOfLightning extends DamageWand {
//the hero is only zapped if they are adjacent
continue;
else if (n != null && !affected.contains( n )) {
arcs.add(new Lightning.Arc(ch.pos, n.pos));
arcs.add(new Lightning.Arc(ch.sprite.center(), n.sprite.center()));
arc(n);
}
}
@ -122,19 +122,20 @@ public class WandOfLightning extends DamageWand {
affected.clear();
arcs.clear();
arcs.add( new Lightning.Arc(bolt.sourcePos, bolt.collisionPos));
int cell = bolt.collisionPos;
Char ch = Actor.findChar( cell );
if (ch != null) {
arcs.add( new Lightning.Arc(curUser.sprite.center(), ch.sprite.center()));
arc(ch);
} else {
arcs.add( new Lightning.Arc(curUser.sprite.center(), bolt.collisionPos));
CellEmitter.center( cell ).burst( SparkParticle.FACTORY, 3 );
}
//don't want to wait for the effect before processing damage.
curUser.sprite.parent.add( new Lightning( arcs, null ) );
curUser.sprite.parent.addToFront( new Lightning( arcs, null ) );
callback.call();
}

View File

@ -213,9 +213,18 @@ public class WandOfRegrowth extends Wand {
for (int cell : visualCells){
//this way we only get the cells at the tip, much better performance.
MagicMissile.foliage(curUser.sprite.parent, bolt.sourcePos, cell, null);
((MagicMissile)curUser.sprite.parent.recycle( MagicMissile.class )).reset(
MagicMissile.FOLIAGE_CONE,
curUser.sprite,
cell,
null
);
}
MagicMissile.foliage( curUser.sprite.parent, bolt.sourcePos, bolt.path.get(dist), callback );
MagicMissile.boltFromChar( curUser.sprite.parent,
MagicMissile.FOLIAGE_CONE,
curUser.sprite,
bolt.path.get(dist/2),
callback );
Sample.INSTANCE.play( Assets.SND_ZAP );
}

View File

@ -28,7 +28,6 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.VenomGas;
import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Venomous;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
@ -61,7 +60,12 @@ public class WandOfVenom extends Wand {
@Override
protected void fx(Ballistica bolt, Callback callback) {
MagicMissile.poison(curUser.sprite.parent, bolt.sourcePos, bolt.collisionPos, callback);
MagicMissile.boltFromChar(
curUser.sprite.parent,
MagicMissile.POISON,
curUser.sprite,
bolt.collisionPos,
callback);
Sample.INSTANCE.play(Assets.SND_ZAP);
}

View File

@ -51,10 +51,10 @@ public class Shocking extends Weapon.Enchantment {
affected.add(attacker);
arcs.clear();
arcs.add(new Lightning.Arc(attacker.pos, defender.pos));
arcs.add(new Lightning.Arc(attacker.sprite.center(), defender.sprite.center()));
hit(defender, Random.Int(1, damage / 3));
attacker.sprite.parent.add( new Lightning( arcs, null ) );
attacker.sprite.parent.addToFront( new Lightning( arcs, null ) );
}
@ -82,12 +82,11 @@ public class Shocking extends Weapon.Enchantment {
ch.sprite.centerEmitter().burst(SparkParticle.FACTORY, 3);
ch.sprite.flash();
HashSet<Char> ns = new HashSet<Char>();
for (int i = 0; i < PathFinder.NEIGHBOURS8.length; i++) {
Char n = Actor.findChar( ch.pos + PathFinder.NEIGHBOURS8[i] );
if (n != null && !affected.contains( n )) {
arcs.add(new Lightning.Arc(ch.pos, n.pos));
arcs.add(new Lightning.Arc(ch.sprite.center(), n.sprite.center()));
hit(n, Random.Int(damage / 2, damage));
}
}

View File

@ -29,6 +29,7 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.MagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Callback;
@ -64,31 +65,35 @@ public class GrimTrap extends Trap {
if (target != null){
final Char finalTarget = target;
final GrimTrap trap = this;
MagicMissile.shadow(target.sprite.parent, pos, target.pos, new Callback() {
@Override
public void call() {
if (!finalTarget.isAlive()) return;
if (finalTarget == Dungeon.hero) {
//almost kill the player
if (((float)finalTarget.HP/finalTarget.HT) >= 0.9f){
finalTarget.damage((finalTarget.HP-1), trap);
//kill 'em
} else {
finalTarget.damage(finalTarget.HP, trap);
((MagicMissile)target.sprite.parent.recycle(MagicMissile.class)).reset(
MagicMissile.SHADOW,
DungeonTilemap.tileCenterToWorld(pos),
target.sprite.center(),
new Callback() {
@Override
public void call() {
if (!finalTarget.isAlive()) return;
if (finalTarget == Dungeon.hero) {
//almost kill the player
if (((float)finalTarget.HP/finalTarget.HT) >= 0.9f){
finalTarget.damage((finalTarget.HP-1), trap);
//kill 'em
} else {
finalTarget.damage(finalTarget.HP, trap);
}
Sample.INSTANCE.play(Assets.SND_CURSED);
if (!finalTarget.isAlive()) {
Dungeon.fail( GrimTrap.class );
GLog.n( Messages.get(GrimTrap.class, "ondeath") );
}
} else {
finalTarget.damage(finalTarget.HP, this);
Sample.INSTANCE.play(Assets.SND_BURNING);
}
finalTarget.sprite.emitter().burst(ShadowParticle.UP, 10);
if (!finalTarget.isAlive()) finalTarget.next();
}
Sample.INSTANCE.play(Assets.SND_CURSED);
if (!finalTarget.isAlive()) {
Dungeon.fail( GrimTrap.class );
GLog.n( Messages.get(GrimTrap.class, "ondeath") );
}
} else {
finalTarget.damage(finalTarget.HP, this);
Sample.INSTANCE.play(Assets.SND_BURNING);
}
finalTarget.sprite.emitter().burst(ShadowParticle.UP, 10);
if (!finalTarget.isAlive()) finalTarget.next();
}
});
});
} else {
CellEmitter.get(pos).burst(ShadowParticle.UP, 10);
Sample.INSTANCE.play(Assets.SND_BURNING);

View File

@ -63,14 +63,17 @@ public class BurningFistSprite extends MobSprite {
if (anim == attack) {
Sample.INSTANCE.play( Assets.SND_ZAP );
MagicMissile.shadow( parent, ch.pos, posToShoot,
new Callback() {
@Override
public void call() {
ch.onAttackComplete();
}
} );
MagicMissile.boltFromChar( parent,
MagicMissile.SHADOW,
this,
posToShoot,
new Callback() {
@Override
public void call() {
ch.onAttackComplete();
}
} );
idle();
} else {

View File

@ -139,12 +139,7 @@ public class CharSprite extends MovieClip implements Tweener.Listener, MovieClip
if (args.length > 0) {
text = Messages.format( text, args );
}
if (ch != null) {
PointF tile = DungeonTilemap.tileCenterToWorld(ch.pos);
FloatingText.show( tile.x, tile.y-(width*0.5f), ch.pos, text, color );
} else {
FloatingText.show( x + width * 0.5f, y, text, color );
}
FloatingText.show( x + width * 0.5f, y, text, color );
}
}

View File

@ -22,6 +22,7 @@ package com.shatteredpixel.shatteredpixeldungeon.sprites;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Eye;
@ -104,7 +105,11 @@ public class EyeSprite extends MobSprite {
if (anim == zap) {
if (Dungeon.visible[ch.pos] || Dungeon.visible[zapPos]) {
parent.add( new Beam.DeathRay( center(), DungeonTilemap.tileCenterToWorld( zapPos ) ) );
if (Actor.findChar(zapPos) != null){
parent.add(new Beam.DeathRay(center(), Actor.findChar(zapPos).sprite.center()));
} else {
parent.add(new Beam.DeathRay(center(), DungeonTilemap.tileCenterToWorld(zapPos)));
}
}
((Eye)ch).deathGaze();
ch.next();

View File

@ -22,6 +22,7 @@ package com.shatteredpixel.shatteredpixeldungeon.sprites;
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.watabou.noosa.Visual;
import com.watabou.noosa.tweeners.PosTweener;
import com.watabou.noosa.tweeners.Tweener;
import com.watabou.utils.Callback;
@ -39,24 +40,42 @@ public class MissileSprite extends ItemSprite implements Tweener.Listener {
}
public void reset( int from, int to, Item item, Callback listener ) {
if (item == null) {
reset( from, to, 0, null, listener );
} else {
reset( from, to, item.image(), item.glowing(), listener );
}
reset( DungeonTilemap.tileToWorld( from ),
DungeonTilemap.tileToWorld( to ),
item,
listener);
}
public void reset( int from, int to, int image, Glowing glowing, Callback listener ) {
public void reset( Visual from, Visual to, Item item, Callback listener ) {
reset( from.center(this),
to.center(this),
item,
listener);
}
public void reset( Visual from, int to, Item item, Callback listener ) {
reset( from.center(this),
DungeonTilemap.tileToWorld( to ),
item,
listener);
}
public void reset( PointF from, PointF to, Item item, Callback listener) {
revive();
view( image, glowing );
int image;
if (item == null){
view( image = 0, null);;
} else {
//no particle effects
view( image = item.image(), item.glowing() );
}
this.callback = listener;
point( DungeonTilemap.tileToWorld( from ) );
PointF dest = DungeonTilemap.tileToWorld( to );
PointF d = PointF.diff( dest, point() );
point( from );
PointF d = PointF.diff( to, from );
speed.set( d ).normalize().scale( SPEED );
if (image == ItemSpriteSheet.DART || image == ItemSpriteSheet.INCENDIARY_DART
@ -70,8 +89,8 @@ public class MissileSprite extends ItemSprite implements Tweener.Listener {
angularSpeed = image == 15 || image == 106 ? 1440 : 720;
}
PosTweener tweener = new PosTweener( this, dest, d.length() / SPEED );
PosTweener tweener = new PosTweener( this, to, d.length() / SPEED );
tweener.listener = this;
parent.add( tweener );
}

View File

@ -57,14 +57,17 @@ public class WarlockSprite extends MobSprite {
turnTo( ch.pos , cell );
play( zap );
MagicMissile.shadow( parent, ch.pos, cell,
new Callback() {
@Override
public void call() {
((Warlock)ch).onZapComplete();
}
} );
MagicMissile.boltFromChar( parent,
MagicMissile.SHADOW,
this,
cell,
new Callback() {
@Override
public void call() {
((Warlock)ch).onZapComplete();
}
} );
Sample.INSTANCE.play( Assets.SND_ZAP );
}

View File

@ -179,12 +179,9 @@ public class QuickSlotButton extends Button implements WndBag.Listener {
CharSprite sprite = lastTarget.sprite;
sprite.parent.addToFront( crossM );
crossM.x = sprite.x + ( sprite.width() - crossM.width())/2f;
crossM.y = sprite.y + ( sprite.height() - crossM.height())/2f;
crossB.x = x + (width - crossB.width) / 2;
crossB.y = y + (height - crossB.height) / 2;
crossM.point(sprite.center(crossM));
crossB.point(slot.icon.center(crossB));
crossB.visible = true;
} else {