Swarm game
Created in 2014, published on 17/01/2023Here is a gameplay image of the game where the leader in red is being chased by a swarm of other circles. The squares are obstacles which the swarm, including the leader, needs to go around. The goal is to move maximum amount of circles from one end of a level to the other while the obstacles scroll by.
/* GUI.scala */
package game.gui
import game._
import scala._
import org.eclipse.swt._
import org.eclipse.swt.events._
import org.eclipse.swt.graphics._
import org.eclipse.swt.widgets._
object GUI {
def main(args: Array[String]): Unit = {
Game.simulationLoop()
var display = new Display()
var shell = new Shell(display)
display.asyncExec(new Runnable() {
def run(): Unit = {
if (!display.isDisposed()) {
shell.addMouseMoveListener(new MouseMoveListener() {
def mouseMove(event: MouseEvent): Unit = {
Game.eventLoop("MouseMoved", event.x, event.y, true)
}
})
}
}
})
shell.setMinimumSize(Game.level.getSize.getX.toInt, Game.level.getSize.getY.toInt)
shell.pack()
shell.open()
shell.addPaintListener(new PaintListener() {
def paintControl(event: PaintEvent): Unit = {
var gc = event.gc
var red = new Color(event.widget.getDisplay(), 0xFF,0, 0)
var black = new Color(event.widget.getDisplay(), 0, 0, 0)
if(Game.swarm.getSwarmSize > 0) {
val swarmList = Game.swarm.getSwarmList
for(i <- 0 until swarmList.length) {
if(swarmList(i) == Game.swarm.getLeader) {
gc.setForeground(red)
}
gc.drawOval(swarmList(i).getPosition.getX.toInt, swarmList(i).getPosition.getY.toInt, swarmList(i).radius*2, swarmList(i).radius*2)
gc.setForeground(black)
}
}
if(Game.level.getObstacleList.length > 0) {
val obstacleList = Game.level.getObstacleList
var xList: scala.List[Int] = scala.List()
var yList: scala.List[Int] = scala.List()
var combinedList: scala.List[Int] = scala.List()
for(i <- 0 until obstacleList.length) {
for(j <- 0 until obstacleList(i).corners) {
xList = xList :+ obstacleList(i).cornerPositions(j).getX.toInt
yList = yList :+ obstacleList(i).cornerPositions(j).getY.toInt
combinedList = combinedList :+ obstacleList(i).cornerPositions(j).getX.toInt
combinedList = combinedList :+ obstacleList(i).cornerPositions(j).getY.toInt
}
gc.drawPolygon(combinedList.toArray)
combinedList = scala.List()
xList = scala.List()
yList = scala.List()
}
}
red.dispose()
}
})
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
shell.redraw()
}
}
display.dispose()
}
}
GUI.scala includes the main object that creates the window and the components in it, listens to user input and draws the simulation.
/* Game.scala */
package game
import game.gui._
import game.io._
import game.sim._
object Game {
private var leaderOffsetX: Double = 0
private var leaderOffsetY: Double = 0
var swarm = new Swarm
var level = new Level
def eventLoop(event: String, mouseX: Double, mouseY: Double, mouseMoved: Boolean): Unit = {
if(event == "MouseClicked") {
val swarmList = this.swarm.getSwarmList
for(i <- 0 until swarmList.length) {
if(((mouseX - swarmList(i).getPosition.getX) < swarmList(i).radius*2 && (mouseX - swarmList(i).getPosition.getX) > 0) && ((mouseY - swarmList(i).getPosition.getY) < swarmList(i).radius*2 && (mouseY - swarmList(i).getPosition.getY) > 0)) {
if(this.swarm.getLeaderControlMode == "automatic") {
this.swarm.setLeader(i)
this.leaderOffsetX = swarmList(i).getPosition.getX - mouseX
this.leaderOffsetY = swarmList(i).getPosition.getY - mouseY
}
else {
this.swarm.changeLeaderControlMode
}
}
}
}
if(mouseMoved == true && this.swarm.getLeaderControlMode == "manual") {
this.swarm.changeLeaderTarget(mouseX + this.leaderOffsetX, mouseY + this.leaderOffsetY)
}
}
def simulationLoop(): Unit = {
File.readTextFile("src/main/scala/preferences/preferences1.txt", "Preferences")
File.readTextFile("src/main/scala/levels/level3.txt", "Level")
var simulation = new Thread(new SimulationThread)
simulation.start
}
}
Game.scala includes the object that holds information about the game preferences, initiates objects from the sim- and io-packages, runs the simulation thread and interprets user input from the main thread.
/* SimulationThread.scala */
package game
import game.gui._
class SimulationThread extends Runnable {
def run(): Unit = {
while(true) {
Game.level.updateBackground
Game.swarm.updateMovement
Game.swarm.calculateCollisions(Game.level)
Game.swarm.checkIfLostSwarmMember
Thread.sleep(20)
}
}
}
SimulationThread.scala ...