Skip to content

Commit

Permalink
Workaround for disappearing player unit (for now...)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultraq committed Jul 27, 2024
1 parent f626e43 commit 7d3ebff
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 38 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ subprojects {
ext.targetPlatform = targetPlatform

dependencies {
implementation 'nz.net.ultraq.groovy:groovy-extensions:2.3.2'
implementation 'nz.net.ultraq.groovy:groovy-extensions:2.3.3'
implementation 'nz.net.ultraq.groovy:groovy-profiling-extensions:0.10.0'
implementation "org.apache.groovy:groovy:${groovyVersion}"
implementation "org.slf4j:slf4j-api:${slf4jVersion}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ class CoordinateExtensions {
*
* @param self
* @param objectHeightInCells
* Vertical space occupied by the objheheight of the object whose coordinates are being translated.
* Vertical space occupied by the objheheight of the object whose
* coordinates are being translated.
* @return
*/
static Vector2f asWorldCoords(Vector2f self, int objectHeightInCells = 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,7 @@ class Map extends Node<Map> {
static final int TILE_HEIGHT = 24
static final int TILES_X = 128
static final int TILES_Y = 128
static final Rectanglef MAX_BOUNDS = new Rectanglef(
-TILES_X * TILE_WIDTH / 2 as float,
-TILES_Y * TILE_HEIGHT / 2 as float,
TILES_X * TILE_WIDTH / 2 as float,
TILES_Y * TILE_HEIGHT / 2 as float
)
static final Rectanglef MAX_BOUNDS = new Rectanglef(0, 0, TILES_X * TILE_WIDTH, TILES_Y * TILE_HEIGHT).center()

private static final Logger logger = LoggerFactory.getLogger(Map)

Expand Down Expand Up @@ -128,24 +123,21 @@ class Map extends Node<Map> {
addChild(new MapBackground())
addChild(new MapPack())
addChild(new OverlayPack())

// The following should be rendered in top-left to bottom-right order so
// that "lower" objects get drawn over the "higher" ones
addChild(new Terrain())
addChild(new Structures())
addChild(new Units())
addChild(new Infantry())

addChild(new MapLines().tap {
transform { ->
translate(0, 0, 0.4)
translate(0f, 0f, 0.1f)
}
})
}

@Override
CompletableFuture<Void> onSceneAddedAsync(Scene scene) {

// TODO: Need to handle if there are no tiles, ie: an empty map
tileSetSpriteSheetFuture = CompletableFuture.supplyAsync { ->
return tileSet.tileFileList
.collect { tileFile ->
Expand Down Expand Up @@ -188,7 +180,10 @@ class Map extends Node<Map> {
@Override
CompletableFuture<Void> onSceneRemovedAsync(Scene scene) {

return scene.requestDelete(tileSet.spriteSheet)
if (tileSet.numTiles) {
return scene.requestDelete(tileSet.spriteSheet)
}
return CompletableFuture.completedFuture()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ class RenderPipeline implements AutoCloseable {
private final FrustumIntersection frustumIntersection = new FrustumIntersection()
private final List<Node> queryResults = []
private final List<RenderCommand> drawCommands = []
private final Comparator<Node> renderOrderComparator = new Comparator<Node>() {
@Override
int compare(Node node1, Node node2) {
return node1.globalPosition.z() <=> node2.globalPosition.z()
}
}

Scene scene

Expand All @@ -208,13 +214,16 @@ class RenderPipeline implements AutoCloseable {
average('Gathering', 1f, logger) { ->
queryResults.clear()
drawCommands.clear()

drawCommands << scene.camera.renderCommand()
frustumIntersection.set(enlargedViewProjection.scaling(0.9f, 0.9f, 1f).mul(scene.camera.viewProjection), false)
scene.query(frustumIntersection, queryResults).each { element ->
if (element instanceof GraphicsElement) {
drawCommands << element.renderCommand()
scene.query(frustumIntersection, queryResults)
.sort(true, renderOrderComparator) // Furthest-away objects first
.each { node ->
if (node instanceof GraphicsElement) {
drawCommands << node.renderCommand()
}
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ class Node<T extends Node> implements SceneEvents, Scriptable<T> {
* for performance purposes.
* <p>
* The default behaviour is to inherit the partition hint of its parent,
* defaulting to {@link PartitionHint#NONE} if there are no hints in the node's ancestor
* tree.
* defaulting to {@link PartitionHint#NONE} if there are no hints in the
* node's ancestor tree.
*/
PartitionHint getPartitionHint() {

Expand Down Expand Up @@ -392,7 +392,7 @@ class Node<T extends Node> implements SceneEvents, Scriptable<T> {
/**
* Set the local position of this node.
*/
void setPosition(float x, float y, float z = 0) {
void setPosition(float x, float y, float z = position.z()) {

transform.setTranslation(
x * scale.x as float,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,11 @@ class Camera extends Node<Camera> implements GraphicsElement {
Camera(Dimension size) {

viewportDef = [0, 0, size.width(), size.height()]
projection = new Matrix4f().setOrtho2D(
-size.width() / 2, size.width() / 2,
-size.height() / 2, size.height() / 2
)
projection = new Matrix4f().setOrthoSymmetric(size.width(), size.height(), 0f, 10f)
logger.debug('Establishing an orthographic projection of {}x{}', size.width(), size.height())

view = new Matrix4f().setLookAt(
0, 0, 1,
0, 0, 10,
0, 0, 0,
0, 1, 0
)
Expand Down Expand Up @@ -168,7 +165,7 @@ class Camera extends Node<Camera> implements GraphicsElement {
}

@Override
void setPosition(float x, float y, float z = 0) {
void setPosition(float x, float y, float z = position.z()) {

// Positioning the camera is the opposite of what we would expect as we are
// instead creating a transform matrix that moves the world around it
Expand All @@ -179,7 +176,7 @@ class Camera extends Node<Camera> implements GraphicsElement {
void update(float delta) {

if (tracking) {
setPosition(tracking.globalPosition)
setPosition(tracking.globalPosition.x(), tracking.globalPosition.y())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ class MapViewerScript extends Script<Map> {
private CompletableFuture<Void> moveCameraTo(Vector3f position) {

var startPosition = new Vector3f(camera.position)
var nextPosition = new Vector3f()
var nextPosition = new Vector3f(0, 0, camera.position.z())

return new Transition(EasingFunctions::easeOutCubic, 800, { float delta ->
camera.position = startPosition.lerp(position, delta, nextPosition)
Expand All @@ -249,6 +249,7 @@ class MapViewerScript extends Script<Map> {
void onSceneRemoved(Scene scene) {

clearControls()
scene.removeChild(outline)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package nz.net.ultraq.redhorizon.shooter

import nz.net.ultraq.redhorizon.classic.filetypes.IniFile
import nz.net.ultraq.redhorizon.classic.filetypes.MapFile
import nz.net.ultraq.redhorizon.classic.filetypes.PalFile
import nz.net.ultraq.redhorizon.classic.maps.Map
import nz.net.ultraq.redhorizon.classic.nodes.GlobalPalette
Expand Down Expand Up @@ -83,10 +85,18 @@ class Shooter {
globalPalette = new GlobalPalette(loadPalette())
scene << globalPalette

player = new Player(resourceManager)
player = new Player(resourceManager).tap {
transform { ->
translate(0f, 0f, 0.5f)
}
}
scene << player

camera.follow(player)

var mapFile = resourceManager.loadFile('scg01ea.ini', IniFile)
var map = new Map(mapFile as MapFile, resourceManager)
scene << map
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ import nz.net.ultraq.redhorizon.engine.input.CursorPositionEvent
import nz.net.ultraq.redhorizon.engine.input.GamepadControl
import nz.net.ultraq.redhorizon.engine.input.KeyControl
import nz.net.ultraq.redhorizon.engine.resources.ResourceManager
import nz.net.ultraq.redhorizon.engine.scenegraph.GraphicsElement
import nz.net.ultraq.redhorizon.engine.scenegraph.Node
import nz.net.ultraq.redhorizon.engine.scenegraph.PartitionHint
import nz.net.ultraq.redhorizon.engine.scenegraph.Scene
import nz.net.ultraq.redhorizon.engine.scenegraph.Temporal
import nz.net.ultraq.redhorizon.engine.scenegraph.UpdateHint
import nz.net.ultraq.redhorizon.engine.scenegraph.scripting.Script

import org.joml.Math
Expand All @@ -45,21 +48,22 @@ import java.util.concurrent.Executors
*
* @author Emanuel Rabina
*/
class Player extends Node<Player> implements Rotatable, Temporal {
class Player extends Node<Player> implements GraphicsElement, Rotatable, Temporal {

// private static final Logger logger = LoggerFactory.getLogger(Player)
private static final Rectanglef MOVEMENT_RANGE = Map.MAX_BOUNDS
private static final float MOVEMENT_SPEED = 100f
private static final float MOVEMENT_SPEED = 200f
private static final float ROTATION_SPEED = 180f
private static final Vector2f up = new Vector2f(0, 1)

final PartitionHint partitionHint = PartitionHint.NONE
final UpdateHint updateHint = UpdateHint.ALWAYS
private final Unit unit

private final Vector2f screenPosition = new Vector2f()
private Vector2f velocity = new Vector2f()
private Vector2f direction = new Vector2f()
private Vector2f movement = new Vector2f()
private Vector2f movementDiff = new Vector2f()
private Vector2f lookAt = new Vector2f()
private Vector2f lastLookAt = new Vector2f()
private Vector2f relativeLookAt = new Vector2f()
Expand Down Expand Up @@ -118,6 +122,15 @@ class Player extends Node<Player> implements Rotatable, Temporal {
attachScript(new PlayerScript())
}

// TODO: Shouldn't need to implement this, but a Unit type is in the quadtree
// whereas Player is not. What should happen is that we update the unit
// position in the QuadTree.
@Override
RenderCommand renderCommand() {

return unit.renderCommand()
}

@Override
void setHeading(float newHeading) {

Expand All @@ -136,11 +149,10 @@ class Player extends Node<Player> implements Rotatable, Temporal {
}

if (velocity.length()) {
movement.set(velocity).normalize().mul(MOVEMENT_SPEED).mul(delta)
movementDiff.set(position.x() + movement.x as float, position.y() + movement.y as float)
movement.set(velocity).normalize().mul(MOVEMENT_SPEED).mul(delta).add(position.x(), position.y())
setPosition(
Math.clamp(movementDiff.x, MOVEMENT_RANGE.minX, MOVEMENT_RANGE.maxX),
Math.clamp(movementDiff.y, MOVEMENT_RANGE.minY, MOVEMENT_RANGE.maxY)
java.lang.Math.clamp(movement.x, MOVEMENT_RANGE.minX, MOVEMENT_RANGE.maxX),
java.lang.Math.clamp(movement.y, MOVEMENT_RANGE.minY, MOVEMENT_RANGE.maxY)
)
}

Expand All @@ -150,7 +162,7 @@ class Player extends Node<Player> implements Rotatable, Temporal {
heading = Math.toDegrees(relativeLookAt.set(lookAt).sub(screenPosition.x(), screenPosition.y()).angle(up))

// Adjust lookAt position with movement
lookAt.add(movementDiff)
lookAt.add(movement)
lastLookAt.set(lookAt)
}
// Keyboard rotation
Expand Down

0 comments on commit 7d3ebff

Please sign in to comment.