Skip to content

Commit

Permalink
Show carried quballs above the player
Browse files Browse the repository at this point in the history
Closes #31.
  • Loading branch information
Sarah Marshall committed Jun 9, 2020
1 parent c16d678 commit 44675bc
Show file tree
Hide file tree
Showing 21 changed files with 45 additions and 63 deletions.
29 changes: 15 additions & 14 deletions src/superposition/component/MultiverseView.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ final class MultiverseView(multiverse: Multiverse, val camera: Camera) extends C

/** Enqueues a renderer that will be called for each universe.
*
* @param dependentState the value of the quantum state that the renderer depends on
* @param renderable the renderable component for the rendered entity
* @param render the rendering action
*/
def enqueueRenderer(dependentState: QExpr[Any])(render: (Universe, UniverseRenderInfo) => Unit): Unit =
renderers.append(UniversePartRenderer(render, dependentState))
def enqueueRenderer(renderable: Renderable)(render: (Universe, UniverseRenderInfo) => Unit): Unit =
renderers.append(UniversePartRenderer(render, renderable))

/** Renders all of the queued renderers for the universe.
*
Expand All @@ -49,24 +49,25 @@ final class MultiverseView(multiverse: Multiverse, val camera: Camera) extends C
* @param renderInfo the rendering information for the universe
*/
def render(universe: Universe, renderInfo: UniverseRenderInfo): Unit =
for (renderer <- renderers) {
renderer.render(universe, if (isSameInAllUniverses(renderer)) UniverseRenderInfo.default else renderInfo)
for (renderer <- renderers.view sortBy (_.renderable.layer(universe))) {
val dependentState = renderer.renderable.dependentState
renderer.render(universe, if (isSameInAllUniverses(dependentState)) UniverseRenderInfo.default else renderInfo)
}

/** Clears the renderer queue for this frame. */
def clearRenderers(): Unit = renderers.clear()

/** Returns true if the renderer's dependent state is the same in all universes.
/** Returns true if the dependent state is the same in all universes.
*
* @param renderer the universe part renderer
* @return true if the renderer's dependent state is the same in all universes
* @param dependentState the dependent state
* @return true if the dependent state is the same in all universes
*/
private def isSameInAllUniverses(renderer: UniversePartRenderer): Boolean = {
private def isSameInAllUniverses(dependentState: QExpr[Any]): Boolean = {
val iterator = multiverse.universes.iterator
var state = renderer.dependentState(iterator.next())
var state = dependentState(iterator.next())
var allSame = true
while (allSame && iterator.hasNext) {
val nextState = renderer.dependentState(iterator.next())
val nextState = dependentState(iterator.next())
allSame &&= state == nextState
state = nextState
}
Expand All @@ -79,12 +80,12 @@ object MultiverseView {

/** Renders a part of a universe.
*
* @param render the action that renders the part
* @param dependentState the value of the quantum state that the renderer depends on
* @param render the rendering action
* @param renderable the renderable component for the rendered entity
*/
private final case class UniversePartRenderer(
render: (Universe, UniverseRenderInfo) => Unit,
dependentState: QExpr[Any])
renderable: Renderable)

/** The component mapper for the multiverse view component. */
val mapper: ComponentMapper[MultiverseView] = ComponentMapper.getFor(classOf[MultiverseView])
Expand Down
2 changes: 1 addition & 1 deletion src/superposition/component/Renderable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import superposition.math.QExpr.QExpr
* @param layer the layer to render in
* @param dependentState the quantum state that the renderers depend on
*/
final class Renderable(val layer: Int, val dependentState: QExpr[Any]) extends Component
final class Renderable(val layer: QExpr[Int], val dependentState: QExpr[Any]) extends Component

/** Contains the component mapper for the renderable component. */
object Renderable {
Expand Down
4 changes: 3 additions & 1 deletion src/superposition/entity/Cat.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package superposition.entity

import cats.syntax.applicative.catsSyntaxApplicativeId
import cats.syntax.flatMap.toFlatMapOps
import cats.syntax.functor.toFunctorOps
import com.badlogic.ashley.core.Entity
Expand All @@ -12,6 +13,7 @@ import superposition.component.Player.isWalking
import superposition.component._
import superposition.entity.Cat.{deadAnimation, standingAnimation, walkingAnimation}
import superposition.game.ResourceResolver.resolve
import superposition.math.QExpr.QExpr
import superposition.math.Vector2

/** Schrödinger's cat.
Expand Down Expand Up @@ -41,7 +43,7 @@ final class Cat(id: Int, multiverse: Multiverse, initialCell: Vector2[Int]) exte
add(new QuantumPosition(absolutePosition, cell, Vector2(0.5, 0.5)))
add(new PrimaryBit(Seq(alive)))
add(new Renderable(
2,
2.pure[QExpr],
for {
isAlive <- alive.value
currentCell <- cell.value
Expand Down
2 changes: 1 addition & 1 deletion src/superposition/entity/CellHighlighter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ import superposition.math.QExpr.QExpr
* @param layer the layer in which to render the cell highlighting
*/
final class CellHighlighter(layer: Int) extends Entity {
add(new Renderable(layer, ().pure[QExpr]))
add(new Renderable(layer.pure[QExpr], ().pure[QExpr]))
add(CellHighlightView)
}
3 changes: 2 additions & 1 deletion src/superposition/entity/Door.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package superposition.entity

import cats.syntax.applicative.catsSyntaxApplicativeId
import cats.syntax.functor.toFunctorOps
import com.badlogic.ashley.core.Entity
import com.badlogic.gdx.graphics.Texture
Expand All @@ -19,7 +20,7 @@ import superposition.math.Vector2
final class Door(multiverse: Multiverse, cell: Vector2[Int], control: QExpr[Boolean]) extends Entity {
add(new ClassicalPosition((cell map (_.toDouble)) + Vector2(0.5, 0.5)))
add(new Collider(control map (if (_) Set.empty else Set(cell))))
add(new Renderable(1, control))
add(new Renderable(1.pure[QExpr], control))
add(new SpriteView(control map (if (_) openTexture else closedTexture)))
}

Expand Down
2 changes: 1 addition & 1 deletion src/superposition/entity/DoubleDoor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ final class DoubleDoor(multiverse: Multiverse, cell: Vector2[Int], control: QExp

add(new ClassicalPosition((cell map (_.toDouble)) + Vector2(1.0, 0.5)))
add(new Collider(control map (if (_) Set.empty else Set(cell, cell + Vector2(1, 0)))))
add(new Renderable(1, frame))
add(new Renderable(1.pure[QExpr], frame))
add(new SpriteView(frame, scale = Vector2(2.0, 1.0).pure[QExpr]))
add(new Animated(animation, animationTime, lastAnimation, invertTime))
}
Expand Down
2 changes: 1 addition & 1 deletion src/superposition/entity/Laser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ final class Laser(
add(new Collider(cells.pure[QExpr]))
add(new Beam(multiverse, gate, direction, control))
add(new Outline(control map (_.any), cell map (_.toDouble), Vector2(2, 2)))
add(new Renderable(1, frame))
add(new Renderable(1.pure[QExpr], frame))
add(new SpriteView(frame, baseTexture, scale = Vector2(2.0, 2.0).pure[QExpr]))
add(new Animated(animation, animationTime, lastAnimation, keepTime))
}
Expand Down
2 changes: 1 addition & 1 deletion src/superposition/entity/Level.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ final class Level(
extends Entity with Disposable {
add(multiverse)
add(multiverseView)
add(new Renderable(0, ().pure[QExpr]))
add(new Renderable(0.pure[QExpr], ().pure[QExpr]))

override def dispose(): Unit = {
mapShader.dispose()
Expand Down
3 changes: 2 additions & 1 deletion src/superposition/entity/Lock.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package superposition.entity

import cats.syntax.applicative.catsSyntaxApplicativeId
import cats.syntax.functor.toFunctorOps
import com.badlogic.ashley.core.Entity
import com.badlogic.gdx.graphics.Texture
Expand Down Expand Up @@ -34,7 +35,7 @@ final class Lock(id: Int, multiverse: Multiverse, cell: Vector2[Int], code: Seq[
add(new EntityId(id))
add(new ClassicalPosition((cell map (_.toDouble)) + Vector2(0.5, 0.5)))
add(new LockCode(code, isOpen))
add(new Renderable(1, frame))
add(new Renderable(1.pure[QExpr], frame))
add(new SpriteView(frame))
add(new Animated(animation, animationTime, lastAnimation, invertTime))
}
Expand Down
3 changes: 2 additions & 1 deletion src/superposition/entity/MapLayer.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package superposition.entity

import cats.syntax.applicative.catsSyntaxApplicativeId
import com.badlogic.ashley.core.Entity
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer
import superposition.component.{MapLayerView, Multiverse, Renderable}
Expand All @@ -20,6 +21,6 @@ final class MapLayer(
multiverse: Multiverse,
control: QExpr[Boolean])
extends Entity {
add(new Renderable(renderLayer, control))
add(new Renderable(renderLayer.pure[QExpr], control))
add(new MapLayerView(renderer, mapLayer, control))
}
2 changes: 1 addition & 1 deletion src/superposition/entity/Oracle.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ final class Oracle(
add(new ClassicalPosition((cell map (_.toDouble)) + Vector2(.5, .5), Set(cell)))
add(new Collider(Set(cell).pure[QExpr]))
add(new Outline(true.pure[QExpr], cell map (_.toDouble), Vector2(1, 1)))
add(new Renderable(1, ().pure[QExpr]))
add(new Renderable(1.pure[QExpr], ().pure[QExpr]))
add(new SpriteView(texture.pure[QExpr]))
add(new Text(name, (cell map (_.toDouble)) + Vector2(.5, 1)))
}
Expand Down
4 changes: 3 additions & 1 deletion src/superposition/entity/Quball.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ final class Quball(id: Int, multiverse: Multiverse, initialCell: Vector2[Int]) e
add(new PrimaryBit(Seq(onOff)))
add(new Activator(Seq(onOff)))
add(new Carriable(carried))
add(new Renderable(1, Apply[QExpr].map3(onOff.value, carried.value, cell.value)((_, _, _))))
add(new Renderable(
carried.value map (if (_) 3 else 1),
Apply[QExpr].map3(onOff.value, carried.value, cell.value)((_, _, _))))
add(new SpriteView(
texture = texture.pure[QExpr],
scale = carried.value map (if (_) Vector2(0.5, 0.5) else Vector2(0.75, 0.75)),
Expand Down
3 changes: 2 additions & 1 deletion src/superposition/entity/QuballMulti.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package superposition.entity

import cats.syntax.applicative.catsSyntaxApplicativeId
import cats.syntax.flatMap.toFlatMapOps
import cats.syntax.functor.toFunctorOps
import com.badlogic.ashley.core.Entity
Expand Down Expand Up @@ -32,7 +33,7 @@ final class QuballMulti(id: Int, multiverse: Multiverse, initialCell: Vector2[In
add(new Carriable(carried))
add(new FourierBit(fourierBit))
add(new Renderable(
1,
1.pure[QExpr],
for {
bitValue <- QExpr.prepare((_: StateId[Boolean]).value)
carriedValue <- carried.value
Expand Down
2 changes: 1 addition & 1 deletion src/superposition/entity/Rotator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ final class Rotator(
add(new ClassicalPosition((cell map (_.toDouble)) + Vector2(1, 1), cells))
add(new Collider(cells.pure[QExpr]))
add(new Outline(phase map (_ != 0), cell map (_.toDouble), Vector2(2, 2)))
add(new Renderable(1, texture))
add(new Renderable(1.pure[QExpr], texture))
add(new SpriteView(texture, scale = Vector2(2.0, 2.0).pure[QExpr]))
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/superposition/graphics/BeamRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ final class BeamRenderer(level: () => Option[Level]) extends Renderer with Dispo
override def render(entity: Entity, deltaTime: Float): Unit = {
val multiverseView = level().get.multiverseView
shapeRenderer.setProjectionMatrix(multiverseView.camera.combined)
val dependentState = Renderable.mapper.get(entity).dependentState
multiverseView.enqueueRenderer(dependentState)(drawBeam(entity))
multiverseView.enqueueRenderer(Renderable.mapper.get(entity))(drawBeam(entity))
}

/** Draws the laser beam.
Expand Down
6 changes: 2 additions & 4 deletions src/superposition/graphics/CellHighlightRenderer.scala
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package superposition.graphics

import cats.syntax.applicative.catsSyntaxApplicativeId
import com.badlogic.ashley.core.{Entity, Family}
import com.badlogic.gdx.Gdx.gl
import com.badlogic.gdx.graphics.GL20.GL_BLEND
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType
import com.badlogic.gdx.utils.Disposable
import superposition.component.{CellHighlightView, QuantumPosition}
import superposition.component.{CellHighlightView, QuantumPosition, Renderable}
import superposition.entity.Level
import superposition.math.QExpr.QExpr

/** Highlights all cells that are occupied by at least one entity in the multiverse.
*
Expand All @@ -31,7 +29,7 @@ final class CellHighlightRenderer(level: () => Option[Level]) extends Renderer w
} yield position.cell.value(universe)).toSet

val multiverseView = level().get.multiverseView
multiverseView.enqueueRenderer(().pure[QExpr]) { (_, _) =>
multiverseView.enqueueRenderer(Renderable.mapper.get(entity)) { (_, _) =>
gl.glEnable(GL_BLEND)
shapeRenderer.setProjectionMatrix(multiverseView.camera.combined)
shapeRenderer.begin(ShapeType.Filled)
Expand Down
4 changes: 1 addition & 3 deletions src/superposition/graphics/MapLayerRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@ final class MapLayerRenderer(level: () => Option[Level]) extends Renderer {
override val family: Family = Family.all(classOf[MapLayerView]).get

override def render(entity: Entity, deltaTime: Float): Unit = {
val multiverse = level().get.multiverse
val multiverseView = level().get.multiverseView
val mapView = MapLayerView.mapper.get(entity)
val shader = mapView.renderer.getBatch.getShader
val dependentState = Renderable.mapper.get(entity).dependentState
multiverseView.enqueueRenderer(dependentState) { (universe, renderInfo) =>
multiverseView.enqueueRenderer(Renderable.mapper.get(entity)) { (universe, renderInfo) =>
shader.begin()
val drawOn = mapView.control(universe)
val tintColor = renderInfo.color.cpy().mul(1, 1, 1, if (drawOn) 2 else .5f)
Expand Down
5 changes: 1 addition & 4 deletions src/superposition/graphics/OutlineRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ final class OutlineRenderer(level: () => Option[Level]) extends Renderer with Di
val multiverseView = level().get.multiverseView
shapeRenderer.setProjectionMatrix(multiverseView.camera.combined)
val outline = Outline.mapper.get(entity)
val dependentState = Renderable.mapper.get(entity).dependentState
multiverseView.enqueueRenderer(dependentState) { (universe, renderInfo) =>
multiverseView.enqueueRenderer(Renderable.mapper.get(entity)) { (universe, _) =>
if (outline.visible(universe) && multiverseView.isSelected(outline)) {
shapeRenderer.begin(Line)
shapeRenderer.setColor(RED)
Expand All @@ -36,5 +35,3 @@ final class OutlineRenderer(level: () => Option[Level]) extends Renderer with Di

override def dispose(): Unit = shapeRenderer.dispose()
}


3 changes: 1 addition & 2 deletions src/superposition/graphics/SpriteRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ final class SpriteRenderer(level: () => Option[Level]) extends Renderer with Dis

override def render(entity: Entity, deltaTime: Float): Unit = {
val multiverseView = level().get.multiverseView
val dependentState = Renderable.mapper.get(entity).dependentState
batch.setProjectionMatrix(multiverseView.camera.combined)
multiverseView.enqueueRenderer(dependentState) { (universe, renderInfo) =>
multiverseView.enqueueRenderer(Renderable.mapper.get(entity)) { (universe, renderInfo) =>
batch.begin()
draw(entity, universe, renderInfo)
batch.end()
Expand Down
4 changes: 1 addition & 3 deletions src/superposition/graphics/TextRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ final class TextRenderer(level: () => Option[Level]) extends Renderer with Dispo

override def render(entity: Entity, deltaTime: Float): Unit = {
val multiverseView = level().get.multiverseView
val dependentState = Renderable.mapper.get(entity).dependentState

multiverseView.enqueueRenderer(dependentState) { (universe, renderInfo) =>
multiverseView.enqueueRenderer(Renderable.mapper.get(entity)) { (universe, renderInfo) =>
draw(entity, multiverseView.camera.combined, universe, renderInfo)
}
}
Expand Down
20 changes: 2 additions & 18 deletions src/superposition/system/RenderingSystem.scala
Original file line number Diff line number Diff line change
@@ -1,34 +1,18 @@
package superposition.system

import com.badlogic.ashley.core.{Entity, Family}
import com.badlogic.ashley.systems.SortedIteratingSystem
import com.badlogic.ashley.systems.IteratingSystem
import superposition.component.Renderable
import superposition.graphics.Renderer
import superposition.system.RenderingSystem.compareLayers

/** The rendering system uses the renderers to render all renderable entities.
*
* @param renderers the renderers
*/
final class RenderingSystem(renderers: Iterable[Renderer])
extends SortedIteratingSystem(Family.all(classOf[Renderable]).get, compareLayers) {
extends IteratingSystem(Family.all(classOf[Renderable]).get) {
override def processEntity(entity: Entity, deltaTime: Float): Unit =
for (renderer <- renderers if renderer.family.matches(entity)) {
renderer.render(entity, deltaTime)
}
}

/** Functions for the rendering system. */
private object RenderingSystem {
/** Compares the layers of both entities and returns an integer whose sign indicates the result.
*
* @param entity1 the first entity
* @param entity2 the second entity
* @return the comparison result
*/
private def compareLayers(entity1: Entity, entity2: Entity): Int = {
val layer1 = Renderable.mapper.get(entity1).layer
val layer2 = Renderable.mapper.get(entity2).layer
layer1.compare(layer2)
}
}

0 comments on commit 44675bc

Please sign in to comment.