|
@@ -2,268 +2,171 @@
|
|
|
package me.lethunderhawk.screen;
|
|
package me.lethunderhawk.screen;
|
|
|
|
|
|
|
|
import com.badlogic.gdx.Gdx;
|
|
import com.badlogic.gdx.Gdx;
|
|
|
-import com.badlogic.gdx.Input;
|
|
|
|
|
import com.badlogic.gdx.Screen;
|
|
import com.badlogic.gdx.Screen;
|
|
|
-import com.badlogic.gdx.assets.AssetDescriptor;
|
|
|
|
|
-import com.badlogic.gdx.graphics.Color;
|
|
|
|
|
import com.badlogic.gdx.graphics.GL20;
|
|
import com.badlogic.gdx.graphics.GL20;
|
|
|
import com.badlogic.gdx.graphics.OrthographicCamera;
|
|
import com.badlogic.gdx.graphics.OrthographicCamera;
|
|
|
-import com.badlogic.gdx.graphics.Texture;
|
|
|
|
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
|
|
-import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
|
|
|
|
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
|
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
|
|
-import com.badlogic.gdx.maps.tiled.TiledMap;
|
|
|
|
|
-import com.badlogic.gdx.maps.tiled.TiledMapTile;
|
|
|
|
|
-import com.badlogic.gdx.maps.tiled.TiledMapTileSet;
|
|
|
|
|
-import com.badlogic.gdx.maps.tiled.TmxMapLoader;
|
|
|
|
|
-import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
|
|
|
|
|
-import com.badlogic.gdx.maps.tiled.tiles.StaticTiledMapTile;
|
|
|
|
|
import com.badlogic.gdx.utils.viewport.ScreenViewport;
|
|
import com.badlogic.gdx.utils.viewport.ScreenViewport;
|
|
|
import me.lethunderhawk.Main;
|
|
import me.lethunderhawk.Main;
|
|
|
|
|
+import me.lethunderhawk.controller.PlayerInputController;
|
|
|
|
|
+import me.lethunderhawk.render.MapManager;
|
|
|
|
|
+import me.lethunderhawk.render.PlayerRenderer;
|
|
|
|
|
+import me.lethunderhawk.render.WorldRenderer;
|
|
|
import me.lethunderhawk.world.entity.player.Player;
|
|
import me.lethunderhawk.world.entity.player.Player;
|
|
|
-import me.lethunderhawk.event.EventDispatcher;
|
|
|
|
|
-import me.lethunderhawk.event.impl.PlayerMoveEvent;
|
|
|
|
|
import me.lethunderhawk.network.GameClient;
|
|
import me.lethunderhawk.network.GameClient;
|
|
|
import me.lethunderhawk.network.packet.impl.PlayerLogoutPacket;
|
|
import me.lethunderhawk.network.packet.impl.PlayerLogoutPacket;
|
|
|
-import me.lethunderhawk.network.packet.impl.PlayerPositionPacket;
|
|
|
|
|
-import me.lethunderhawk.world.World;
|
|
|
|
|
import me.lethunderhawk.camera.CameraController;
|
|
import me.lethunderhawk.camera.CameraController;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
|
-import java.util.Map;
|
|
|
|
|
-import java.util.UUID;
|
|
|
|
|
|
|
|
|
|
public class GameScreen implements Screen {
|
|
public class GameScreen implements Screen {
|
|
|
|
|
|
|
|
|
|
+ private final Main game;
|
|
|
|
|
+
|
|
|
private final ShapeRenderer shapeRenderer;
|
|
private final ShapeRenderer shapeRenderer;
|
|
|
private final SpriteBatch spriteBatch;
|
|
private final SpriteBatch spriteBatch;
|
|
|
|
|
+
|
|
|
private final GameClient client;
|
|
private final GameClient client;
|
|
|
- private final Main mainGame;
|
|
|
|
|
|
|
+
|
|
|
private OrthographicCamera camera;
|
|
private OrthographicCamera camera;
|
|
|
private ScreenViewport viewport;
|
|
private ScreenViewport viewport;
|
|
|
- private CameraController cameraController;
|
|
|
|
|
- private World world;
|
|
|
|
|
- private TiledMap tiledMap;
|
|
|
|
|
- private OrthogonalTiledMapRenderer tiledMapRenderer;
|
|
|
|
|
- private Texture tilesetTexture;
|
|
|
|
|
- private TiledMapTileSet runtimeTileset; // will hold the runtime tileset you added
|
|
|
|
|
|
|
+
|
|
|
|
|
+ private final CameraController cameraController;
|
|
|
|
|
+ private final PlayerInputController inputController;
|
|
|
|
|
+
|
|
|
|
|
+ private MapManager mapManager;
|
|
|
|
|
+
|
|
|
|
|
+ private WorldRenderer worldRenderer;
|
|
|
|
|
+ private PlayerRenderer playerRenderer;
|
|
|
|
|
|
|
|
public GameScreen(Main game, String ip) {
|
|
public GameScreen(Main game, String ip) {
|
|
|
- this.mainGame = game;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ this.game = game;
|
|
|
|
|
+
|
|
|
this.shapeRenderer = new ShapeRenderer();
|
|
this.shapeRenderer = new ShapeRenderer();
|
|
|
this.spriteBatch = new SpriteBatch();
|
|
this.spriteBatch = new SpriteBatch();
|
|
|
|
|
+
|
|
|
this.client = new GameClient();
|
|
this.client = new GameClient();
|
|
|
|
|
+
|
|
|
this.cameraController = new CameraController();
|
|
this.cameraController = new CameraController();
|
|
|
|
|
+ this.inputController = new PlayerInputController();
|
|
|
|
|
+
|
|
|
|
|
+ connect(ip);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void connect(String ip) {
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
client.connect(ip);
|
|
client.connect(ip);
|
|
|
|
|
+
|
|
|
} catch (IOException e) {
|
|
} catch (IOException e) {
|
|
|
- e.printStackTrace();
|
|
|
|
|
|
|
+
|
|
|
|
|
+ System.out.println("Couldn't connect to ip: " + ip);
|
|
|
|
|
+ System.out.println("Starting Singleplayer instead!");
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void show() {
|
|
public void show() {
|
|
|
- // --- Load tileset texture and split into 16x16 tiles ---
|
|
|
|
|
- Texture tilesetTexture = new Texture(Gdx.files.internal("TX/TX Tileset Grass.png")); // ensure file has extension
|
|
|
|
|
- final int TILE_PX = 16;
|
|
|
|
|
- TextureRegion[][] regions = TextureRegion.split(tilesetTexture, TILE_PX, TILE_PX);
|
|
|
|
|
-
|
|
|
|
|
- // Create a TiledMapTileSet and put each tile in it (IDs start at 1)
|
|
|
|
|
- TiledMapTileSet tileset = new TiledMapTileSet();
|
|
|
|
|
- int id = 1;
|
|
|
|
|
- for (int row = 0; row < regions.length; row++) {
|
|
|
|
|
- for (int col = 0; col < regions[row].length; col++) {
|
|
|
|
|
- TextureRegion region = regions[row][col];
|
|
|
|
|
- if (region == null) continue;
|
|
|
|
|
- StaticTiledMapTile tile = new StaticTiledMapTile(region);
|
|
|
|
|
- tile.setId(id);
|
|
|
|
|
- tileset.putTile(id, tile);
|
|
|
|
|
- id++;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- mainGame.assetManager.finishLoading();
|
|
|
|
|
-
|
|
|
|
|
- // --- Load the Tiled map ---
|
|
|
|
|
- TiledMap map = new TmxMapLoader().load("level/lobby.tmx");
|
|
|
|
|
|
|
|
|
|
- // Add the runtime tileset to the map so its tiles can be referenced by layers/objects if needed
|
|
|
|
|
- tileset.setName("runtime_grass");
|
|
|
|
|
- map.getTileSets().addTileSet(tileset);
|
|
|
|
|
|
|
+ setupCamera();
|
|
|
|
|
|
|
|
- this.tiledMap = map;
|
|
|
|
|
- this.runtimeTileset = map.getTileSets().getTileSet(tileset.getName() /* tileset.getName() may be null */);
|
|
|
|
|
-
|
|
|
|
|
- // fallback: if getTileSet by name fails, use first non-empty tileset:
|
|
|
|
|
- if (this.runtimeTileset == null) {
|
|
|
|
|
- for (TiledMapTileSet ts : map.getTileSets()) {
|
|
|
|
|
- if (ts.size() > 0) { this.runtimeTileset = ts; break; }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ mapManager = new MapManager("level/lobby.tmx");
|
|
|
|
|
|
|
|
- // --- Setup renderer and camera ---
|
|
|
|
|
- final float UNIT_SCALE = 1f / TILE_PX; // map tiles are 16px so 1/16f unit scale
|
|
|
|
|
- OrthogonalTiledMapRenderer renderer = new OrthogonalTiledMapRenderer(map, UNIT_SCALE);
|
|
|
|
|
|
|
+ worldRenderer = new WorldRenderer(
|
|
|
|
|
+ spriteBatch,
|
|
|
|
|
+ client,
|
|
|
|
|
+ mapManager
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
- // Determine map world size (in world units) and center camera on it
|
|
|
|
|
- int mapTilesX = map.getProperties().get("width", Integer.class);
|
|
|
|
|
- int mapTilesY = map.getProperties().get("height", Integer.class);
|
|
|
|
|
- int mapTilePixelWidth = map.getProperties().get("tilewidth", Integer.class);
|
|
|
|
|
- int mapTilePixelHeight = map.getProperties().get("tileheight", Integer.class);
|
|
|
|
|
|
|
+ playerRenderer = new PlayerRenderer(shapeRenderer);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- float worldWidth = mapTilesX * mapTilePixelWidth * UNIT_SCALE;
|
|
|
|
|
- float worldHeight = mapTilesY * mapTilePixelHeight * UNIT_SCALE;
|
|
|
|
|
|
|
+ private void setupCamera() {
|
|
|
|
|
|
|
|
camera = new OrthographicCamera();
|
|
camera = new OrthographicCamera();
|
|
|
- viewport = new ScreenViewport(camera);
|
|
|
|
|
-
|
|
|
|
|
- // Set a reasonable viewport size: keep the screen viewport but ensure camera centers on map
|
|
|
|
|
- camera.setToOrtho(false, viewport.getWorldWidth(), viewport.getWorldHeight());
|
|
|
|
|
- camera.position.set(worldWidth / 2f, worldHeight / 2f, 0f);
|
|
|
|
|
- camera.update();
|
|
|
|
|
|
|
|
|
|
- renderer.setView(camera);
|
|
|
|
|
|
|
+ viewport = new ScreenViewport(camera);
|
|
|
|
|
|
|
|
- // Store renderer / map / tileset as fields if you need to render/dispose later:
|
|
|
|
|
- this.tiledMap = map;
|
|
|
|
|
- this.tiledMapRenderer = renderer;
|
|
|
|
|
- this.tilesetTexture = tilesetTexture; // keep a ref for disposal
|
|
|
|
|
|
|
+ camera.position.set(0, 0, 0);
|
|
|
|
|
|
|
|
|
|
+ camera.update();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void render(float delta) {
|
|
public void render(float delta) {
|
|
|
- update(delta);
|
|
|
|
|
|
|
|
|
|
- Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
|
|
|
|
|
|
+ update(delta);
|
|
|
|
|
|
|
|
- // Render World with SpriteBatch
|
|
|
|
|
- spriteBatch.setProjectionMatrix(camera.combined);
|
|
|
|
|
- spriteBatch.begin();
|
|
|
|
|
- renderWorld();
|
|
|
|
|
- spriteBatch.end();
|
|
|
|
|
|
|
+ clearScreen();
|
|
|
|
|
|
|
|
- // Render Players with ShapeRenderer
|
|
|
|
|
- shapeRenderer.setProjectionMatrix(camera.combined);
|
|
|
|
|
- shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
|
|
|
|
|
|
|
+ mapManager.render(camera);
|
|
|
|
|
|
|
|
- for (Map.Entry<UUID, Player> entry : client.getOtherPlayers().entrySet()) {
|
|
|
|
|
- renderPlayerGrid(entry.getValue());
|
|
|
|
|
- }
|
|
|
|
|
- if (client.getPlayer() != null) {
|
|
|
|
|
- renderPlayerGrid(client.getPlayer());
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ worldRenderer.render(camera);
|
|
|
|
|
|
|
|
- shapeRenderer.end();
|
|
|
|
|
|
|
+ playerRenderer.render(camera, client);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private void renderWorld() {
|
|
|
|
|
- World world = client.getWorld();
|
|
|
|
|
- if (world == null || runtimeTileset == null) return;
|
|
|
|
|
- float scale = world.getBlockScale(); // world units per tile
|
|
|
|
|
-
|
|
|
|
|
- for (int x = 0; x < world.getWidth(); x++) {
|
|
|
|
|
- for (int y = 0; y < world.getHeight(); y++) {
|
|
|
|
|
- int blockId = world.getBlock(x, y);
|
|
|
|
|
- if (blockId == 0) continue;
|
|
|
|
|
-
|
|
|
|
|
- TextureRegion region = getRegionForBlock(blockId);
|
|
|
|
|
- if (region != null) {
|
|
|
|
|
- spriteBatch.draw(region, x * scale, y * scale, scale, scale);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private TextureRegion getRegionForBlock(int blockId) {
|
|
|
|
|
- // If your block IDs match the runtime tile IDs you assigned when creating the tileset:
|
|
|
|
|
- TiledMapTile tile = runtimeTileset.getTile(blockId);
|
|
|
|
|
- if (tile == null) return null;
|
|
|
|
|
|
|
+ private void update(float delta) {
|
|
|
|
|
|
|
|
- // Most runtime tiles are StaticTiledMapTile; get the region:
|
|
|
|
|
- if (tile.getTextureRegion() != null) {
|
|
|
|
|
- return tile.getTextureRegion();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ Player player = client.getPlayer();
|
|
|
|
|
|
|
|
- // fallback for tiled tiles that wrap an atlas region:
|
|
|
|
|
- if (tile instanceof StaticTiledMapTile) {
|
|
|
|
|
- return ((StaticTiledMapTile) tile).getTextureRegion();
|
|
|
|
|
|
|
+ if (player == null) {
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ inputController.update(delta, player, client);
|
|
|
|
|
|
|
|
- private void renderPlayerGrid(Player player) {
|
|
|
|
|
- if (player.avatar == null) return;
|
|
|
|
|
- float cellSize = 2f;
|
|
|
|
|
- for (int x = 0; x < 16; x++) {
|
|
|
|
|
- for (int y = 0; y < 16; y++) {
|
|
|
|
|
- Color color = player.avatar.getColor(x, y);
|
|
|
|
|
- shapeRenderer.setColor(color);
|
|
|
|
|
- shapeRenderer.rect(player.x + x * cellSize, player.y + y * cellSize, cellSize, cellSize);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ cameraController.update(delta, camera, player);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private void update(float delta) {
|
|
|
|
|
- float speed = 300f;
|
|
|
|
|
- boolean moved = false;
|
|
|
|
|
- Player currentPlayer = client.getPlayer();
|
|
|
|
|
-
|
|
|
|
|
- if (Gdx.input.isKeyJustPressed(Input.Keys.ESCAPE)) {
|
|
|
|
|
- mainGame.setScreen(new MenuScreen(mainGame));
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ private void clearScreen() {
|
|
|
|
|
|
|
|
- if (currentPlayer != null) {
|
|
|
|
|
- if (Gdx.input.isKeyPressed(Input.Keys.W)) { currentPlayer.y += speed * delta; moved = true; }
|
|
|
|
|
- if (Gdx.input.isKeyPressed(Input.Keys.S)) { currentPlayer.y -= speed * delta; moved = true; }
|
|
|
|
|
- if (Gdx.input.isKeyPressed(Input.Keys.A)) { currentPlayer.x -= speed * delta; moved = true; }
|
|
|
|
|
- if (Gdx.input.isKeyPressed(Input.Keys.D)) { currentPlayer.x += speed * delta; moved = true; }
|
|
|
|
|
-
|
|
|
|
|
- if (moved) {
|
|
|
|
|
- PlayerPositionPacket packet = new PlayerPositionPacket(currentPlayer.uuid, currentPlayer.x, currentPlayer.y);
|
|
|
|
|
- EventDispatcher.getInstance().fire(new PlayerMoveEvent(currentPlayer, currentPlayer.x, currentPlayer.y));
|
|
|
|
|
- client.send(packet);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ Gdx.gl.glClearColor(0, 0, 0, 1);
|
|
|
|
|
|
|
|
- // Update camera dead-zone follow logic
|
|
|
|
|
- if (currentPlayer != null) {
|
|
|
|
|
- cameraController.update(delta, camera, currentPlayer);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void resize(int width, int height) {
|
|
public void resize(int width, int height) {
|
|
|
- if (viewport != null) {
|
|
|
|
|
- viewport.update(width, height, true);
|
|
|
|
|
- camera.update();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- @Override
|
|
|
|
|
- public void pause() {}
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void resume() {}
|
|
|
|
|
|
|
+ viewport.update(width, height, true);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void hide() {
|
|
public void hide() {
|
|
|
|
|
+
|
|
|
logout();
|
|
logout();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void dispose() {
|
|
public void dispose() {
|
|
|
|
|
+
|
|
|
logout();
|
|
logout();
|
|
|
|
|
+
|
|
|
shapeRenderer.dispose();
|
|
shapeRenderer.dispose();
|
|
|
|
|
+ spriteBatch.dispose();
|
|
|
|
|
+
|
|
|
|
|
+ mapManager.dispose();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void logout() {
|
|
private void logout() {
|
|
|
- if (client.getPlayer() != null) {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ Player player = client.getPlayer();
|
|
|
|
|
+
|
|
|
|
|
+ if (player != null) {
|
|
|
|
|
+
|
|
|
PlayerLogoutPacket packet = new PlayerLogoutPacket();
|
|
PlayerLogoutPacket packet = new PlayerLogoutPacket();
|
|
|
- packet.uuid = client.getPlayer().uuid;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ packet.uuid = player.uuid;
|
|
|
|
|
+
|
|
|
client.send(packet);
|
|
client.send(packet);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
client.disconnect();
|
|
client.disconnect();
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ @Override public void pause() {}
|
|
|
|
|
+ @Override public void resume() {}
|
|
|
}
|
|
}
|