Added rudimentary support for animation overlays

This commit is contained in:
Collin Smith 2020-08-21 01:14:17 -07:00
parent cf410fc64d
commit e42288f8f6
6 changed files with 150 additions and 2 deletions

View File

@ -0,0 +1,62 @@
package com.riiablo.engine.client;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.artemis.ComponentMapper;
import com.artemis.annotations.All;
import com.artemis.systems.IteratingSystem;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.riiablo.Riiablo;
import com.riiablo.codec.Animation;
import com.riiablo.codec.DC;
import com.riiablo.codec.excel.Overlay;
import com.riiablo.graphics.BlendMode;
@All(com.riiablo.engine.client.component.Overlay.class)
public class OverlayManager extends IteratingSystem {
private static final Logger log = LogManager.getLogger(OverlayManager.class);
protected ComponentMapper<com.riiablo.engine.client.component.Overlay> mOverlay;
@Override
protected void process(int entityId) {
com.riiablo.engine.client.component.Overlay overlay = mOverlay.get(entityId);
if (!Riiablo.assets.isLoaded(overlay.assetDescriptor)) return;
Animation animation = overlay.animation;
if (!overlay.isLoaded) {
DC dc = Riiablo.assets.get(overlay.assetDescriptor);
animation.edit()
.layer(dc, overlay.entry.Trans == 3 ? BlendMode.LUMINOSITY : BlendMode.ID)
.build();
animation.setMode(Animation.Mode.ONCE);
// FIXME: set frame to elapsed time since creation
overlay.isLoaded = true;
log.debug("Loaded {}", overlay.assetDescriptor.fileName);
}
if (animation.isFinished()) {
dispose(overlay);
mOverlay.remove(entityId);
}
}
public void set(int entityId, String overlayId) {
if (mOverlay.has(entityId)) {
dispose(mOverlay.get(entityId));
}
Overlay.Entry overlay = Riiablo.files.Overlay.get(overlayId);
com.riiablo.engine.client.component.Overlay overlayC = mOverlay.create(entityId).set(overlay);
Riiablo.assets.load(overlayC.assetDescriptor);
}
void dispose(com.riiablo.engine.client.component.Overlay overlay) {
AssetDescriptor assetDescriptor = overlay.assetDescriptor;
Riiablo.assets.unload(assetDescriptor.fileName);
log.debug("Unloaded {}", assetDescriptor.fileName);
}
}

View File

@ -0,0 +1,22 @@
package com.riiablo.engine.client;
import com.artemis.ComponentMapper;
import com.artemis.annotations.All;
import com.artemis.systems.IntervalIteratingSystem;
import com.riiablo.codec.Animation;
import com.riiablo.engine.client.component.Overlay;
@All(Overlay.class)
public class OverlayStepper extends IntervalIteratingSystem {
protected ComponentMapper<Overlay> mOverlay;
public OverlayStepper() {
super(null, Animation.FRAME_DURATION);
}
@Override
protected void process(int entityId) {
mOverlay.get(entityId).animation.update(Animation.FRAME_DURATION);
}
}

View File

@ -0,0 +1,35 @@
package com.riiablo.engine.client.component;
import com.artemis.PooledComponent;
import com.artemis.annotations.PooledWeaver;
import com.artemis.annotations.Transient;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.riiablo.codec.Animation;
import com.riiablo.codec.DC;
import com.riiablo.codec.DCC;
@Transient
@PooledWeaver
public class Overlay extends PooledComponent {
public final Animation animation = Animation.newAnimation();
public AssetDescriptor<? extends DC> assetDescriptor;
public com.riiablo.codec.excel.Overlay.Entry entry;
public boolean isLoaded;
public Overlay set(com.riiablo.codec.excel.Overlay.Entry overlay) {
this.entry = overlay;
this.assetDescriptor = new AssetDescriptor<>("data\\global\\overlays\\" + overlay.Filename + ".dcc", DCC.class);
this.isLoaded = false;
return this;
}
@Override
protected void reset() {
animation.reset();
assetDescriptor = null;
entry = null;
isLoaded = false;
}
}

View File

@ -7,6 +7,7 @@ import net.mostlyoriginal.api.system.core.PassiveSystem;
import com.riiablo.Riiablo;
import com.riiablo.codec.excel.Skills;
import com.riiablo.engine.client.OverlayManager;
import com.riiablo.engine.server.component.Class;
import com.riiablo.engine.server.component.MovementModes;
import com.riiablo.engine.server.component.Sequence;
@ -15,10 +16,13 @@ import com.riiablo.log.LogManager;
public class Actioneer extends PassiveSystem {
private static final Logger log = LogManager.getLogger(Actioneer.class);
protected OverlayManager overlays;
protected ComponentMapper<Class> mClass;
protected ComponentMapper<Sequence> mSequence;
protected ComponentMapper<MovementModes> mMovementModes;
// TODO: much of this should be split into different systems or events (e.g., onSpellCast)
public void cast(int entityId, int skillId) {
if (mSequence.has(entityId)) return;
final Skills.Entry skill = Riiablo.files.skills.get(skillId);
@ -33,6 +37,12 @@ public class Actioneer extends PassiveSystem {
mSequence.create(entityId).sequence(mode, mMovementModes.get(entityId).NU);
// FIXME: below uses client-side-only code -- may change to event-based model
// does server even need to care about overlays?
Riiablo.audio.play(skill.stsound, true);
if (!skill.castoverlay.isEmpty()) {
overlays.set(entityId, skill.castoverlay);
}
}
}

View File

@ -34,6 +34,7 @@ import com.riiablo.engine.Engine;
import com.riiablo.engine.client.component.AnimationWrapper;
import com.riiablo.engine.client.component.BBoxWrapper;
import com.riiablo.engine.client.component.Hovered;
import com.riiablo.engine.client.component.Overlay;
import com.riiablo.engine.client.component.Selectable;
import com.riiablo.engine.server.component.AIWrapper;
import com.riiablo.engine.server.component.Angle;
@ -103,6 +104,7 @@ public class RenderSystem extends BaseEntitySystem {
};
protected ComponentMapper<AnimationWrapper> mAnimationWrapper;
protected ComponentMapper<Overlay> mOverlay;
protected ComponentMapper<CofReference> mCofReference;
protected ComponentMapper<Position> mPosition;
protected ComponentMapper<Object> mObject;
@ -672,10 +674,22 @@ public class RenderSystem extends BaseEntitySystem {
// CofComponent cofComponent = this.cofComponent.get(entity);
// if (cofComponent != null && cofComponent.load != Dirty.NONE) return;
Animation animation = mAnimationWrapper.get(entity).animation;
// TODO: create EntityRenderer class to encapsulate the following code:
Vector2 pos = mPosition.get(entity).position;
Vector2 tmp = iso.toScreen(tmpVec2.set(pos));
Overlay overlay = mOverlay.get(entity);
if (overlay != null && overlay.entry.PreDraw) {
overlay.animation.draw(batch, tmp.x, tmp.y);
}
Animation animation = mAnimationWrapper.get(entity).animation;
animation.draw(batch, tmp.x, tmp.y);
if (overlay != null && !overlay.entry.PreDraw) {
overlay.animation.draw(batch, tmp.x, tmp.y);
}
}
}

View File

@ -69,6 +69,8 @@ import com.riiablo.engine.client.MissileLoader;
import com.riiablo.engine.client.MonsterLabelManager;
import com.riiablo.engine.client.NetworkIdManager;
import com.riiablo.engine.client.NetworkedClientItemManager;
import com.riiablo.engine.client.OverlayManager;
import com.riiablo.engine.client.OverlayStepper;
import com.riiablo.engine.client.SelectableManager;
import com.riiablo.engine.client.SoundEmitterHandler;
import com.riiablo.engine.client.WarpSubstManager;
@ -568,7 +570,10 @@ public class GameScreen extends ScreenAdapter implements GameLoadingScreen.Loada
;
if (!DEBUG_TOUCHPAD && Gdx.app.getType() == Application.ApplicationType.Desktop) {
builder.with(new CursorMovementSystem());
builder.with(new Actioneer());
/** FIXME: below is tightly coupled with client-side-only code {@link Actioneer#cast} */
builder.with(new Actioneer()); // TODO: move to more appropriate spot in list
builder.with(new OverlayManager()); // TODO: move to more appropriate spot in list
builder.with(new OverlayStepper()); // TODO: move to more appropriate spot in list
}
if (socket == null) {
builder.with(new ItemGenerator());