Added starter components.
This commit is contained in:
parent
4873a308ee
commit
300a62e621
|
@ -0,0 +1,3 @@
|
|||
.idea/
|
||||
target/
|
||||
*.iml
|
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="256"
|
||||
height="256"
|
||||
viewBox="0 0 67.733332 67.733335"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
|
||||
sodipodi:docname="icon.svg"
|
||||
inkscape:export-filename="A:\Programming\GitHub-andrewlalis\StarshipArena\design\icon.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:document-units="px"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-page="true"
|
||||
inkscape:zoom="2"
|
||||
inkscape:cx="61.5"
|
||||
inkscape:cy="141.75"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1">
|
||||
<sodipodi:guide
|
||||
position="33.866667,54.715007"
|
||||
orientation="1,0"
|
||||
id="guide824" />
|
||||
<sodipodi:guide
|
||||
position="2.5765869,33.866667"
|
||||
orientation="0,-1"
|
||||
id="guide826" />
|
||||
<sodipodi:guide
|
||||
position="2.778125,2.5016983e-07"
|
||||
orientation="0,-1"
|
||||
id="guide828" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2822">
|
||||
<stop
|
||||
style="stop-color:#00023d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2818" />
|
||||
<stop
|
||||
style="stop-color:#8158ac;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop2820" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2822"
|
||||
id="linearGradient3304"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="33.866665"
|
||||
y1="44.908512"
|
||||
x2="33.866665"
|
||||
y2="0.92604166"
|
||||
gradientTransform="matrix(1.0004146,0,0,0.92621082,-0.01400114,2.308488)" />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:#ce0900;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 37.120775,63.000637 C 37.208969,42.098554 21.012326,39.151829 11.972396,42.569364 l 3.373437,2.645833 c 9.37066,-5.335764 20.407928,7.113912 21.774942,17.78544 z"
|
||||
id="path4745"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="fill:#05e898;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 30.775166,63.000637 C 30.686972,42.098554 46.883615,39.151829 55.923545,42.569364 l -3.373437,2.645833 c -9.37066,-5.335764 -20.407928,7.113912 -21.774942,17.78544 z"
|
||||
id="path8544"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="fill:url(#linearGradient3304);fill-opacity:1;stroke:#ffb800;stroke-width:1.01874;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 12.530819,65.043834 33.866706,3.1661977 55.008802,65.043833 33.866706,40.170249 Z"
|
||||
id="path863"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#ce0900;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 11.972396,42.569364 C -2.2722264,48.32423 20.397365,66.043094 41.63193,42.657014 62.866491,19.270926 45.943565,5.5747177 45.943565,5.5747177 51.46268,17.143022 53.619707,20.974556 38.278435,40.494141 25.055936,55.054458 6.5096703,50.64227 15.345833,45.215197 Z"
|
||||
id="path6747"
|
||||
sodipodi:nodetypes="cscccc" />
|
||||
<path
|
||||
style="fill:#05e898;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 55.923545,42.569364 C 70.168167,48.32423 47.498576,66.043094 26.264011,42.657014 5.0294498,19.270926 21.952376,5.5747177 21.952376,5.5747177 16.433261,17.143022 14.276234,20.974556 29.617506,40.494141 42.840005,55.054458 61.38627,50.64227 52.550108,45.215197 Z"
|
||||
id="path13334"
|
||||
sodipodi:nodetypes="cscccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.5 KiB |
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>nl.andrewl</groupId>
|
||||
<artifactId>starship-arena</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.9.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>nl.andrewl.starship_arena.StarshipArena</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id> <!-- this is used for inheritance merges -->
|
||||
<phase>package</phase> <!-- bind to the packaging phase -->
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,21 @@
|
|||
package nl.andrewl.starship_arena;
|
||||
|
||||
import nl.andrewl.starship_arena.model.Arena;
|
||||
import nl.andrewl.starship_arena.model.Ship;
|
||||
import nl.andrewl.starship_arena.model.ShipModel;
|
||||
import nl.andrewl.starship_arena.util.ResourceUtils;
|
||||
import nl.andrewl.starship_arena.view.ArenaWindow;
|
||||
|
||||
/**
|
||||
* The main executable class which starts the program.
|
||||
*/
|
||||
public class StarshipArena {
|
||||
public static void main(String[] args) {
|
||||
ShipModel corvette = ShipModel.load(ResourceUtils.getString("/ships/corvette.json"));
|
||||
Ship s = new Ship(corvette);
|
||||
Arena arena = new Arena();
|
||||
arena.getShips().add(s);
|
||||
var window = new ArenaWindow(arena);
|
||||
window.setVisible(true);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package nl.andrewl.starship_arena.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Represents the top-level model containing all objects in an arena that can
|
||||
* interact with each other.
|
||||
*/
|
||||
public class Arena {
|
||||
private final Collection<Ship> ships = new ArrayList<>();
|
||||
private final Camera camera = new Camera();
|
||||
|
||||
public Collection<Ship> getShips() {
|
||||
return ships;
|
||||
}
|
||||
|
||||
public Camera getCamera() {
|
||||
return camera;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package nl.andrewl.starship_arena.model;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
public class Camera {
|
||||
public static final double SCALE_INTERVAL = 50.0;
|
||||
|
||||
private Object focus;
|
||||
|
||||
private Point2D.Float position = new Point2D.Float();
|
||||
|
||||
private int scaleIncrement = 1;
|
||||
|
||||
public Object getFocus() {
|
||||
return focus;
|
||||
}
|
||||
|
||||
public void setFocus(Object focus) {
|
||||
this.focus = focus;
|
||||
}
|
||||
|
||||
public Point2D.Float getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(Point2D.Float position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public int getScaleIncrement() {
|
||||
return scaleIncrement;
|
||||
}
|
||||
|
||||
public void setScaleIncrement(int scaleIncrement) {
|
||||
this.scaleIncrement = scaleIncrement;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package nl.andrewl.starship_arena.model;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
public class PhysicsObject {
|
||||
/**
|
||||
* The position of this object in the scene, in meters from the origin.
|
||||
* Positive x-axis goes to the right, and positive y-axis goes down.
|
||||
*/
|
||||
private final Point2D.Float position = new Point2D.Float();
|
||||
|
||||
/**
|
||||
* The object's rotation in radians, from 0 to 2 PI.
|
||||
*/
|
||||
private float rotation;
|
||||
|
||||
/**
|
||||
* The object's velocity, in meters per second.
|
||||
*/
|
||||
private final Point2D.Float velocity = new Point2D.Float();
|
||||
|
||||
/**
|
||||
* The object's rotational speed, in radians per second.
|
||||
*/
|
||||
private float rotationSpeed;
|
||||
|
||||
public Point2D.Float getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public float getRotation() {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
public void setRotation(float rotation) {
|
||||
while (rotation < 0) rotation += 2 * Math.PI;
|
||||
while (rotation > 2 * Math.PI) rotation -= 2 * Math.PI;
|
||||
this.rotation = rotation;
|
||||
}
|
||||
|
||||
public Point2D.Float getVelocity() {
|
||||
return velocity;
|
||||
}
|
||||
|
||||
public float getRotationSpeed() {
|
||||
return rotationSpeed;
|
||||
}
|
||||
|
||||
public void setRotationSpeed(float rotationSpeed) {
|
||||
this.rotationSpeed = rotationSpeed;
|
||||
}
|
||||
|
||||
public void update(double delta) {
|
||||
position.x += velocity.x * delta;
|
||||
position.y += velocity.y * delta;
|
||||
setRotation((float) (rotation + rotationSpeed * delta));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package nl.andrewl.starship_arena.model;
|
||||
|
||||
import nl.andrewl.starship_arena.model.ship.Gun;
|
||||
import nl.andrewl.starship_arena.model.ship.Panel;
|
||||
import nl.andrewl.starship_arena.model.ship.ShipComponent;
|
||||
import nl.andrewl.starship_arena.util.ResourceUtils;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public class Ship extends PhysicsObject {
|
||||
private final String modelName;
|
||||
private final Collection<ShipComponent> components;
|
||||
|
||||
private final Collection<Panel> panels;
|
||||
private final Collection<Gun> guns;
|
||||
|
||||
private Color primaryColor = Color.GRAY;
|
||||
|
||||
public Ship(ShipModel model) {
|
||||
this.modelName = model.getName();
|
||||
this.components = model.getComponents();
|
||||
this.panels = new ArrayList<>();
|
||||
this.guns = new ArrayList<>();
|
||||
for (var c : components) {
|
||||
c.setShip(this);
|
||||
if (c instanceof Panel p) panels.add(p);
|
||||
if (c instanceof Gun g) guns.add(g);
|
||||
}
|
||||
}
|
||||
|
||||
public Ship(String modelResource) {
|
||||
this(ShipModel.load(ResourceUtils.getString(modelResource)));
|
||||
}
|
||||
|
||||
public String getModelName() {
|
||||
return modelName;
|
||||
}
|
||||
|
||||
public Collection<ShipComponent> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
public Color getPrimaryColor() {
|
||||
return primaryColor;
|
||||
}
|
||||
|
||||
public float getMass() {
|
||||
float m = 0;
|
||||
for (var c : components) {
|
||||
m += c.getMass();
|
||||
}
|
||||
return m;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package nl.andrewl.starship_arena.model;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import nl.andrewl.starship_arena.model.ship.ComponentDeserializer;
|
||||
import nl.andrewl.starship_arena.model.ship.GeometricComponent;
|
||||
import nl.andrewl.starship_arena.model.ship.Gun;
|
||||
import nl.andrewl.starship_arena.model.ship.ShipComponent;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class ShipModel {
|
||||
private String name;
|
||||
private Collection<ShipComponent> components;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Collection<ShipComponent> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the geometric properties of the components such that the ship
|
||||
* model's components are centered around (0, 0).
|
||||
* TODO: Consider scaling?
|
||||
*/
|
||||
private void normalizeComponents() {
|
||||
float minX = Float.MAX_VALUE;
|
||||
float maxX = Float.MIN_VALUE;
|
||||
float minY = Float.MAX_VALUE;
|
||||
float maxY = Float.MIN_VALUE;
|
||||
for (var c : components) {
|
||||
if (c instanceof GeometricComponent g) {
|
||||
for (var p : g.getPoints()) {
|
||||
minX = Math.min(minX, p.x);
|
||||
maxX = Math.max(maxX, p.x);
|
||||
minY = Math.min(minY, p.y);
|
||||
maxY = Math.max(maxY, p.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
final float width = maxX - minX;
|
||||
final float height = maxY - minY;
|
||||
final float offsetX = -minX - width / 2;
|
||||
final float offsetY = -minY - height / 2;
|
||||
// Shift all components to the top-left.
|
||||
for (var c : components) {
|
||||
if (c instanceof GeometricComponent g) {
|
||||
for (var p : g.getPoints()) {
|
||||
p.x += offsetX;
|
||||
p.y += offsetY;
|
||||
}
|
||||
} else if (c instanceof Gun g) {
|
||||
g.getLocation().x += offsetX;
|
||||
g.getLocation().y += offsetY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ShipModel load(String json) {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(ShipComponent.class, new ComponentDeserializer())
|
||||
.create();
|
||||
ShipModel model = gson.fromJson(json, ShipModel.class);
|
||||
model.normalizeComponents();
|
||||
return model;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package nl.andrewl.starship_arena.model.ship;
|
||||
|
||||
/**
|
||||
* A cockpit represents the control point of the ship.
|
||||
*/
|
||||
public class Cockpit extends GeometricComponent {
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package nl.andrewl.starship_arena.model.ship;
|
||||
|
||||
import com.google.gson.*;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Custom deserializer that's used to deserialize components based on their
|
||||
* "type" property.
|
||||
*/
|
||||
public class ComponentDeserializer implements JsonDeserializer<ShipComponent> {
|
||||
@Override
|
||||
public ShipComponent deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext ctx) throws JsonParseException {
|
||||
JsonObject obj = jsonElement.getAsJsonObject();
|
||||
String componentTypeName = obj.get("type").getAsString();
|
||||
Type componentType = switch (componentTypeName) {
|
||||
case "panel" -> Panel.class;
|
||||
case "cockpit" -> Cockpit.class;
|
||||
case "gun" -> Gun.class;
|
||||
default -> throw new JsonParseException("Invalid ship component type: " + componentTypeName);
|
||||
};
|
||||
return ctx.deserialize(obj, componentType);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package nl.andrewl.starship_arena.model.ship;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a component of a ship that can be drawn as a geometric primitive.
|
||||
*/
|
||||
public abstract class GeometricComponent extends ShipComponent {
|
||||
private List<Point2D.Float> points;
|
||||
|
||||
public List<Point2D.Float> getPoints() {
|
||||
return points;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package nl.andrewl.starship_arena.model.ship;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
public class Gun extends ShipComponent {
|
||||
private String name;
|
||||
private Point2D.Float location;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Point2D.Float getLocation() {
|
||||
return location;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package nl.andrewl.starship_arena.model.ship;
|
||||
|
||||
/**
|
||||
* A simple structural panel that makes up all or part of a ship's body.
|
||||
*/
|
||||
public class Panel extends GeometricComponent {
|
||||
private String name;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package nl.andrewl.starship_arena.model.ship;
|
||||
|
||||
import nl.andrewl.starship_arena.model.Ship;
|
||||
|
||||
/**
|
||||
* Represents the top-level component information for any part of a ship.
|
||||
*/
|
||||
public class ShipComponent {
|
||||
/**
|
||||
* The ship that this component belongs to.
|
||||
*/
|
||||
private transient Ship ship;
|
||||
|
||||
private float mass;
|
||||
|
||||
public Ship getShip() {
|
||||
return ship;
|
||||
}
|
||||
|
||||
public void setShip(Ship ship) {
|
||||
this.ship = ship;
|
||||
}
|
||||
|
||||
public float getMass() {
|
||||
return mass;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package nl.andrewl.starship_arena.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
|
||||
public class ResourceUtils {
|
||||
public static InputStream get(String name) {
|
||||
InputStream in = ResourceUtils.class.getResourceAsStream(name);
|
||||
if (in == null) throw new UncheckedIOException(new IOException("Could not load resource: " + name));
|
||||
return in;
|
||||
}
|
||||
|
||||
public static String getString(String name) {
|
||||
try (var in = get(name)) {
|
||||
return new String(in.readAllBytes());
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package nl.andrewl.starship_arena.view;
|
||||
|
||||
import nl.andrewl.starship_arena.model.Arena;
|
||||
import nl.andrewl.starship_arena.model.Camera;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
||||
public class ArenaPanel extends JPanel {
|
||||
private final Arena arena;
|
||||
|
||||
private final ShipRenderer shipRenderer = new ShipRenderer();
|
||||
|
||||
public ArenaPanel(Arena arena) {
|
||||
this.arena = arena;
|
||||
this.addMouseWheelListener(e -> {
|
||||
arena.getCamera().setScaleIncrement(arena.getCamera().getScaleIncrement() + e.getWheelRotation());
|
||||
repaint();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
g2.setColor(Color.BLACK);
|
||||
g2.fillRect(0, 0, getWidth(), getHeight());
|
||||
|
||||
AffineTransform originalTx = g2.getTransform();
|
||||
AffineTransform tx = new AffineTransform();
|
||||
|
||||
Camera cam = arena.getCamera();
|
||||
|
||||
double translateX = (double) getWidth() / 2;
|
||||
double translateY = (double) getHeight() / 2;
|
||||
if (cam.getFocus() == null) {
|
||||
translateX += cam.getPosition().x;
|
||||
translateY += cam.getPosition().y;
|
||||
}
|
||||
|
||||
double scale = 1 * Camera.SCALE_INTERVAL;
|
||||
if (cam.getScaleIncrement() > 0) {
|
||||
scale = cam.getScaleIncrement() * Camera.SCALE_INTERVAL;
|
||||
} else if (cam.getScaleIncrement() < 0) {
|
||||
scale = 1.0 / Math.abs(cam.getScaleIncrement() * Camera.SCALE_INTERVAL);
|
||||
}
|
||||
|
||||
tx.translate(translateX, translateY);
|
||||
tx.scale(scale, scale);
|
||||
g2.setTransform(tx);
|
||||
|
||||
for (var s : arena.getShips()) {
|
||||
shipRenderer.render(s, g2);
|
||||
}
|
||||
|
||||
g2.setTransform(originalTx);
|
||||
|
||||
g2.setColor(Color.GREEN);
|
||||
g2.fillRect(0, 0, 20, 20);
|
||||
g2.setColor(Color.BLUE);
|
||||
g2.fillRect(getWidth() - 20, getHeight() - 20, 20, 20);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package nl.andrewl.starship_arena.view;
|
||||
|
||||
import nl.andrewl.starship_arena.model.Arena;
|
||||
import nl.andrewl.starship_arena.util.ResourceUtils;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class ArenaWindow extends JFrame {
|
||||
private final ArenaPanel arenaPanel;
|
||||
|
||||
public ArenaWindow(Arena arena) {
|
||||
super("Starship Arena");
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
setUndecorated(true);
|
||||
try {
|
||||
GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
|
||||
device.setFullScreenWindow(this);
|
||||
setPreferredSize(new Dimension(device.getDisplayMode().getWidth(), device.getDisplayMode().getHeight()));
|
||||
} catch (HeadlessException e) {
|
||||
System.err.println("Cannot start the program on systems without a screen.");
|
||||
System.exit(1);
|
||||
}
|
||||
try {
|
||||
InputStream in = ResourceUtils.get("/img/icon.png");
|
||||
setIconImage(ImageIO.read(in));
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
arenaPanel = new ArenaPanel(arena);
|
||||
add(arenaPanel);
|
||||
pack();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package nl.andrewl.starship_arena.view;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public interface Renderer<T> {
|
||||
void render(T obj, Graphics2D g);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package nl.andrewl.starship_arena.view;
|
||||
|
||||
import nl.andrewl.starship_arena.model.Ship;
|
||||
import nl.andrewl.starship_arena.model.ship.Cockpit;
|
||||
import nl.andrewl.starship_arena.model.ship.GeometricComponent;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Path2D;
|
||||
|
||||
public class ShipRenderer implements Renderer<Ship> {
|
||||
@Override
|
||||
public void render(Ship ship, Graphics2D g) {
|
||||
for (var c : ship.getComponents()) {
|
||||
if (c instanceof GeometricComponent geo) {
|
||||
Path2D.Float path = new Path2D.Float();
|
||||
var first = geo.getPoints().get(0);
|
||||
path.moveTo(first.x, first.y);
|
||||
for (int i = 0; i < geo.getPoints().size(); i++) {
|
||||
var point = geo.getPoints().get(i);
|
||||
path.lineTo(point.x, point.y);
|
||||
}
|
||||
if (geo instanceof Cockpit) {
|
||||
g.setColor(new Color(0f, 0f, 0.5f, 0.5f));
|
||||
} else {
|
||||
g.setColor(ship.getPrimaryColor());
|
||||
}
|
||||
g.fill(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
"name": "Corvette",
|
||||
"components": [
|
||||
{
|
||||
"type": "panel",
|
||||
"name": "Main Fuselage",
|
||||
"mass": 5000,
|
||||
"points": [
|
||||
{"x": 0.3, "y": 0.6},
|
||||
{"x": 0.2, "y": 0.1},
|
||||
{"x": 0.1, "y": 0.5},
|
||||
{"x": 0.2, "y": 0.8},
|
||||
{"x": 0.8, "y": 0.8},
|
||||
{"x": 0.9, "y": 0.5},
|
||||
{"x": 0.8, "y": 0.1},
|
||||
{"x": 0.7, "y": 0.6}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
"name": "Front Cargo Bay",
|
||||
"mass": 1000,
|
||||
"points": [
|
||||
{"x": 0.4, "y": 0.2},
|
||||
{"x": 0.35, "y": 0.6},
|
||||
{"x": 0.65, "y": 0.6},
|
||||
{"x": 0.6, "y": 0.2}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "cockpit",
|
||||
"mass": 800,
|
||||
"points": [
|
||||
{"x": 0.5, "y": 0.0},
|
||||
{"x": 0.4, "y": 0.2},
|
||||
{"x": 0.6, "y": 0.2}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "gun",
|
||||
"name": "Port-Side Machine Gun",
|
||||
"mass": 500,
|
||||
"location": {"x": 0.15, "y": 0.4}
|
||||
},
|
||||
{
|
||||
"type": "gun",
|
||||
"name": "Starboard-Side Machine Gun",
|
||||
"mass": 500,
|
||||
"location": {"x": 0.85, "y": 0.4}
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue