Skip to content

Commit

Permalink
add stairs and treasure
Browse files Browse the repository at this point in the history
  • Loading branch information
mtrupkin committed Mar 13, 2016
1 parent aeed4b0 commit e05af6b
Show file tree
Hide file tree
Showing 14 changed files with 173 additions and 82 deletions.
Binary file modified src/main/resources/rex/area-1.xp
Binary file not shown.
Binary file modified src/main/resources/rex/area-2.xp
Binary file not shown.
Binary file modified src/main/resources/rex/area-3.xp
Binary file not shown.
Binary file added src/main/resources/rex/area-4.xp
Binary file not shown.
Binary file added src/main/resources/rex/area-5.xp
Binary file not shown.
Binary file added src/main/resources/rex/area-6.xp
Binary file not shown.
Binary file added src/main/resources/rex/start-1.xp
Binary file not shown.
2 changes: 1 addition & 1 deletion src/main/resources/views/Console.css
Expand Up @@ -4,7 +4,7 @@

.dark, .dark .label {
-fx-background-color: black;
-fx-font-size: 16pt;
-fx-font-size: 24pt;
-fx-font-family: "Segoe UI Semibold";
-fx-text-fill: white;
}
Expand Down
24 changes: 7 additions & 17 deletions src/main/resources/views/Game.fxml
Expand Up @@ -18,30 +18,20 @@
<Pane fx:id="consolePane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="200.0" minWidth="400.0" style="-fx-border-color: white;" styleClass="dark-background" GridPane.halignment="LEFT" GridPane.valignment="TOP" />
<GridPane styleClass="dark" GridPane.columnIndex="1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="435.0" minWidth="120.0" prefWidth="120.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="789.0" minWidth="10.0" prefWidth="774.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="200.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="789.0" minWidth="10.0" prefWidth="672.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="ALWAYS" />
</rowConstraints>
<children>
<Label text="Hit Points:" />
<Label text="Attack:" GridPane.rowIndex="2" />
<Label layoutX="10.0" layoutY="75.0" text="Damage:" GridPane.rowIndex="3" />
<Label layoutX="10.0" layoutY="175.0" text="Modifier:" GridPane.rowIndex="6" />
<Label layoutX="10.0" layoutY="180.0" text="Defense:" GridPane.rowIndex="4" />
<Label text="Attack:" GridPane.rowIndex="1" />
<Label fx:id="hitPoints" layoutX="10.0" layoutY="60.0" text="0" GridPane.columnIndex="1" />
<Label fx:id="attack" layoutX="10.0" layoutY="140.0" text="0" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label fx:id="damage" layoutX="10.0" layoutY="100.0" text="0" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<Label fx:id="modifier" layoutX="10.0" layoutY="20.0" text="0" GridPane.columnIndex="1" GridPane.rowIndex="6" />
<Label fx:id="defense" layoutX="10.0" layoutY="180.0" text="0" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Label fx:id="attack" layoutX="10.0" layoutY="140.0" text="0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/app/App.scala
Expand Up @@ -14,7 +14,7 @@ class ConsoleApp extends Application {
val is = getClass.getResourceAsStream(s"/fonts/RobotoMono-Regular.ttf")
ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, is))

primaryStage.setTitle("Rogue")
primaryStage.setTitle("Alpha Rogue")

object Controller extends Controller {
lazy val initialState: ControllerState = new GameController(WorldBuilder())
Expand Down
15 changes: 3 additions & 12 deletions src/main/scala/controller/Game.scala
Expand Up @@ -23,13 +23,7 @@ trait Game { self: Controller =>
@FXML var consolePane: Pane = _

@FXML var hitPoints: Label = _

@FXML var damage: Label = _

@FXML var attack: Label = _
@FXML var modifier: Label = _

@FXML var defense: Label = _

@FXML var textArea: TextArea = _

Expand All @@ -53,6 +47,8 @@ trait Game { self: Controller =>
consolePane.getChildren.add(console)

consolePane.setFocusTraversable(true)

textArea.appendText("Welcome to Alpha Rogue.\nPress Tab to cycle special actions. Ctrl-Direction to use special action.\n")
}

override def update(elapsed: Int): Unit = {
Expand All @@ -69,12 +65,7 @@ trait Game { self: Controller =>

hitPoints.setText(player.hitPoints.toString)

damage.setText(player.damage.toString)

attack.setText(player.attackRating.toString)
modifier.setText(player.modifier().toString)

defense.setText(player.defenseRating.toString)
}

def handleMouseMove(event: sfxi.MouseEvent): Unit = {
Expand All @@ -97,7 +88,7 @@ trait Game { self: Controller =>
val direction = getDirection(code)
code match {
case ESCAPE => exit()
case TAB => world.player.nextAction()
case TAB => textArea.appendText(world.player.nextAction())
case _ => direction.map( p => {
val text = if (event.controlDown) world.specialAction(p) else world.action(p)
textArea.appendText(text)
Expand Down
57 changes: 28 additions & 29 deletions src/main/scala/model/Agent.scala
Expand Up @@ -13,13 +13,11 @@ trait Agent {
var position: Point
var hitPoints: Int

// combat stats
var damage: Int = 1
var attackRating: Int = 1
// combat stat
var attackRating: Int

// situational modifiers
def modifier(): Int = 0
var defenseRating: Int = 1
var modifier: Int = 0

val sc: ScreenChar
}
Expand All @@ -28,39 +26,40 @@ case class Monster(
val name: String,
var position: Point,
var hitPoints: Int,
var attackRating: Int,
val sc: ScreenChar) extends Agent {
def attack(player: Player): Option[String] = {
val bonusDamage = Combat.bonusDamage(this, player)
if (bonusDamage > 0 ) {
player.hitPoints -= bonusDamage
Some(s"Player damaged: $bonusDamage")
val damage = Combat.damage(this, player)
if (damage > 0 ) {
player.hitPoints -= damage
Some(s"Monster attacks player for $damage damage.")
} else None
}
}

class Player(
var position: Point,
var hitPoints: Int,
var attackRating: Int = 1,
val sc: ScreenChar) extends Agent {

var currentActionIndex = 0
val actions: List[Action] = List(Dash, Burst, Blast)

def nextAction(): Unit = {
def nextAction(): String = {
currentActionIndex += 1
if (currentActionIndex >= actions.size) currentActionIndex = 0
println(actions(currentActionIndex))
s"\nSpecial action: ${actions(currentActionIndex)}"
}

def action(): Action = actions(currentActionIndex)

def attack(monster: Monster): String = {
val bonusDamage = Combat.bonusDamage(this, monster)
val totalDamage = damage + bonusDamage
val damage = Math.max(1, Combat.damage(this, monster))

monster.hitPoints -= totalDamage
monster.hitPoints -= damage

s"Attack ${monster.name}: $totalDamage"
s"Player attacks ${monster.name} for $damage damage."
}

sealed trait Action {
Expand All @@ -72,7 +71,11 @@ class Player(
val (canDash, firstText) = world.attackOrMove(direction)
if (canDash) {
val (_, secondText) = world.attackOrMove(direction)
secondText
secondText match {
case Some(text) => Some(s"\nDash\n$text")
case None => Some(s"\nDash")
}

} else firstText
}
}
Expand All @@ -93,7 +96,7 @@ class Player(
neighbors(origin).foreach(p => {
world.monsters.find(_.position == p).map(m => textList += attack(m))
})
if (textList.isEmpty) None else Some(textList.mkString("\n"))
if (textList.isEmpty) None else Some(s"\nBurst\n${textList.mkString("\n")}")
}
}
// attack 3x3 around player
Expand All @@ -103,7 +106,7 @@ class Player(
position.neighbors().foreach(p => {
world.monsters.find(_.position == p).map(m => textList += attack(m))
})
if (textList.isEmpty) None else Some(textList.mkString("\n"))
if (textList.isEmpty) None else Some(s"\nBlast\n${textList.mkString("\n")}")
}
}
}
Expand All @@ -112,18 +115,14 @@ object Combat {
// chance that a multiple is successful
val multipleDamageChance = 50

private def bonusDamage(damage: Int, multiplier: Int, modifier: Int): Int = {
val bonuses = for {
i <- 1 to multiplier
if (Random.nextInt(100) + modifier > multipleDamageChance)
} yield damage

bonuses.sum
}
private def totalHits(attack: Int, modifier: Int): Int = {
val hits = for {
i <- 1 to attack
if ((Random.nextInt(100) + modifier) > multipleDamageChance)
} yield 1

def bonusDamage(offense: Agent, defense: Agent): Int = {
val multiplier = Math.max(offense.attackRating - defense.defenseRating, 1)
bonusDamage(offense.damage, multiplier, offense.modifier())
hits.sum
}

def damage(offense: Agent, defense: Agent): Int = totalHits(offense.attackRating, offense.modifier)
}
61 changes: 59 additions & 2 deletions src/main/scala/model/World.scala
Expand Up @@ -5,6 +5,7 @@ import org.mtrupkin.core.{Matrix, Size, Point}
import pathfinding.AStar

import scala.collection.mutable.ListBuffer
import scala.util.Random

/**
* Created by mtrupkin on 2/10/2016.
Expand All @@ -18,6 +19,7 @@ sealed trait Terrain {
var explored: Boolean = false
var marked: Boolean = false
def display: ScreenChar = if(explored) sc else Terrain.unexplored
def action(world: World): Option[String] = None
}

trait TerrainMap {
Expand All @@ -42,6 +44,39 @@ case class Door(areaID: Int, var open: Boolean = false) extends Terrain {
def sc: ScreenChar = if (open) openScreenChar else closedScreenChar
}

case class Treasure(areaID: Int) extends Terrain {
var looted: Boolean = false
val unlootedScreenChar = ScreenChar('*', Colors.Yellow, Terrain.floorColor)
val lootedScreenChar = ScreenChar('.', Colors.White, Terrain.floorColor)

def name = "Treasure"
def move = true

override def sc: ScreenChar = if (looted) lootedScreenChar else unlootedScreenChar

override def action(world: World): Option[String] = {
if (looted) return None

looted = true
Random.nextInt(100) match {
case x if 0 until 20 contains x => {
world.player.hitPoints += 2
Some("Healing potion.")
}
case x if 20 until 40 contains x => {
world.player.attackRating += 1
Some("Weapon damage +1.")
}
case x if 40 until 60 contains x => {
world.player.modifier += 5
Some("Weapon to hit +1")
}
case _ => None
}
}
}


object Terrain {
val floorColor = RGB(70, 70, 70)

Expand All @@ -55,6 +90,12 @@ object Terrain {

def floor(areaID: Int, sc: ScreenChar) = Cell(areaID, "Floor", sc.copy(c = '.'), move = true)
def wall(areaID: Int, sc: ScreenChar) = Cell(areaID, "Wall", sc, move = false)
def stairsDown(areaID: Int) = new Cell(areaID, "Stairs Down", ScreenChar('>', Colors.White, floorColor), move = true) {
override def action(world: World): Option[String] = {
WorldBuilder.newWorld(world)
Some(s"Descending to level ${world.level}")
}
}

val outOfBoundsWall: Cell = wall(-1, ScreenChar('#', Colors.White, floorColor))
//val inBoundsWall: Cell = wall(-2, ScreenChar('#', Colors.White, floorColor))
Expand All @@ -65,15 +106,18 @@ object Terrain {
}

class World(val player: Player) extends TerrainMap {
var level = 0
val size = Size(40, 20)
val cells = new Matrix[Terrain](size)
var monsters = List[Monster]()

def apply(p: Point): Terrain = if(size.in(p)) cells(p) else Terrain.outOfBoundsWall

def action(direction: Point): String = {
val moveMonsters = triggersMonsterMove(player.position + direction)
val (_, playerText) = attackOrMove(direction)
val gameText = endAction()

val gameText = if (moveMonsters) endAction() else None

val s1 = playerText match {
case Some(t) => s"\n$t"
Expand Down Expand Up @@ -103,9 +147,12 @@ class World(val player: Player) extends TerrainMap {

def endAction(): Option[String] = {
val text = ListBuffer[String]()
monsters.foreach(m => if (m.hitPoints <= 0) text.append(s"${m.name} died"))
monsters.foreach(m => if (m.hitPoints <= 0) text.append(s"${m.name} died."))
monsters = monsters.filter(_.hitPoints > 0)
monsters.foreach(moveMonster(_).map(t => text.append(t)))

this(player.position).action(this).map(t => text.append(t))

if (text.isEmpty) None else Some(text.mkString("\n"))
}

Expand All @@ -128,6 +175,16 @@ class World(val player: Player) extends TerrainMap {
}
}

def triggersMonsterMove(p: Point): Boolean = {
val newTerrain = this(p)
newTerrain match {
case Door(_, open) => open
case Cell(_, _, _, move) => move
case c: Treasure => true
}
}


// returns true if moved only
def move(p: Point): Boolean = {
val newTerrain = this(p)
Expand Down

0 comments on commit e05af6b

Please sign in to comment.