From 6ad1be646ae22041b2d31fd9faa2166a15146e03 Mon Sep 17 00:00:00 2001 From: alphaneet Date: Sat, 4 Feb 2012 20:13:48 +0900 Subject: [PATCH] refs #35 2012/02/04 nightly. --- models/src/main/scala/Board.scala | 2 +- models/src/main/scala/Deck.scala | 23 +++++++- models/src/main/scala/Game.scala | 3 + models/src/main/scala/Player.scala | 4 +- processing2D/BoardSelectScene.scala | 10 +++- processing2D/DeckMakeScene.scala | 12 +++- processing2D/DeckScene.scala | 45 ++++++--------- processing2D/DeckSelectScene.scala | 21 +++++-- processing2D/GameScene.scala | 85 +++++++++++++++++++++++++++++ processing2D/TitleScene.scala | 6 +- processing2D/main.scala | 13 ++++- processing2D/package.scala | 56 +++++++++++-------- 12 files changed, 213 insertions(+), 67 deletions(-) create mode 100644 processing2D/GameScene.scala diff --git a/models/src/main/scala/Board.scala b/models/src/main/scala/Board.scala index 03aa257..9ef3930 100644 --- a/models/src/main/scala/Board.scala +++ b/models/src/main/scala/Board.scala @@ -33,7 +33,7 @@ object Board { } } -case class Board( +class Board( val width: Int, val height: Int, val name: String = "", diff --git a/models/src/main/scala/Deck.scala b/models/src/main/scala/Deck.scala index a95029d..c1e0862 100644 --- a/models/src/main/scala/Deck.scala +++ b/models/src/main/scala/Deck.scala @@ -6,7 +6,7 @@ class Deck(val maxCost: Int) extends NotNull { def foreach(f: Character => Unit) { champion foreach { f(_) } - minions foreach { f(_) } + minions foreach { f(_) } } def clear() { @@ -35,8 +35,9 @@ class Deck(val maxCost: Int) extends NotNull { } catch { case _ => false } - - def isCostOver: Boolean = nowCost > maxCost + + def isMaxCost: Boolean = nowCost == maxCost + def isCostOver: Boolean = nowCost > maxCost def nowCost: Int = champion.map(_.param.cost).getOrElse(0) + minions.foldLeft(0)(_ + _.param.cost) @@ -92,4 +93,20 @@ class Deck(val maxCost: Int) extends NotNull { this } + + def random(champions: List[Champion], minions: List[Minion]): this.type = { + import scala.util.Random.{nextInt, shuffle} + + this.clear() + this.champion = Option(champions(nextInt(champions.size))) + + shuffle(minions) foreach { + minion => + this.minions += minion + if (this.isCostOver) this.minions -= minion + if (this.isMaxCost) return this + } + + this + } } diff --git a/models/src/main/scala/Game.scala b/models/src/main/scala/Game.scala index b33bcc1..79c5556 100644 --- a/models/src/main/scala/Game.scala +++ b/models/src/main/scala/Game.scala @@ -1,5 +1,8 @@ package com.github.alphaneet.suparobo + +// TK: GameReady とかの Option 用のクラスを用意すべきかも +// GameDeliver という名前を思いついた case class Game( self: Option[Player] = None, other: Option[Player] = None, diff --git a/models/src/main/scala/Player.scala b/models/src/main/scala/Player.scala index e375e14..f54aa42 100644 --- a/models/src/main/scala/Player.scala +++ b/models/src/main/scala/Player.scala @@ -1,3 +1,5 @@ package com.github.alphaneet.suparobo -class Player +case class Player(deck: Deck) extends NotNull { + +} diff --git a/processing2D/BoardSelectScene.scala b/processing2D/BoardSelectScene.scala index 9c959b5..79c94b6 100644 --- a/processing2D/BoardSelectScene.scala +++ b/processing2D/BoardSelectScene.scala @@ -41,7 +41,15 @@ case class BoardSelectScene( filename => val board = Board.loadXML(BOARDS_PATH + filename) - val sprite = createBoardSprite(board, viewerRect) + val sprite = createBoardSprite( + board, + viewerRect, + (g, rect) => { + g.stroke(C5R, C5G, C5B) + g.noFill() + g.rect(0, 0, rect.width - 1, rect.height - 1) + } + ) val buttonImages = List( (C2, C5), (C1, C4), diff --git a/processing2D/DeckMakeScene.scala b/processing2D/DeckMakeScene.scala index 7febd1f..dd86f1b 100644 --- a/processing2D/DeckMakeScene.scala +++ b/processing2D/DeckMakeScene.scala @@ -14,12 +14,20 @@ case class DeckMakeScene(implicit applet: SPApplet, i18n: I18N) registerButtons( menuBtnMgr, List( - ('save, t("save"), save _), + ('save, t("save"), confirmAndSave _), ('clear, t("clear"), clear _), ('back, t("back"), back _) ) ) - + + def confirmAndSave() { + dialog.confirm(nowDeckName + " " + t("confirm.save")) { + save { + dialog.message(t("execute.save")) + } + } + } + def back() { dialog.confirm(t("TitleScene.back")) { TitleScene() diff --git a/processing2D/DeckScene.scala b/processing2D/DeckScene.scala index d23ef34..0d24b43 100644 --- a/processing2D/DeckScene.scala +++ b/processing2D/DeckScene.scala @@ -13,16 +13,6 @@ abstract class DeckScene( val dialog = new MyDialog - val champions: List[Champion] = Champion.loadChampions( - CHARACTERS_PATH + "championProfiles.xml", - CHARACTERS_PATH + "championParameters.xml" - ) - - val minions: List[Minion] = Minion.loadMinions( - CHARACTERS_PATH + "minionProfiles.xml", - CHARACTERS_PATH + "minionParameters.xml" - ) - val decks: List[Deck] = List.range(0, MAX_DECK) map { i => createDeck() } var nowDeck = decks(0) @@ -203,25 +193,24 @@ abstract class DeckScene( } def nowDeckName: String = t("deck") + (decks.indexOf(nowDeck) + 1) - - def save() { - dialog.confirm(nowDeckName + " " + t("confirm.save")) { - try { - val filename = DECKS_PATH + "deck" + decks.indexOf(nowDeck) + ".xml" - nowDeck.entry().saveXML(filename) - dialog.message(t("execute.save")) - } catch { - case _: NoSuchChampionException => - dialog.message(t("NoSuchChampionException")) - case _: OverCostException => - dialog.message(t("OverCostException")) - case ex => - ex.printStackTrace(Console.err) - dialog.message(ex.getClass.getSimpleName) - } - } + + def save(success: => Unit = {}) { + try { + val filename = DECKS_PATH + "deck" + decks.indexOf(nowDeck) + ".xml" + nowDeck.entry().saveXML(filename) + success + } catch { + case _: NoSuchChampionException => + println(nowDeck) + dialog.message(t("NoSuchChampionException")) + case _: OverCostException => + dialog.message(t("OverCostException")) + case ex => + ex.printStackTrace(Console.err) + dialog.message(ex.getClass.getSimpleName) + } } - + def clear() { dialog.confirm(nowDeckName + " " + t("confirm.clear")) { nowDeck.clear() diff --git a/processing2D/DeckSelectScene.scala b/processing2D/DeckSelectScene.scala index aa77dfe..f0561a3 100644 --- a/processing2D/DeckSelectScene.scala +++ b/processing2D/DeckSelectScene.scala @@ -12,7 +12,7 @@ case class DeckSelectScene( menuBtnMgr, List( ('entry, t("entry"), entry _), - ('save, t("save"), save _), + ('save, t("clear"), clear _), ('back, t("back"), back _) ) ) @@ -24,7 +24,15 @@ case class DeckSelectScene( ) val boardViewer: Option[Sprite] = game.board.map { - createBoardSprite(_, layout.rect('viewer)) + createBoardSprite( + _, + layout.rect('viewer), + (g, rect) => { + g.stroke(C5R, C5G, C5B) + g.noFill() + g.rect(0, 0, rect.width - 1, rect.height - 1) + } + ) } def back() { @@ -35,14 +43,17 @@ case class DeckSelectScene( def entry() { dialog.confirm(nowDeckName + " " + t("DeckSelectScene.entryMessage")) { + save { + val self = Option(Player(nowDeck)) + GameScene(game.copy(self = self)) + } } } override def draw() { - applet.background(C2) - + applet.background(C2) title.draw() - boardNameLabel.draw() + boardNameLabel.draw() boardViewer foreach { _.draw() } super.draw() } diff --git a/processing2D/GameScene.scala b/processing2D/GameScene.scala new file mode 100644 index 0000000..795fb36 --- /dev/null +++ b/processing2D/GameScene.scala @@ -0,0 +1,85 @@ +package com.github.alphaneet.suparobo + +case class GameScene( + game: Game +)(implicit + applet: SPApplet, + i18n: I18N +) extends Scene(applet) with MyUtil { +// implicit val layout = new LayoutXML(LAYOUTS_PATH + "BoardSelectScene.xml") + implicit val gg = new GraphicsGenerator(applet) + + val board = game.board.get // TK: ちょい適当 @ で直す + object boardViewer { + val width = applet.width + val height = width * (board.height / board.width) + + private var _scale = 1.0f + def scale = _scale + def scale_=(scale: Float) { + _scale = rangeOfNumber(scale, 0.375f, 1.0f) + val halfW = width >> 1 + val prevH = sprite.height + + sprite.width = (width * _scale).toInt + sprite.height = (height * _scale).toInt + + sprite.x = (halfW - _scale * halfW).toInt + y += (prevH - sprite.height) / 2 + } + + def y = sprite.y + def y_=(y: Int) { + sprite.y = rangeOfNumber(y, -sprite.height + applet.height, 0) + } + + val sprite: Sprite = createBoardSprite(board, new Rectangle(0, 0, width, height)) + + def draw() { + sprite.draw() + + applet.stroke(C5R, C5G, C5B) + applet.noFill() + + val w = sprite.width.toFloat / board.width + val h = sprite.height.toFloat / board.height + val (sx, ex) = (sprite.x, sprite.x + sprite.width) + val (sy, ey) = (sprite.y, sprite.y + sprite.height) + (0 to board.width) foreach { + i => + val x = sx + w * i + applet.line(x, sy, x, ey) + } + (0 to board.height) foreach { + i => + val y = sy + h * i + applet.line(sx, y, ex, y) + } + } + } + + var action: Action = readyAction + + trait Action extends NotNull { + action = this + def draw(): Unit + } + + def readyAction = new Action { + def draw() { + } + } + + override def draw() { + applet.background(C2) + boardViewer.draw() + } + + override def mouseWheelMoved() { + boardViewer.scale += applet.mouseWheelRotation.toFloat / 100 + } + + override def mouseDragged() { + boardViewer.y += (applet.mouseY - applet.pmouseY) + } +} diff --git a/processing2D/TitleScene.scala b/processing2D/TitleScene.scala index 13f4b0b..83a1ee8 100644 --- a/processing2D/TitleScene.scala +++ b/processing2D/TitleScene.scala @@ -27,7 +27,11 @@ case class TitleScene(implicit applet: SPApplet, i18n: I18N) extends Scene(apple size = 12 ) - def start() { BoardSelectScene() } + def start() { + val other = Option(Player(createDeck.random(champions, minions))) + BoardSelectScene(Game(other = other)) + } + def network() { println("未実装") } def deck() { DeckMakeScene() } def replay() { println("未実装") } diff --git a/processing2D/main.scala b/processing2D/main.scala index 8e7d1e8..39d3034 100644 --- a/processing2D/main.scala +++ b/processing2D/main.scala @@ -7,7 +7,18 @@ object Main extends SPApplet { frameRate(24) val i18n = createI18N("ja") title = i18n.t("title") - TitleScene()(this, i18n) +// TitleScene()(this, i18n) + + // TK: test + def create = Option(new Player(createDeck.random(champions, minions))) + GameScene( + Game( + self = create, + other = create, +// board = Option(new Board(10, 20)) + board = Option(Board.loadXML(BOARDS_PATH + "stage3.xml")) + ) + )(this, i18n) } } diff --git a/processing2D/package.scala b/processing2D/package.scala index 972f187..d10dc2a 100644 --- a/processing2D/package.scala +++ b/processing2D/package.scala @@ -12,7 +12,19 @@ package object suparobo extends processing.core.PConstants { val MAX_DECK = 3 val MAX_COST = 13 + def createDeck() = new Deck(MAX_COST) + + val champions: List[Champion] = Champion.loadChampions( + CHARACTERS_PATH + "championProfiles.xml", + CHARACTERS_PATH + "championParameters.xml" + ) + + val minions: List[Minion] = Minion.loadMinions( + CHARACTERS_PATH + "minionProfiles.xml", + CHARACTERS_PATH + "minionParameters.xml" + ) + // thanks for http://kuler.adobe.com/#themeID/1692819 @@ -51,6 +63,7 @@ package object suparobo extends processing.core.PConstants { type Rectangle = java.awt.Rectangle type PImage = processing.core.PImage + type PGraphics = processing.core.PGraphics import com.github.alphaneet._ type SPApplet = scala_processing.SPApplet @@ -66,35 +79,27 @@ package object suparobo extends processing.core.PConstants { new I18N(locale, LOCALES_PATH + locale + ".xml") def t(name: String)(implicit i18n: I18N): String = i18n.t(name) - - object Sprite { - def empty()(implicit applet: SPApplet) = Sprite( - applet.createImage(0, 0, processing.core.PConstants.ARGB), - new Rectangle(0, 0, 0, 0) - ) - } // TK: scala-processing にいつか移行するかも? case class Sprite( - img: PImage, - rect: Rectangle + image: PImage, + var x: Int, + var y: Int, + var width: Int, + var height: Int ) extends NotNull { + def this(image: PImage, rect: Rectangle) = this( + image, rect.x, rect.y, rect.width, rect.height + ) + def this( - img: PImage, - x: Int, - y: Int, - width: Int, - height: Int - ) = this(img, new Rectangle(x, y, width, height)) - - def this( - img: PImage, + image: PImage, x: Int, y: Int - ) = this(img, new Rectangle(x, y, img.width, img.height)) + ) = this(image, x, y, image.width, image.height) def draw()(implicit applet: SPApplet) { - applet.image(img, rect.x, rect.y, rect.width, rect.height) + applet.image(image, x, y, width, height) } } @@ -125,7 +130,7 @@ package object suparobo extends processing.core.PConstants { width: Int, height: Int, size: Int = 18 - )( implicit gg: GraphicsGenerator): List[PImage] = { + )(implicit gg: GraphicsGenerator): List[PImage] = { List(C2, C1, C3).map { gg.createLabel(text, width, height, size, _, C5) } @@ -133,20 +138,23 @@ package object suparobo extends processing.core.PConstants { def createBoardSprite( board: Board, - rect: Rectangle + rect: Rectangle, + draw: (PGraphics, Rectangle) => Unit = (_, _) => {} )(implicit gg: GraphicsGenerator): Sprite = { val w = rect.width.toFloat / board.width val h = rect.height.toFloat / board.height - val image = gg.createAndDrawPImage(rect.width + 1, rect.height + 1) { + val image = gg.createAndDrawPImage(rect.width, rect.height) { g => + g.noStroke() board foreach { case (pos, status) => val (red, green, blue) = gg.rgb(BoardValueColors(status)) g.fill(red, green, blue) g.rect(pos.x * w, pos.y * h, w, h) } + draw(g, rect) } - Sprite(image, rect) + new Sprite(image, rect) } def registerButtons(