diff --git a/core/src/main/scala/com/pluto/box/BreakoutGame.scala b/core/src/main/scala/com/pluto/box/BreakoutGame.scala new file mode 100644 index 0000000..d9c0ff6 --- /dev/null +++ b/core/src/main/scala/com/pluto/box/BreakoutGame.scala @@ -0,0 +1,88 @@ +package com.pluto.box + +import com.badlogic.ashley.core.Entity +import com.badlogic.gdx.graphics.glutils.ShapeRenderer +import com.badlogic.gdx.graphics.{Color, GL20} +import com.badlogic.gdx.{Game, Gdx} +import com.pluto.box.component.{CircleComponent, MouseXTrackingComponent, PositionComponent, RectangleComponent, RenderableComponent, VelocityComponent} +import com.pluto.box.system.{MouseXTrackingMovementSystem, MovementSystem, RenderingSystem} + +class BreakoutGame extends Game { + + lazy val ashleyEngine = new com.badlogic.ashley.core.Engine() + + lazy val shapeRenderer: ShapeRenderer = new ShapeRenderer + + lazy val colors: Seq[Color] = Seq[Color](Color.YELLOW, Color.GREEN, Color.BLUE, Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE) + + lazy val ball: Entity = { + val positionComponent = new PositionComponent + positionComponent.x = Gdx.graphics.getWidth / 2 + positionComponent.y = Gdx.graphics.getHeight / 2 + val circleComponent = new CircleComponent + circleComponent.radius = 20 + val velocityComponent = new VelocityComponent + velocityComponent.x = 3 + velocityComponent.y = 3 + new Entity() + .add(positionComponent) + .add(circleComponent) + .add(velocityComponent) + .add(new RenderableComponent) + } + + lazy val paddle: Entity = { + val positionComponent = new PositionComponent + positionComponent.x = 0 + positionComponent.y = 20 + val rectangleComponent = new RectangleComponent + rectangleComponent.width = 100 + rectangleComponent.height = 10 + new Entity() + .add(positionComponent) + .add(rectangleComponent) + .add(new MouseXTrackingComponent) + .add(new RenderableComponent) + } + + lazy val blocks: Seq[Entity] = { + val blockWidth = 63 + val blockHeight = 20 + (Gdx.graphics.getWidth / 2 to Gdx.graphics.getHeight by blockHeight + 10).zipWithIndex.flatMap({case (y: Int, colorIndex: Int) => + (0 to Gdx.graphics.getWidth by blockWidth + 10).map(x => { + val positionComponent = new PositionComponent + positionComponent.x = x + positionComponent.y = y + val rectangleComponent = new RectangleComponent + rectangleComponent.width = blockWidth + rectangleComponent.height = blockHeight + rectangleComponent.color = colors(colorIndex) + new Entity() + .add(positionComponent) + .add(rectangleComponent) + .add(new RenderableComponent) + }) + }) + } + + override def create(): Unit = { + // add entities +// ashleyEngine.addEntity(ball) +// ashleyEngine.addEntity(paddle) + blocks.foreach(println) // line should be blocks.foreach(ashleyEngine.addEntity) + + // add systems +// ashleyEngine.addSystem(new MouseXTrackingMovementSystem) +// ashleyEngine.addSystem(new MovementSystem) +// ashleyEngine.addSystem(new RenderingSystem(shapeRenderer)) + } + + override def render(): Unit = { + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) + shapeRenderer.begin(ShapeRenderer.ShapeType.Filled) +// ashleyEngine.update(Gdx.graphics.getDeltaTime) + shapeRenderer.setColor(Color.BLUE) + shapeRenderer.circle(50, 50, 50) + shapeRenderer.end() + } +} diff --git a/core/src/main/scala/com/pluto/box/component/CircleComponent.scala b/core/src/main/scala/com/pluto/box/component/CircleComponent.scala new file mode 100644 index 0000000..4aa65e9 --- /dev/null +++ b/core/src/main/scala/com/pluto/box/component/CircleComponent.scala @@ -0,0 +1,9 @@ +package com.pluto.box.component + +import com.badlogic.ashley.core.Component +import com.badlogic.gdx.graphics.Color + +class CircleComponent extends Component { + var radius: Float = 0.0f + var color: Color = Color.YELLOW +} diff --git a/core/src/main/scala/com/pluto/box/component/MouseXTrackingComponent.scala b/core/src/main/scala/com/pluto/box/component/MouseXTrackingComponent.scala new file mode 100644 index 0000000..fc54de8 --- /dev/null +++ b/core/src/main/scala/com/pluto/box/component/MouseXTrackingComponent.scala @@ -0,0 +1,5 @@ +package com.pluto.box.component + +import com.badlogic.ashley.core.Component + +class MouseXTrackingComponent extends Component {} diff --git a/core/src/main/scala/com/pluto/box/component/PositionComponent.scala b/core/src/main/scala/com/pluto/box/component/PositionComponent.scala new file mode 100644 index 0000000..461ab9d --- /dev/null +++ b/core/src/main/scala/com/pluto/box/component/PositionComponent.scala @@ -0,0 +1,9 @@ +package com.pluto.box.component + +import com.badlogic.ashley.core.Component + +class PositionComponent extends Component { + var x: Float = 0.0f + var y: Float = 0.0f + var z: Float = 0.0f // determines render order +} diff --git a/core/src/main/scala/com/pluto/box/component/RectangleComponent.scala b/core/src/main/scala/com/pluto/box/component/RectangleComponent.scala new file mode 100644 index 0000000..7448e0e --- /dev/null +++ b/core/src/main/scala/com/pluto/box/component/RectangleComponent.scala @@ -0,0 +1,10 @@ +package com.pluto.box.component + +import com.badlogic.ashley.core.Component +import com.badlogic.gdx.graphics.Color + +class RectangleComponent extends Component { + var width: Float = 0.0f + var height: Float = 0.0f + var color: Color = Color.YELLOW +} diff --git a/core/src/main/scala/com/pluto/box/component/RenderableComponent.scala b/core/src/main/scala/com/pluto/box/component/RenderableComponent.scala new file mode 100644 index 0000000..75bbf82 --- /dev/null +++ b/core/src/main/scala/com/pluto/box/component/RenderableComponent.scala @@ -0,0 +1,5 @@ +package com.pluto.box.component + +import com.badlogic.ashley.core.Component + +class RenderableComponent extends Component {} diff --git a/core/src/main/scala/com/pluto/box/component/VelocityComponent.scala b/core/src/main/scala/com/pluto/box/component/VelocityComponent.scala new file mode 100644 index 0000000..48937cc --- /dev/null +++ b/core/src/main/scala/com/pluto/box/component/VelocityComponent.scala @@ -0,0 +1,8 @@ +package com.pluto.box.component + +import com.badlogic.ashley.core.Component + +class VelocityComponent extends Component { + var x: Float = 0.0f + var y: Float = 0.0f +} diff --git a/core/src/main/scala/com/pluto/box/system/MouseXTrackingMovementSystem.scala b/core/src/main/scala/com/pluto/box/system/MouseXTrackingMovementSystem.scala new file mode 100644 index 0000000..5551ce9 --- /dev/null +++ b/core/src/main/scala/com/pluto/box/system/MouseXTrackingMovementSystem.scala @@ -0,0 +1,20 @@ +package com.pluto.box.system + +import com.badlogic.ashley.core.{ComponentMapper, Entity, Family} +import com.badlogic.ashley.systems.IteratingSystem +import com.badlogic.gdx.Gdx +import com.pluto.box.component.{MouseXTrackingComponent, PositionComponent} + +class MouseXTrackingMovementSystem extends IteratingSystem( + Family + .all(classOf[PositionComponent], classOf[MouseXTrackingComponent]) + .get() +) { + private val positionMapper: ComponentMapper[PositionComponent] = ComponentMapper.getFor(classOf[PositionComponent]) + + override def processEntity(entity: Entity, deltaTime: Float): Unit = { + val position = positionMapper.get(entity) + + position.x = Gdx.input.getX() + } +} diff --git a/core/src/main/scala/com/pluto/box/system/MovementSystem.scala b/core/src/main/scala/com/pluto/box/system/MovementSystem.scala new file mode 100644 index 0000000..e096d82 --- /dev/null +++ b/core/src/main/scala/com/pluto/box/system/MovementSystem.scala @@ -0,0 +1,22 @@ +package com.pluto.box.system + +import com.badlogic.ashley.core.{ComponentMapper, Entity, Family} +import com.badlogic.ashley.systems.IteratingSystem +import com.pluto.box.component.{PositionComponent, VelocityComponent} + +class MovementSystem extends IteratingSystem( + Family + .all(classOf[PositionComponent], classOf[VelocityComponent]) + .get() +) { + private val positionMapper: ComponentMapper[PositionComponent] = ComponentMapper.getFor(classOf[PositionComponent]) + private val velocityMapper: ComponentMapper[VelocityComponent] = ComponentMapper.getFor(classOf[VelocityComponent]) + + override def processEntity(entity: Entity, deltaTime: Float): Unit = { + val position = positionMapper.get(entity) + val velocity = velocityMapper.get(entity) + + position.x += velocity.x * deltaTime + position.y += velocity.y * deltaTime + } +} diff --git a/core/src/main/scala/com/pluto/box/system/RenderingSystem.scala b/core/src/main/scala/com/pluto/box/system/RenderingSystem.scala new file mode 100644 index 0000000..1f2df0e --- /dev/null +++ b/core/src/main/scala/com/pluto/box/system/RenderingSystem.scala @@ -0,0 +1,35 @@ +package com.pluto.box.system + +import com.badlogic.ashley.core.{ComponentMapper, Entity, Family} +import com.badlogic.ashley.systems.SortedIteratingSystem +import com.badlogic.gdx.graphics.glutils.ShapeRenderer +import com.pluto.box.component.{CircleComponent, PositionComponent, RectangleComponent, RenderableComponent} +import com.pluto.box.util.ZComparator + +class RenderingSystem(shapeRenderer: ShapeRenderer) extends SortedIteratingSystem( + Family + .all(classOf[PositionComponent], classOf[RenderableComponent]) + .one(classOf[CircleComponent], classOf[RectangleComponent]) + .get(), + ZComparator +) { + private val positionMapper: ComponentMapper[PositionComponent] = ComponentMapper.getFor(classOf[PositionComponent]) + private val circleMapper: ComponentMapper[CircleComponent] = ComponentMapper.getFor(classOf[CircleComponent]) + private val rectangleMapper: ComponentMapper[RectangleComponent] = ComponentMapper.getFor(classOf[RectangleComponent]) + + override def processEntity(entity: Entity, deltaTime: Float): Unit = { + val position = positionMapper.get(entity) + val circleOpt = Option(circleMapper.get(entity)) + val rectangleOpt = Option(rectangleMapper.get(entity)) + + circleOpt.foreach(circle => { + shapeRenderer.setColor(circle.color) + shapeRenderer.circle(position.x, position.y, circle.radius) + }) + + rectangleOpt.foreach(rectangle => { + shapeRenderer.setColor(rectangle.color) + shapeRenderer.rect(position.x, position.y, rectangle.width, rectangle.height) + }) + } +} diff --git a/core/src/main/scala/com/pluto/box/util/ZComparator.scala b/core/src/main/scala/com/pluto/box/util/ZComparator.scala new file mode 100644 index 0000000..ff5549e --- /dev/null +++ b/core/src/main/scala/com/pluto/box/util/ZComparator.scala @@ -0,0 +1,14 @@ +package com.pluto.box.util + +import com.badlogic.ashley.core.{ComponentMapper, Entity} +import com.pluto.box.component.PositionComponent + +import java.util.Comparator + +object ZComparator extends Comparator[Entity] { + private val positionComponent: ComponentMapper[PositionComponent] = ComponentMapper.getFor(classOf[PositionComponent]) + + override def compare(o1: Entity, o2: Entity): Int = { + Math.signum(positionComponent.get(o1).z - positionComponent.get(o2).z).toInt + } +} diff --git a/desktop/src/main/scala/com/pluto/box/DesktopLauncher.scala b/desktop/src/main/scala/com/pluto/box/DesktopLauncher.scala index 9c3fcb2..8972466 100644 --- a/desktop/src/main/scala/com/pluto/box/DesktopLauncher.scala +++ b/desktop/src/main/scala/com/pluto/box/DesktopLauncher.scala @@ -5,5 +5,5 @@ import com.badlogic.gdx.backends.lwjgl3.{Lwjgl3Application, Lwjgl3ApplicationCon object DesktopLauncher extends App { val config = new Lwjgl3ApplicationConfiguration config.setWindowSizeLimits(800, 800, 1000, 1000) - new Lwjgl3Application(new TestGame, config) + new Lwjgl3Application(new BreakoutGame, config) } diff --git a/project/Dependencies.scala b/project/Dependencies.scala index a0b399a..b4244e0 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -24,12 +24,14 @@ object Dependencies { lazy val teaVMJsoImpl ="org.teavm" % "teavm-jso-impl" % Versions.teaVMVersion lazy val gdxTeaVM = "com.github.xpenatan.gdx-teavm" % "backend-teavm" % Versions.gdxTeaVMVersion lazy val gdxFreetypeTeaVM = "com.github.xpenatan.gdx-teavm" % "gdx-freetype-teavm" % Versions.gdxTeaVMVersion + lazy val ashley = "com.badlogicgames.ashley" % "ashley" % "1.7.4" lazy val core = depends( slf4j, gdxPlatform, gdxFreetype, gdxFreetypePlatform, + ashley ) lazy val desktop = depends( diff --git a/project/Versions.scala b/project/Versions.scala index 1392d8f..693f162 100644 --- a/project/Versions.scala +++ b/project/Versions.scala @@ -2,5 +2,5 @@ object Versions { lazy val scala = "2.13.12" lazy val libgdxVersion = "1.12.1" lazy val gdxTeaVMVersion = "1.0.0-b9" - lazy val teaVMVersion = "0.9.2" + lazy val teaVMVersion = "0.10.0-dev-8" } diff --git a/teavm/src/main/scala/com/pluto/box/TeaVMBuilder.scala b/teavm/src/main/scala/com/pluto/box/TeaVMBuilder.scala index 346942e..5857754 100644 --- a/teavm/src/main/scala/com/pluto/box/TeaVMBuilder.scala +++ b/teavm/src/main/scala/com/pluto/box/TeaVMBuilder.scala @@ -1,5 +1,6 @@ package com.pluto.box +import com.github.xpenatan.gdx.backends.teavm.config.plugins.TeaReflectionSupplier import com.github.xpenatan.gdx.backends.teavm.config.{TeaBuildConfiguration, TeaBuilder} import com.github.xpenatan.gdx.backends.teavm.gen.SkipClass import org.teavm.vm.TeaVMOptimizationLevel @@ -19,6 +20,11 @@ object TeaVMBuilder { // Register any classes or packages that require reflection here: // TeaReflectionSupplier.addReflectionClass("com.pluto.box.reflect") + // Unsure if these are necessary + TeaReflectionSupplier.addReflectionClass("com.pluto.box.component") + TeaReflectionSupplier.addReflectionClass("com.pluto.box.util") + TeaReflectionSupplier.addReflectionClass("com.pluto.box.system") + val tool = TeaBuilder.config(teaBuildConfiguration) tool.setOptimizationLevel(TeaVMOptimizationLevel.ADVANCED) tool.setObfuscated(true) diff --git a/teavm/src/main/scala/com/pluto/box/TeaVMLauncher.scala b/teavm/src/main/scala/com/pluto/box/TeaVMLauncher.scala index 281a1b3..4d6b3a6 100644 --- a/teavm/src/main/scala/com/pluto/box/TeaVMLauncher.scala +++ b/teavm/src/main/scala/com/pluto/box/TeaVMLauncher.scala @@ -5,6 +5,9 @@ import com.github.xpenatan.gdx.backends.teavm.{TeaApplication, TeaApplicationCon object TeaVMLauncher { def main(args: Array[String]): Unit = { val config = new TeaApplicationConfiguration("canvas") - new TeaApplication(new TestGame, config) + // Setting these to 0 will fill all available space on web browser + config.width = 0 + config.height = 0 + new TeaApplication(new BreakoutGame, config) } }