package com.jenjinstudios.demo.client.ui; import com.jenjinstudios.world.Actor; import com.jenjinstudios.world.Location; import com.jenjinstudios.world.WorldObject; import com.jenjinstudios.world.actor.Vision; import com.jenjinstudios.world.client.WorldClient; import com.jenjinstudios.world.math.SightCalculator; import com.jenjinstudios.world.util.LocationUtils; import javafx.application.Platform; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.image.Image; import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.transform.Rotate; import java.io.InputStream; import java.util.Map; /** * @author Caleb Brinkman */ public class PlayerViewCanvas extends Canvas { private static final double PLAYER_SCALE = 75; private static final double BULLET_SCALE = 15; private static final double SCALE = 75; private final double locScale = (SCALE / Location.SIZE); private final Image playerTile; private final Image bulletTile; private final Actor clientPlayer; private final double yOrig = getHeight() / 2; private final double xOrig = getWidth() / 2; private final WorldClient worldClient; public PlayerViewCanvas(WorldClient client, double width, double height) { super(width, height); this.worldClient = client; this.clientPlayer = client.getPlayer(); Platform.runLater(this::requestFocus); String tankImageFile = "com/jenjinstudios/demo/client/images/tank.png"; InputStream tankStream = getClass().getClassLoader().getResourceAsStream(tankImageFile); playerTile = new Image(tankStream, PLAYER_SCALE * 1.25, PLAYER_SCALE, false, true); String bulletImageFile = "com/jenjinstudios/demo/client/images/bullet.png"; InputStream bulletStream = getClass().getClassLoader().getResourceAsStream(bulletImageFile); bulletTile = new Image(bulletStream, BULLET_SCALE, BULLET_SCALE, false, true); } public void drawWorld() { clearBackground(); drawLocations(); drawObjects(); drawHUD(); } private void drawHUD() { int fontSize = 14; GraphicsContext graphicsContext2D = getGraphicsContext2D(); graphicsContext2D.setFill(Color.WHITE); graphicsContext2D.setFont(Font.font("Arial", fontSize)); String[] hudStrings = { "UPS: " + String.valueOf(worldClient.getAverageUPS()), "Visible Object Count: " + ((Vision) clientPlayer.getPreUpdateEvent(Vision.EVENT_NAME)). getVisibleObjects().size(), clientPlayer.getName(), clientPlayer.getVector2D().toString() }; for (int i = 0; i < hudStrings.length; i++) { graphicsContext2D.fillText(hudStrings[i], 0, 12 + (i * fontSize * 1.5)); } } protected void clearBackground() { GraphicsContext graphicsContext2D = getGraphicsContext2D(); graphicsContext2D.setFill(Color.BLACK); graphicsContext2D.fillRect(0, 0, getWidth(), getHeight()); } protected void drawLocations() { if (LocationUtils.getObjectLocation(clientPlayer) != null) { SightCalculator.getVisibleLocations(clientPlayer).stream().filter(l -> l != null). forEach(this::drawLocation); } } protected void drawLocation(Location location) { Location pLoc = LocationUtils.getObjectLocation(clientPlayer); int xDiff = location.getX() - pLoc.getX(); int yDiff = location.getY() - pLoc.getY();//+ 1; double xBuff = clientPlayer.getVector2D().getXCoordinate() % Location.SIZE; double yBuff = clientPlayer.getVector2D().getYCoordinate() % Location.SIZE; double x = xOrig + (xDiff * SCALE - xBuff * locScale); double y = yOrig - (yDiff * SCALE - yBuff * locScale) - SCALE; GraphicsContext graphicsContext2D = getGraphicsContext2D(); Map<String, String> properties = location.getProperties(); boolean walkable = !"false".equals(properties.get("walkable")); boolean indoors = "true".equals(properties.get("indoors")); if (!walkable) { graphicsContext2D.setFill(Color.GRAY); } else if (indoors) { graphicsContext2D.setFill(Color.BROWN); } else { graphicsContext2D.setFill(Color.GREEN); } graphicsContext2D.fillRect(x, y, SCALE - 2, SCALE - 2); } protected void drawObjects() { Object object = clientPlayer.getPreUpdateEvent(Vision.EVENT_NAME); if (object != null && object instanceof Vision) { Vision vision = (Vision) object; vision.getVisibleObjects().forEach(this::drawObject); drawObject(clientPlayer); } } private void drawObject(WorldObject o) { double xDiff = o.getVector2D().getXCoordinate() - clientPlayer.getVector2D().getXCoordinate(); double yDiff = o.getVector2D().getYCoordinate() - clientPlayer.getVector2D().getYCoordinate(); double x = xOrig + (xDiff * locScale); double y = yOrig - (yDiff * locScale); GraphicsContext graphicsContext2D = getGraphicsContext2D(); graphicsContext2D.save(); Rotate r = new Rotate(-Math.toDegrees(o.getAngle().getAbsoluteAngle()), x, y); graphicsContext2D.setTransform(r.getMxx(), r.getMyx(), r.getMxy(), r.getMyy(), r.getTx(), r.getTy()); Image objectTile = getObjectTile(o); graphicsContext2D.drawImage(objectTile, x - objectTile.getWidth() / 2, y - objectTile.getHeight() / 2); graphicsContext2D.restore(); } private Image getObjectTile(WorldObject object) { Image tile; switch (object.getResourceID()) { case 0: tile = playerTile; break; case 1: tile = bulletTile; break; default: tile = playerTile; break; } return tile; } }