Initial commit

This commit is contained in:
2025-09-08 04:39:35 +01:00
commit 73b6e2c156
126 changed files with 6867 additions and 0 deletions

12
core/build.gradle Normal file
View File

@@ -0,0 +1,12 @@
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
eclipse.project.name = appName + '-core'
dependencies {
api "com.badlogicgames.gdx:gdx:$gdxVersion"
if(enableGraalNative == 'true') {
implementation "io.github.berstanio:gdx-svmhelper-annotations:$graalHelperVersion"
}
implementation(project(":server"))
}

View File

@@ -0,0 +1,41 @@
package com.ghost.technic;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.utils.viewport.FitViewport;
public class BattlefieldScreen implements Screen {
private final Stage stage;
private final Skin skin;
public BattlefieldScreen(Skin skin) {
this.stage = new Stage(new FitViewport(1280, 720));
this.skin = skin;
// Add the battlefield view
BattlefieldView battlefieldView = new BattlefieldView(skin);
stage.addActor(battlefieldView);
Gdx.input.setInputProcessor(stage);
stage.setDebugAll(true);
}
@Override
public void render(float delta) {
ScreenUtils.clear(0f, 0f, 0f, 1f);
stage.act(delta);
stage.draw();
}
@Override public void resize(int width, int height) { stage.getViewport().update(width, height, true); }
@Override public void show() {}
@Override public void hide() {}
@Override public void pause() {}
@Override public void resume() {}
@Override public void dispose() { stage.dispose(); }
}

View File

@@ -0,0 +1,62 @@
package com.ghost.technic;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
public class BattlefieldView extends Table {
public BattlefieldView(Skin skin) {
super(skin);
setFillParent(true);
// Top rows — opponent side
Table opponentZones = new Table(skin);
// opponentZones.align(Align.left);
opponentZones.add(new Label("Archives", skin)).pad(5);
opponentZones.add(new Label("Discard", skin)).pad(5);
opponentZones.add().expandX(); // spacer
opponentZones.add(new Label("Archon", skin)).pad(5);
opponentZones.add(new Label("Deck", skin)).pad(5).right();
Table opponentArtifacts = new Table(skin);
opponentArtifacts.add(new Label("Opponent Artifacts", skin)).pad(10);
Table opponentCreatures = new Table(skin);
opponentCreatures.add(new Label("Opponent Creatures", skin)).pad(10);
Table yourCreatures = new Table(skin);
yourCreatures.add(new Label("Your Creatures", skin)).pad(10);
Table yourArtifacts = new Table(skin);
yourArtifacts.add(new Label("Your Artifacts", skin)).pad(10);
Table yourZones = new Table(skin);
// yourZones.align(Align.left);
yourZones.add(new Label("Deck", skin)).pad(5);
yourZones.add(new Label("Archon", skin)).pad(5);
yourZones.add().expandX(); // spacer
yourZones.add(new Label("Discard", skin)).pad(5);
yourZones.add(new Label("Archives", skin)).pad(5).right();
// Misc vertical zone (Tide, Prophecy, Tokens, etc.)
Table miscZone = new Table(skin);
miscZone.top().right();
miscZone.add(new Label("Misc Zone", skin)).pad(10).row();
miscZone.add(new Label("[Tide]", skin)).pad(5).row();
miscZone.add(new Label("[Prophecy]", skin)).pad(5).row();
miscZone.add(new Label("[Tokens]", skin)).pad(5);
// Layout main table with a center content + misc column on right
Table mainCenter = new Table(skin);
mainCenter.add(opponentZones).expand().fill().row();
mainCenter.add(opponentArtifacts).expand().fill().row();
mainCenter.add(opponentCreatures).expand().fill().row();
mainCenter.add(yourCreatures).expand().fill().row();
mainCenter.add(yourArtifacts).expand().fill().row();
mainCenter.add(yourZones).expand().fill().row();;
// Add main and misc to the root table
this.add(mainCenter).expand().fill().left();
this.add(miscZone).right().padRight(20f);
}
}

View File

@@ -0,0 +1,83 @@
package com.ghost.technic;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.ghost.technic.server.card.keyword.Keyword;
import com.ghost.technic.server.card.playable.PlayableCard;
import com.ghost.technic.server.card.playable.usable.impl.CreatureCard;
import java.util.stream.Collectors;
public class CardActor extends Table {
private final PlayableCard card;
public CardActor(PlayableCard card, Skin skin) {
this.card = card;
setBackground("default-round");
pad(10);
Label nameLabel = new Label(card.getName(), skin);
add(nameLabel).row();
// Example: add keyword display
if (card instanceof CreatureCard creature) {
for (Keyword k : creature.getKeywords()) {
Label kwLabel = new Label(k.toString(), skin);
add(kwLabel).row();
addTooltip(kwLabel, k.getKeywordAbility().name()); // TODO: add tooltip details
}
}
}
private void addTooltip(Actor actor, String text) {
Tooltip<Label> tooltip = new Tooltip<>(new Label(text, getSkin()));
TooltipManager.getInstance().initialTime = 0.4f;
tooltip.setInstant(true);
tooltip.setAlways(true);
actor.addListener(tooltip);
}
}
//public class CardActor extends Image {
// private final PlayableCard card;
//
// public CardActor(PlayableCard card, Skin skin) {
// super(skin.getDrawable("card-default")); // Replace with card sprite
// this.card = card;
//
// setSize(100, 150); // Default size
// addListener(new InputListener() {
// @Override
// public boolean mouseMoved(InputEvent event, float x, float y) {
// setScale(1.2f);
// setZIndex(Integer.MAX_VALUE); // bring to front
// return true;
// }
//
// @Override
// public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
// setScale(1f);
// }
//
// @Override
// public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
// System.out.println("Clicked: " + card.getName());
// return true;
// }
// });
//
// addListener(new Tooltip<>(new Label(generateTooltipText(card), skin)));
// }
//
// private String generateTooltipText(PlayableCard card) {
// if (card instanceof CreatureCard creature) {
// return creature.getKeywords().stream()
// .map(Keyword::toString)
// .collect(Collectors.joining(", "));
// }
// return "Playable: " + card.getCardType();
// }
//}

View File

@@ -0,0 +1,30 @@
package com.ghost.technic;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.utils.DragListener;
public class CardView extends Image {
private final String cardId;
public CardView(TextureAtlas atlas, String cardId) {
super(atlas.findRegion(cardId));
this.cardId = cardId;
setSize(150, 210); // Resize for display
setTouchable(Touchable.enabled);
addListener(new DragListener() {
@Override
public void drag(InputEvent event, float x, float y, int pointer) {
moveBy(x - getWidth() / 2, y - getHeight() / 2);
}
});
}
public String getCardId() {
return cardId;
}
}

View File

@@ -0,0 +1,32 @@
package com.ghost.technic;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.utils.Align;
import java.util.ArrayList;
import java.util.List;
public class HandView extends Table {
private final List<CardView> cards = new ArrayList<>();
public HandView(Skin skin) {
super(skin);
setBackground("default-round"); // Optional
setFillParent(false);
align(Align.bottomLeft);
pad(10);
}
public void addCard(CardView cardView) {
cards.add(cardView);
add(cardView).pad(5);
row();
}
public boolean isCardNear(Vector2 cardPos) {
Vector2 local = stageToLocalCoordinates(cardPos.cpy());
return hit(local.x, local.y, true) != null;
}
}

View File

@@ -0,0 +1,74 @@
package com.ghost.technic;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.ghost.technic.server.Player;
import com.ghost.technic.server.game.GameActionService;
import com.ghost.technic.server.game.GameState;
import com.ghost.technic.server.game.event.EventBus;
/** {@link com.badlogic.gdx.ApplicationListener} implementation shared by all platforms. */
public class TechnicClient extends ApplicationAdapter {
private Skin skin;
private Screen currentScreen;
private AssetManager assetManager;
private GameState gameState;
private GameActionService gameActionService;
@Override
public void create() {
skin = new Skin(Gdx.files.internal("ui/uiskin.json"));
assetManager = new AssetManager();
assetManager.load("cards/cards.atlas", TextureAtlas.class);
assetManager.finishLoading();
Gdx.app.log("TechnicClient | INFO", "Finished loading assets!");
gameState = new GameState(new EventBus());
gameActionService = new GameActionService(gameState);
Player playerOne = Player.builder().name("Alice").build();
Player playerTwo = Player.builder().name("Bob").build();
gameState.setPlayers(playerOne, playerTwo);
gameState.setup();
currentScreen = new BattlefieldScreen(skin); // store reference
currentScreen.show();
}
@Override
public void render() {
if (currentScreen != null) {
currentScreen.render(Gdx.graphics.getDeltaTime());
}
}
@Override
public void resize(int width, int height) {
if (currentScreen != null) {
currentScreen.resize(width, height);
}
}
@Override
public void dispose() {
if (currentScreen != null) {
currentScreen.dispose();
}
skin.dispose();
}
}