add typing label example

This commit is contained in:
Quillraven
2025-06-10 21:30:52 +02:00
parent 9baae0a410
commit b062f68ae4
7 changed files with 57 additions and 4 deletions

View File

@@ -12,6 +12,9 @@ dependencies {
api "com.github.raeleus.stripe:freetype:$stripeVersion"
// ten patch for better ProgressBar support (scene2d)
api "com.github.raeleus.TenPatch:tenpatch:$tenPatchVersion"
// typing label support
api "com.github.tommyettinger:textratypist:$textraTypistVersion"
api "com.github.tommyettinger:freetypist:$freeTypistVersion"
if(enableGraalNative == 'true') {
implementation "io.github.berstanio:gdx-svmhelper-annotations:$graalHelperVersion"

View File

@@ -10,7 +10,7 @@ import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.utils.Disposable;
import com.ray3k.stripe.FreeTypeSkinLoader;
import com.github.tommyettinger.freetypist.FreeTypistSkinLoader;
public class AssetService implements Disposable {
private final AssetManager assetManager;
@@ -18,7 +18,7 @@ public class AssetService implements Disposable {
public AssetService(FileHandleResolver fileHandleResolver) {
this.assetManager = new AssetManager(fileHandleResolver);
this.assetManager.setLoader(TiledMap.class, new TmxMapLoader());
assetManager.setLoader(Skin.class, new FreeTypeSkinLoader(assetManager.getFileHandleResolver()));
assetManager.setLoader(Skin.class, new FreeTypistSkinLoader(assetManager.getFileHandleResolver()));
}
public TiledMap load(MapAsset mapAsset) {

View File

@@ -75,7 +75,7 @@ public class GameScreen extends ScreenAdapter {
// detect when a damaged animation should be played.
// This is done by checking if an entity has a Damaged component,
// and this component is removed in the DamagedSystem.
this.engine.addSystem(new DamagedSystem());
this.engine.addSystem(new DamagedSystem(viewModel));
this.engine.addSystem(new TriggerSystem(audioService));
this.engine.addSystem(new LifeSystem(this.viewModel));
this.engine.addSystem(new AnimationSystem(game.getAssetService()));

View File

@@ -5,11 +5,15 @@ import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.systems.IteratingSystem;
import io.github.com.quillraven.component.Damaged;
import io.github.com.quillraven.component.Life;
import io.github.com.quillraven.component.Transform;
import io.github.com.quillraven.ui.model.GameViewModel;
public class DamagedSystem extends IteratingSystem {
private final GameViewModel viewModel;
public DamagedSystem() {
public DamagedSystem(GameViewModel viewModel) {
super(Family.all(Damaged.class).get());
this.viewModel = viewModel;
}
@Override
@@ -21,5 +25,14 @@ public class DamagedSystem extends IteratingSystem {
if (life != null) {
life.addLife(-damaged.getDamage());
}
Transform transform = Transform.MAPPER.get(entity);
if (transform != null) {
// we should check that the damage source is the player, but
// in this tutorial game it is in the only possibility so we can skip it
float x = transform.getPosition().x + transform.getSize().x * 0.5f;
float y = transform.getPosition().y;
viewModel.playerDamage((int) damaged.getDamage(), x, y);
}
}
}

View File

@@ -1,22 +1,30 @@
package io.github.com.quillraven.ui.model;
import com.badlogic.gdx.math.Vector2;
import io.github.com.quillraven.GdxGame;
import io.github.com.quillraven.asset.SoundAsset;
import io.github.com.quillraven.audio.AudioService;
import java.util.Map;
public class GameViewModel extends ViewModel {
public static final String LIFE_POINTS = "lifePoints";
public static final String MAX_LIFE = "maxLife";
public static final String PLAYER_DAMAGE = "playerDamage";
private final AudioService audioService;
private int lifePoints;
private int maxLife;
private final Vector2 tmpVec2;
private Map.Entry<Vector2, Integer> playerDamage;
public GameViewModel(GdxGame game) {
super(game);
this.audioService = game.getAudioService();
this.lifePoints = 0;
this.maxLife = 0;
this.tmpVec2 = new Vector2();
this.playerDamage = null;
}
public void setMaxLife(int maxLife) {
@@ -48,4 +56,12 @@ public class GameViewModel extends ViewModel {
setMaxLife((int) maxLife);
setLifePoints((int) life);
}
public void playerDamage(int amount, float x, float y) {
tmpVec2.set(x, y);
game.getViewport().project(tmpVec2);
this.playerDamage = Map.entry(tmpVec2, amount);
this.propertyChangeSupport.firePropertyChange(PLAYER_DAMAGE, null, this.playerDamage);
}
}

View File

@@ -1,13 +1,19 @@
package io.github.com.quillraven.ui.view;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.HorizontalGroup;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.utils.Align;
import com.github.tommyettinger.textra.TextraLabel;
import com.github.tommyettinger.textra.TypingLabel;
import io.github.com.quillraven.ui.model.GameViewModel;
import java.util.Map;
public class GameView extends View<GameViewModel> {
private final HorizontalGroup lifeGroup;
@@ -18,6 +24,7 @@ public class GameView extends View<GameViewModel> {
updateLife(viewModel.getLifePoints());
viewModel.onPropertyChange(GameViewModel.LIFE_POINTS, Integer.class, this::updateLife);
viewModel.onPropertyChange(GameViewModel.PLAYER_DAMAGE, Map.Entry.class, this::showDamage);
}
@Override
@@ -46,4 +53,16 @@ public class GameView extends View<GameViewModel> {
lifePoints -= 4;
}
}
private void showDamage(Map.Entry<Vector2, Integer> damAndPos) {
Vector2 position = damAndPos.getKey();
int damage = damAndPos.getValue();
stage.getViewport().unproject(position);
position.y = stage.getViewport().getWorldHeight() - position.y;
TextraLabel textraLabel = new TypingLabel("[%75]{JUMP=2.0;0.5;0.9}{RAINBOW}" + damage, skin, "small");
textraLabel.setPosition(position.x, position.y);
stage.addActor(textraLabel);
textraLabel.addAction(Actions.sequence(Actions.delay(1.25f), Actions.removeActor()));
}
}