Skip to content

Commit

Permalink
wip(map-pick): add map picker in setup view
Browse files Browse the repository at this point in the history
  • Loading branch information
manuandru committed Oct 12, 2023
1 parent 7b2ca2a commit 05725d4
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 4 deletions.
7 changes: 4 additions & 3 deletions src/main/scala/scatan/controllers/game/SetUpController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package scatan.controllers.game
import scatan.lib.mvc.{BaseController, Controller}
import scatan.model.ApplicationState
import scatan.views.game.SetUpView
import scatan.model.GameMap

/** This is the controller for the setup page.
*/
trait SetUpController extends Controller[ApplicationState]:
def startGame(usernames: String*): Unit
def startGame(gameMap: GameMap, usernames: String*): Unit

object SetUpController:
def apply(requirements: Controller.Requirements[SetUpView, ApplicationState]): SetUpController =
Expand All @@ -21,5 +22,5 @@ private class SetUpControllerImpl(requirements: Controller.Requirements[SetUpVie
extends BaseController(requirements)
with SetUpController:

override def startGame(usernames: String*): Unit =
this.model.update(_.createGame(usernames*))
override def startGame(gameMap: GameMap, usernames: String*): Unit =
this.model.update(_.createGame(gameMap, usernames*))
46 changes: 45 additions & 1 deletion src/main/scala/scatan/views/game/SetUpView.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ import scatan.Pages
import scatan.controllers.game.SetUpController
import scatan.lib.mvc.{BaseScalaJSView, View}
import scatan.model.ApplicationState
import scatan.views.game.components.map.MapComponent
import scatan.model.GameMap
import MapSelectionMode.*
import scatan.views.game.components.LeftTabComponent.buttonsComponent
import scatan.model.GameMapFactory

enum MapSelectionMode:
case Default, Random, WithIterator

/** This is the view for the setup page.
*/
Expand Down Expand Up @@ -35,6 +43,18 @@ private class ScalaJsSetUpView(container: String, requirements: View.Requirement
val numberOfUsers: Var[Int] = Var(3)
val reactiveNumberOfUsers: Signal[Int] = numberOfUsers.signal

val mapSelectionMode: Var[MapSelectionMode] = Var(MapSelectionMode.Default)
val reactiveGameMap: Var[GameMap] = Var(GameMapFactory.defaultMap)

def changeMap: Unit =
mapSelectionMode.now() match
case Default =>
reactiveGameMap.set(GameMapFactory.defaultMap)
case Random =>
reactiveGameMap.set(GameMapFactory.randomMap)
case WithIterator =>
reactiveGameMap.set(GameMapFactory.nextPermutation)

private def validateNames(usernames: String*) =
usernames.forall(_.matches(".*\\S.*"))

Expand All @@ -48,7 +68,7 @@ private class ScalaJsSetUpView(container: String, requirements: View.Requirement
.value
if validateNames(usernames*) then
println(usernames)
this.controller.startGame(usernames*)
this.controller.startGame(reactiveGameMap.now(), usernames*)
this.navigateTo(Pages.Game)

override def switchToHome(): Unit =
Expand Down Expand Up @@ -104,5 +124,29 @@ private class ScalaJsSetUpView(container: String, requirements: View.Requirement
cls := "setup-menu-button",
onClick --> (_ => this.switchToHome()),
"Back"
),
div(
cls := "setup-menu-map-picker",
div(
cls := "setup-menu-map-picker-left-tab",
select(
cls := "setup-menu-map-picker-combobox",
onChange.mapToValue.map(v => MapSelectionMode.fromOrdinal(v.toInt)) --> mapSelectionMode,
for (mode <- MapSelectionMode.values)
yield option(
value := s"${mode.ordinal}",
mode.toString
)
),
button(
cls := "setup-menu-map-picker-button",
"Change Map",
onClick --> (_ => changeMap)
)
),
div(
cls := "setup-menu-map",
child <-- reactiveGameMap.signal.map(gameMap => MapComponent.map(using gameMap))
)
)
)
87 changes: 87 additions & 0 deletions src/main/scala/scatan/views/game/components/map/MapComponent.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package scatan.views.game.components.map

import scatan.model.GameMap
import com.raquo.laminar.api.L.*
import scatan.model.map.Hexagon
import scatan.views.utils.Coordinates.center
import scatan.views.utils.Coordinates
import scatan.views.game.components.ContextMap
import scatan.views.game.components.ContextMap.toImgId
import scatan.model.map.TileContent
import scatan.model.components.UnproductiveTerrain

object MapComponent:

private given hexSize: Int = 100
private val radius = hexSize / 4
private val svgCornersPoints: String =
(for
i <- 0 to 5
angleDeg = 60 * i + 30
angleRad = Math.PI / 180 * angleDeg
x = hexSize * math.cos(angleRad)
y = hexSize * math.sin(angleRad)
yield s"$x,$y").mkString(" ")
private val layersToCanvasSize: Int => Int = x => (2 * x * hexSize) + 50

def map: GameMap ?=> Element =
val gameMap = summon[GameMap]
val canvasSize = layersToCanvasSize(gameMap.totalLayers)
svg.svg(
svgImages,
svg.viewBox := s"-${canvasSize} -${canvasSize} ${2 * canvasSize} ${2 * canvasSize}",
for
hex <- gameMap.tiles.toList
content = gameMap.toContent(hex)
yield svgHexagon(hex, content)
)

private def svgHexagon(hex: Hexagon, content: TileContent): Element =
val Coordinates(x, y) = hex.center
svg.g(
svg.transform := s"translate($x, $y)",
svg.polygon(
svg.points := svgCornersPoints,
svg.cls := "hexagon",
svg.fill := s"url(#${content.terrain.toImgId})"
),
content.terrain match
case UnproductiveTerrain.Sea => ""
case _ => circularNumber(hex, content)
)

def circularNumber(hex: Hexagon, content: TileContent): Element =
svg.g(
svg.circle(
svg.cx := "0",
svg.cy := "0",
svg.r := s"$radius",
svg.className := "hexagon-center-circle"
),
svg.text(
svg.x := "0",
svg.y := "0",
svg.fontSize := s"$radius",
svg.className := "hexagon-center-number",
content.number.map(_.toString).getOrElse("")
)
)

private val svgImages: Element =
svg.svg(
svg.defs(
for (terrain, path) <- ContextMap.resources.toList
yield svg.pattern(
svg.idAttr := terrain.toImgId,
svg.width := "100%",
svg.height := "100%",
svg.patternContentUnits := "objectBoundingBox",
svg.image(
svg.href := path,
svg.width := "1",
svg.height := "1",
svg.preserveAspectRatio := "none"
)
)
)
)
32 changes: 32 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,36 @@ body {
margin-top: 2.5em;
}

.setup-menu-map-picker {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 100%;
}

.setup-menu-map-picker-left-tab {
display: flex;
padding: 0 4em;
flex-direction: column;
}

.setup-menu-map-picker-button {
font-size: 1.5em;
padding: 0.6em 0.8em;
margin-top: 3em;
border-radius: 1em;
background-color: var(--button-color);
}

.setup-menu-map-picker-combobox {
font-size: 3em;
}

.setup-menu-map {
width: 25%;
}

/* Game */
.game-view-left-tab {
display: inline-flex;
Expand Down Expand Up @@ -203,9 +233,11 @@ body {
.game-view-phase {
font-size: 1em;
}

.game-view-step {
font-size: 1em;
}

.game-view-buttons {
margin-top: 1em;
display: flex;
Expand Down

0 comments on commit 05725d4

Please sign in to comment.