From a4e847e6a1feff79cce5d10798e9296463f198cd Mon Sep 17 00:00:00 2001 From: soywiz Date: Sat, 7 Oct 2017 17:35:15 +0200 Subject: [PATCH] Refactor tic-tac-toe --- build.gradle | 53 +++++++ korge-tic-tac-toe/common/.gitignore | 7 + korge-tic-tac-toe/{ => common}/build.gradle | 21 ++- korge-tic-tac-toe/common/settings.gradle | 1 + .../common/src/generated/resources/main.ani | Bin 0 -> 1075 bytes .../src/generated/resources/main.ani.0.png | Bin 0 -> 46818 bytes .../src/generated/resources/main.ani.meta | 1 + .../com/soywiz/korge/tictactoe/Board.kt | 64 ++++++++ .../soywiz/korge/tictactoe/BoardMediator.kt | 92 +++++++++++ .../com/soywiz/korge/tictactoe/InjectExt.kt | 10 ++ .../com/soywiz/korge/tictactoe/TicTacToe.kt | 146 ++++++++++++++++++ .../{ => common/src/main}/resources/icon.png | Bin .../src/main}/resources/index.html | 0 .../{ => common/src/main}/resources/main.fla | Bin .../{ => common/src/main}/resources/main.swf | Bin .../src/main}/resources/main.swf.config | 16 +- .../com/soywiz/korge/tictactoe/BoardTest.kt | 0 korge-tic-tac-toe/js/.gitignore | 7 + korge-tic-tac-toe/js/build.gradle | 46 ++++++ korge-tic-tac-toe/js/settings.gradle | 1 + korge-tic-tac-toe/jvm/.gitignore | 7 + korge-tic-tac-toe/jvm/build.gradle | 18 +++ korge-tic-tac-toe/jvm/settings.gradle | 1 + settings.gradle | 5 +- 24 files changed, 481 insertions(+), 15 deletions(-) create mode 100644 korge-tic-tac-toe/common/.gitignore rename korge-tic-tac-toe/{ => common}/build.gradle (79%) create mode 100644 korge-tic-tac-toe/common/settings.gradle create mode 100644 korge-tic-tac-toe/common/src/generated/resources/main.ani create mode 100644 korge-tic-tac-toe/common/src/generated/resources/main.ani.0.png create mode 100644 korge-tic-tac-toe/common/src/generated/resources/main.ani.meta create mode 100644 korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/Board.kt create mode 100644 korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/BoardMediator.kt create mode 100644 korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/InjectExt.kt create mode 100644 korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/TicTacToe.kt rename korge-tic-tac-toe/{ => common/src/main}/resources/icon.png (100%) rename korge-tic-tac-toe/{ => common/src/main}/resources/index.html (100%) rename korge-tic-tac-toe/{ => common/src/main}/resources/main.fla (100%) rename korge-tic-tac-toe/{ => common/src/main}/resources/main.swf (100%) rename korge-tic-tac-toe/{ => common/src/main}/resources/main.swf.config (95%) rename korge-tic-tac-toe/{test => common/src/test/kotlin}/com/soywiz/korge/tictactoe/BoardTest.kt (100%) create mode 100644 korge-tic-tac-toe/js/.gitignore create mode 100644 korge-tic-tac-toe/js/build.gradle create mode 100644 korge-tic-tac-toe/js/settings.gradle create mode 100644 korge-tic-tac-toe/jvm/.gitignore create mode 100644 korge-tic-tac-toe/jvm/build.gradle create mode 100644 korge-tic-tac-toe/jvm/settings.gradle diff --git a/build.gradle b/build.gradle index 48b347f..ea703d8 100644 --- a/build.gradle +++ b/build.gradle @@ -8,6 +8,20 @@ buildscript { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" classpath "com.soywiz:korge-gradle-plugin:$korVersion" } + + ext { + libraries = [ + kotlin_stdlib_common: "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlinVersion", + kotlin_stdlib_jvm : "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion", + kotlin_stdlib_js : "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlinVersion", + + kotlin_test_common : "org.jetbrains.kotlin:kotlin-test-common:$kotlinVersion", + kotlin_test_jvm : "org.jetbrains.kotlin:kotlin-test:$kotlinVersion", + kotlin_test_js : "org.jetbrains.kotlin:kotlin-test-js:$kotlinVersion", + + kotlin_reflect : "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion", + ] + } } configurations { @@ -25,5 +39,44 @@ allprojects { maven { url 'http://dl.bintray.com/kotlin/kotlin-eap-1.2' } mavenCentral() } + + it.afterEvaluate { + if (it.plugins.hasPlugin("kotlin-platform-common")) { + dependencies { + compile libraries.kotlin_stdlib_common + testCompile libraries.kotlin_test_common + } + + kotlin { + experimental { coroutines 'enable' } + } + } + if (it.plugins.hasPlugin("kotlin-platform-jvm") || it.plugins.hasPlugin("kotlin")) { + dependencies { + compile libraries.kotlin_stdlib_jvm + testCompile libraries.kotlin_test_jvm + testCompile "junit:junit:4.12" + } + + kotlin { + experimental { coroutines 'enable' } + } + } + if (it.plugins.hasPlugin("kotlin-platform-js") || it.plugins.hasPlugin("kotlin2js")) { + dependencies { + compile libraries.kotlin_stdlib_js + testCompile libraries.kotlin_test_js + } + + kotlin { + experimental { coroutines 'enable' } + } + + compileKotlin2Js { + kotlinOptions.moduleKind = "umd" + kotlinOptions.sourceMap = true + } + } + } } diff --git a/korge-tic-tac-toe/common/.gitignore b/korge-tic-tac-toe/common/.gitignore new file mode 100644 index 0000000..d88dafb --- /dev/null +++ b/korge-tic-tac-toe/common/.gitignore @@ -0,0 +1,7 @@ +/.idea +/.gradle +/build +/classes +/out +/genresources +/web diff --git a/korge-tic-tac-toe/build.gradle b/korge-tic-tac-toe/common/build.gradle similarity index 79% rename from korge-tic-tac-toe/build.gradle rename to korge-tic-tac-toe/common/build.gradle index 40bc0df..489f77c 100644 --- a/korge-tic-tac-toe/build.gradle +++ b/korge-tic-tac-toe/common/build.gradle @@ -1,10 +1,15 @@ -apply from: "../include_js.gradle" - -apply plugin: 'kotlin2js' +apply plugin: 'kotlin-platform-common' //apply plugin: 'application' //mainClassName = "com.soywiz.korge.tictactoe.TicTacToe" +sourceSets { + //generated.resources.srcDirs = ['src/generated/resources'] + //main.resources.srcDirs = [ 'src/main/resources' ] + main.resources.srcDirs = [ 'src/main/resources', 'src/generated/resources' ] +} + +/* sourceSets { generated.resources.srcDirs = [ 'genresources' ] @@ -12,17 +17,20 @@ sourceSets { main.resources.srcDirs = [ 'resources', 'genresources' ] test.kotlin.srcDirs = [ 'test' ] } +*/ dependencies { - compile "com.soywiz:korge-js:$korVersion" - compile "com.soywiz:korge-ext-swf-js:$korVersion" - compile "com.soywiz:korau-mp3-js:$korVersion" + compile "com.soywiz:korge-common:$korVersion" + compile "com.soywiz:korge-ext-swf-common:$korVersion" + compile "com.soywiz:korau-mp3-common:$korVersion" + testCompile "com.soywiz:korge-tests-common:$korVersion" //compile "com.soywiz:korge:$korVersion" //compile "com.soywiz:korge-ext-swf:$korVersion" //compile "com.soywiz:korau-mp3:$korVersion" } +/* compileKotlin2Js { kotlinOptions.outputFile = "${projectDir}/web/output.js" //kotlinOptions.moduleKind = "amd" @@ -58,6 +66,7 @@ compileKotlin2Js.doLast { } jar.enabled = false +*/ //distTar.enabled = false //distZip.enabled = false diff --git a/korge-tic-tac-toe/common/settings.gradle b/korge-tic-tac-toe/common/settings.gradle new file mode 100644 index 0000000..6fae12c --- /dev/null +++ b/korge-tic-tac-toe/common/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'korge-tic-tac-toe-common' diff --git a/korge-tic-tac-toe/common/src/generated/resources/main.ani b/korge-tic-tac-toe/common/src/generated/resources/main.ani new file mode 100644 index 0000000000000000000000000000000000000000..9064af1f727e00d712a65619b005ef7a59888ee3 GIT binary patch literal 1075 zcma)5O-$2Z7=FL+YuAqbDg+ZxvvAn~=pY!uZD2J`V^L_w>W zkW|eqYqpe(=Pa`v$tkLqkf!y5R*Fn%bCI-FP)sRO(w`tba#4z?mSNcmsYk|>%SjPK zD`R-3sHnP`Pe^jVEK8Axnr${6gJ%;pTG{~8L*4)dyQ zl}emxnHsMZisi>bx}mk?zl)BJlu6yxy4q2h_iqa`sA4EP6l{}eYc3lj5P}d77f4j_ zK=TRu<|W&jlSU<3svLvZNiZl?$eRsH2oUhX$jdc~@8QI52qAIdui|1DAsusUFV-mC zeoa1)BE#Cu#w)TggA6Ax^e%T1z-*^^y}VrOT}__O*-_|0|Ghk=Zg#dfK5+#&t}0eV zfZAYf5Ge3KNYrVl)fWLb;0RAh1P-Y8LtpCSCfV%egFG-2MF;LUAO#G(KYk0VhkQet zk9g#j{^emejR%;#@@@>cCGk>KtkXJO=RZ9F0a*Ul7Shkd2iyS%u%FmZfavNGj?=gG zc*CfbW{3zBwL+t*)+Gw^GyfMKaLA)H)Zqu{0M>H@OI%+Pci0ZAch|eu`_}uw*W&kl zfARhfEWj$X!|`ZkCeXe)BWjlAnU77# z%Q3ZaO;HB&*KSP-PfvN)@%v;`2(&f=0X4f literal 0 HcmV?d00001 diff --git a/korge-tic-tac-toe/common/src/generated/resources/main.ani.0.png b/korge-tic-tac-toe/common/src/generated/resources/main.ani.0.png new file mode 100644 index 0000000000000000000000000000000000000000..5b24934c105a98ace0e383dc50be62a6b5903993 GIT binary patch literal 46818 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%0DZFOSF)C-YNjTmgtt&0%Wu;R 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 literal 0 HcmV?d00001 diff --git a/korge-tic-tac-toe/common/src/generated/resources/main.ani.meta b/korge-tic-tac-toe/common/src/generated/resources/main.ani.meta new file mode 100644 index 0000000..7f774be --- /dev/null +++ b/korge-tic-tac-toe/common/src/generated/resources/main.ani.meta @@ -0,0 +1 @@ +{"name":"main.swf","loaderVersion":16,"sha1":"516c0fac4fbcac08b7740d2cabcc718d08c6fab4","configSha1":"3c38f2d222663a800a900cf37498c8ff3b43e9fb"} \ No newline at end of file diff --git a/korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/Board.kt b/korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/Board.kt new file mode 100644 index 0000000..b749c38 --- /dev/null +++ b/korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/Board.kt @@ -0,0 +1,64 @@ +package com.soywiz.korge.tictactoe + +import com.soywiz.korio.util.Extra +import com.soywiz.korma.ds.Array2 +import com.soywiz.korma.geom.PointInt +import kotlin.collections.ArrayList + +enum class Chip { EMPTY, CROSS, CIRCLE } + +class Board(val width: Int = 3, val height: Int = width, val lineSize: Int = width) { + class Cell(val x: Int, val y: Int) : Extra by Extra.Mixin() { + val pos = PointInt(x, y) + var value = Chip.EMPTY + } + + val cells = Array2(width, height) { Cell(it % width, it / width) } + + fun inside(x: Int, y: Int) = cells.inside(x, y) + + fun select(x: Int, y: Int, dx: Int, dy: Int, size: Int): List? { + if (!inside(x, y)) return null + if (!inside(x + dx * (size - 1), y + dy * (size - 1))) return null + return (0 until size).map { cells[x + dx * it, y + dy * it] } + } + + val lines = kotlin.collections.ArrayList>() + + init { + fun addLine(line: List?) { + if (line != null) lines += line + } + for (y in 0..height) { + for (x in 0..width) { + addLine(select(x, y, 1, 0, lineSize)) + addLine(select(x, y, 0, 1, lineSize)) + addLine(select(x, y, 1, 1, lineSize)) + addLine(select(width - x - 1, y, -1, 1, lineSize)) + } + } + } + + operator fun get(x: Int, y: Int) = cells[x, y] + operator fun set(x: Int, y: Int, value: Chip) = run { cells[x, y].value = value } + + val Iterable.chipLine: Chip? + get() { + val expected = this.first().value + return if (expected == Chip.EMPTY) null else if (this.all { it.value == expected }) expected else null + } + + val moreMovements: Boolean get() = cells.any { it.value == Chip.EMPTY } + + val winnerLine: List? + get() { + val out = kotlin.collections.ArrayList() + for (line in lines) if (line.chipLine != null) out += line + return if (out.isEmpty()) null else out.toSet().toList() + } + + val winner: Chip? + get() { + return winnerLine?.firstOrNull()?.value + } +} diff --git a/korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/BoardMediator.kt b/korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/BoardMediator.kt new file mode 100644 index 0000000..5f52d53 --- /dev/null +++ b/korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/BoardMediator.kt @@ -0,0 +1,92 @@ +package com.soywiz.korge.tictactoe + +import com.soywiz.korge.animate.play +import com.soywiz.korge.input.onClick +import com.soywiz.korge.time.milliseconds +import com.soywiz.korge.tween.* +import com.soywiz.korge.view.View +import com.soywiz.korge.view.get +import com.soywiz.korio.async.Signal +import com.soywiz.korio.async.async +import com.soywiz.korio.util.Extra + +var Board.Cell.view by Extra.Property { null } +val Board.Cell.vview: View get() = this.view!! +val Board.Cell.onPress by Extra.Property { Signal() } + +fun Board.Cell.set(type: Chip) { + this.value = type + view["chip"].play(when (type) { + Chip.EMPTY -> "empty" + Chip.CIRCLE -> "circle" + Chip.CROSS -> "cross" + }) +} + +suspend fun Board.Cell.setAnimate(type: Chip) { + set(type) + async { + view.tween( + (view["chip"]!!::alpha[0.7, 1.0]).linear(), + (view["chip"]!!::scale[0.8, 1.0]).easeOutElastic(), + time = 300.milliseconds + ) + } +} + +var Board.Cell.highlighting by Extra.Property { false } + +suspend fun Board.Cell.highlight(highlight: Boolean) { + view["highlight"].play(if (highlight) "highlight" else "none") + this.highlighting = highlight + if (highlight) { + async { + + val hl = view["highlight"]!! + while (highlighting) { + hl.tween((hl::alpha[0.7]).easeInOutQuad(), time = 300.milliseconds) + hl.tween((hl::alpha[1.0]).easeInOutQuad(), time = 200.milliseconds) + } + } + + async { + val ch = view["chip"]!! + ch.tween((ch::scale[0.4]).easeOutQuad(), time = 100.milliseconds) + ch.tween((ch::scale[1.2]).easeOutElastic(), time = 300.milliseconds) + while (highlighting) { + ch.tween((ch::scale[1.0]).easeOutQuad(), time = 300.milliseconds) + ch.tween((ch::scale[1.2]).easeOutElastic(), time = 300.milliseconds) + } + } + } +} + +suspend fun Board.Cell.lowlight(lowlight: Boolean) { + async { + view.tween( + view!!::scale[1.0, 0.7], + view!!::alpha[0.3], + time = 300.milliseconds, easing = Easings.EASE_OUT_QUAD + ) + } +} + +suspend fun Board.reset() { + for (cell in cells) { + //cell.view?.removeAllComponents() + cell.set(Chip.EMPTY) + cell.highlight(false) + cell.view?.scale = 1.0 + cell.view?.alpha = 1.0 + cell.view["chip"]?.scale = 1.0 + cell.view["chip"]?.alpha = 1.0 + } +} + +fun Board.Cell.init(view: View) { + this.view = view + set(this.value) + view["hit"].onClick { + onPress(Unit) + } +} diff --git a/korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/InjectExt.kt b/korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/InjectExt.kt new file mode 100644 index 0000000..e7ec889 --- /dev/null +++ b/korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/InjectExt.kt @@ -0,0 +1,10 @@ +package com.soywiz.korge.tictactoe + +import com.soywiz.korge.animate.AnLibrary +import com.soywiz.korge.resources.getPath +import com.soywiz.korio.inject.AsyncInjector + +// AUTOGENERATED: +fun AsyncInjector.generatedInject() = this + //.mapPrototype { TicTacToeMainScene(getPath("main.ani")) } // @TODO: kotlin.js bug + .mapPrototype { TicTacToeMainScene(getPath(AnLibrary::class, "main.ani")) } diff --git a/korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/TicTacToe.kt b/korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/TicTacToe.kt new file mode 100644 index 0000000..cad2b08 --- /dev/null +++ b/korge-tic-tac-toe/common/src/main/kotlin/com/soywiz/korge/tictactoe/TicTacToe.kt @@ -0,0 +1,146 @@ +package com.soywiz.korge.tictactoe + +import com.soywiz.korge.Korge +import com.soywiz.korge.animate.AnLibrary +import com.soywiz.korge.animate.AnLibraryPlugin +import com.soywiz.korge.input.mouse +import com.soywiz.korge.plugin.KorgePlugin +import com.soywiz.korge.resources.Path +import com.soywiz.korge.scene.Module +import com.soywiz.korge.scene.Scene +import com.soywiz.korge.view.Container +import com.soywiz.korge.view.descendantsWithPropInt +import com.soywiz.korge.view.get +import com.soywiz.korge.view.setText +import com.soywiz.korio.async.Signal +import com.soywiz.korio.async.go +import com.soywiz.korio.async.waitOne +import com.soywiz.korio.error.invalidOp +import com.soywiz.korio.inject.AsyncInjector +import com.soywiz.korio.lang.JvmStatic +import com.soywiz.korma.geom.PointInt + +object TicTacToe { + @JvmStatic + fun main(args: Array) = Korge(TicTacToeModule, injector = AsyncInjector().generatedInject()) +} + +object TicTacToeModule : Module() { + override val mainScene = TicTacToeMainScene::class + override val title: String = "tic-tac-toe" + override val icon: String = "icon.png" + override val plugins: List = super.plugins + listOf( + AnLibraryPlugin + ) + + suspend override fun init(injector: AsyncInjector) { + //injector.get().mapExtensions("swf" to "ani") + //injector.get().mapExtensionsJustInJTransc("swf" to "ani") + } +} + +// Controller +class TicTacToeMainScene( + @Path("main.ani") val mainLibrary: AnLibrary +) : Scene() { + val board = Board(3, 3) + lateinit var game: Game + + suspend override fun sceneInit(sceneView: Container) { + sceneView += mainLibrary.createMainTimeLine() + + for ((rowView, row) in sceneView.descendantsWithPropInt("row")) { + for ((cellView, cell) in rowView.descendantsWithPropInt("cell")) { + board.cells[row, cell].init(cellView) + } + } + + val p1 = InteractivePlayer(board, Chip.CROSS) + val p2 = BotPlayer(board, Chip.CIRCLE) + //val p2 = InteractivePlayer(board, Chip.CIRCLE) + + game = Game(board, listOf(p1, p2)) + cancellables += go { + while (true) { + game.board.reset() + val result = game.game() + + println(result) + + val results = mainLibrary.createMovieClip("Results") + //(results["result"] as AnTextField).format?.face = Html.FontFace.Bitmap(font) + when (result) { + is Game.Result.DRAW -> results["result"].setText("DRAW") + is Game.Result.WIN -> { + results["result"].setText("WIN") + for (cell in result.cells) cell.highlight(true) + for (cell in game.board.cells.toList() - result.cells) cell.lowlight(true) + } + } + sceneView += results + results["hit"]?.mouse?.onClick?.waitOne() + //sceneView -= results + results.removeFromParent() + + } + } + } +} + +interface Player { + val chip: Chip + suspend fun move(): PointInt +} + +class Game(val board: Board, val players: List) { + interface Result { + object DRAW : Result + class WIN(val player: Player?, val cells: List) : Result + } + + suspend fun game(): Result { + var turn = 0 + while (board.moreMovements) { + val currentPlayer = players[turn % players.size] + while (true) { + val pos = currentPlayer.move() + println(pos) + if (board.cells[pos].value == Chip.EMPTY) { + board.cells[pos].setAnimate(currentPlayer.chip) + break + } + } + if (board.winner != null) return Result.WIN(currentPlayer, board.winnerLine ?: listOf()) + turn++ + } + return Result.DRAW + } +} + +class BotPlayer(val board: Board, override val chip: Chip) : Player { + suspend override fun move(): PointInt { + for (cell in board.cells) { + if (cell.value == Chip.EMPTY) { + return cell.pos + } + } + invalidOp("No more movements") + } +} + +class InteractivePlayer(val board: Board, override val chip: Chip) : Player { + val clicked = Signal() + + init { + for (cell in board.cells) { + cell.onPress { + clicked(cell.pos) + } + } + } + + suspend override fun move(): PointInt { + return clicked.waitOne() + } + +} diff --git a/korge-tic-tac-toe/resources/icon.png b/korge-tic-tac-toe/common/src/main/resources/icon.png similarity index 100% rename from korge-tic-tac-toe/resources/icon.png rename to korge-tic-tac-toe/common/src/main/resources/icon.png diff --git a/korge-tic-tac-toe/resources/index.html b/korge-tic-tac-toe/common/src/main/resources/index.html similarity index 100% rename from korge-tic-tac-toe/resources/index.html rename to korge-tic-tac-toe/common/src/main/resources/index.html diff --git a/korge-tic-tac-toe/resources/main.fla b/korge-tic-tac-toe/common/src/main/resources/main.fla similarity index 100% rename from korge-tic-tac-toe/resources/main.fla rename to korge-tic-tac-toe/common/src/main/resources/main.fla diff --git a/korge-tic-tac-toe/resources/main.swf b/korge-tic-tac-toe/common/src/main/resources/main.swf similarity index 100% rename from korge-tic-tac-toe/resources/main.swf rename to korge-tic-tac-toe/common/src/main/resources/main.swf diff --git a/korge-tic-tac-toe/resources/main.swf.config b/korge-tic-tac-toe/common/src/main/resources/main.swf.config similarity index 95% rename from korge-tic-tac-toe/resources/main.swf.config rename to korge-tic-tac-toe/common/src/main/resources/main.swf.config index 1a86a20..5821822 100644 --- a/korge-tic-tac-toe/resources/main.swf.config +++ b/korge-tic-tac-toe/common/src/main/resources/main.swf.config @@ -1,9 +1,9 @@ -mipmaps: true -antialiasing: true -rasterizerMethod: X4 -exportScale: 2.0 -minShapeSide: 64 -maxShapeSide: 512 -minMorphShapeSide: 16 -maxMorphShapeSide: 128 +mipmaps: true +antialiasing: true +rasterizerMethod: X4 +exportScale: 2.0 +minShapeSide: 64 +maxShapeSide: 512 +minMorphShapeSide: 16 +maxMorphShapeSide: 128 exportPaths: false \ No newline at end of file diff --git a/korge-tic-tac-toe/test/com/soywiz/korge/tictactoe/BoardTest.kt b/korge-tic-tac-toe/common/src/test/kotlin/com/soywiz/korge/tictactoe/BoardTest.kt similarity index 100% rename from korge-tic-tac-toe/test/com/soywiz/korge/tictactoe/BoardTest.kt rename to korge-tic-tac-toe/common/src/test/kotlin/com/soywiz/korge/tictactoe/BoardTest.kt diff --git a/korge-tic-tac-toe/js/.gitignore b/korge-tic-tac-toe/js/.gitignore new file mode 100644 index 0000000..d88dafb --- /dev/null +++ b/korge-tic-tac-toe/js/.gitignore @@ -0,0 +1,7 @@ +/.idea +/.gradle +/build +/classes +/out +/genresources +/web diff --git a/korge-tic-tac-toe/js/build.gradle b/korge-tic-tac-toe/js/build.gradle new file mode 100644 index 0000000..aaa1510 --- /dev/null +++ b/korge-tic-tac-toe/js/build.gradle @@ -0,0 +1,46 @@ +apply plugin: 'kotlin-platform-js' + +sourceSets { + main.resources.srcDirs = [ '../common/src/main/resources', '../common/src/generated/resources' ] +} + +dependencies { + implement project(":korge-tic-tac-toe:common") + + compile "com.soywiz:korge-js:$korVersion" + compile "com.soywiz:korge-ext-swf-js:$korVersion" + compile "com.soywiz:korau-mp3-js:$korVersion" + testCompile "com.soywiz:korge-tests-js:$korVersion" +} + +compileKotlin2Js { + kotlinOptions.outputFile = "${projectDir}/web/output.js" + kotlinOptions.sourceMap = false +} + + +clean { + delete new File("${projectDir}/web") +} + +compileKotlin2Js.doLast { + configurations.compile.each { File file -> + copy { + includeEmptyDirs = false + + from zipTree(file.absolutePath) + into "${projectDir}/web" + include { fileTreeElement -> + def path = fileTreeElement.path + (path.endsWith(".js") || path.endsWith(".js.map")) && (path.startsWith("META-INF/resources/") || !path.startsWith("META-INF/")) + } + } + } + + copy { + from sourceSets.main.resources.srcDirs + into "${projectDir}/web" + } +} + +jar.enabled = false diff --git a/korge-tic-tac-toe/js/settings.gradle b/korge-tic-tac-toe/js/settings.gradle new file mode 100644 index 0000000..1578f51 --- /dev/null +++ b/korge-tic-tac-toe/js/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'korge-tic-tac-toe-js' diff --git a/korge-tic-tac-toe/jvm/.gitignore b/korge-tic-tac-toe/jvm/.gitignore new file mode 100644 index 0000000..d88dafb --- /dev/null +++ b/korge-tic-tac-toe/jvm/.gitignore @@ -0,0 +1,7 @@ +/.idea +/.gradle +/build +/classes +/out +/genresources +/web diff --git a/korge-tic-tac-toe/jvm/build.gradle b/korge-tic-tac-toe/jvm/build.gradle new file mode 100644 index 0000000..cc74a08 --- /dev/null +++ b/korge-tic-tac-toe/jvm/build.gradle @@ -0,0 +1,18 @@ +apply plugin: 'kotlin-platform-jvm' + +apply plugin: 'application' + +mainClassName = 'com.soywiz.korge.tictactoe.TicTacToe' + +sourceSets { + main.resources.srcDirs = [ '../common/src/main/resources', '../common/src/generated/resources' ] +} + +dependencies { + implement project(":korge-tic-tac-toe:common") + + compile "com.soywiz:korge:$korVersion" + compile "com.soywiz:korge-ext-swf:$korVersion" + compile "com.soywiz:korau-mp3:$korVersion" + testCompile "com.soywiz:korge-tests:$korVersion" +} diff --git a/korge-tic-tac-toe/jvm/settings.gradle b/korge-tic-tac-toe/jvm/settings.gradle new file mode 100644 index 0000000..57aa17e --- /dev/null +++ b/korge-tic-tac-toe/jvm/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'korge-tic-tac-toe' diff --git a/settings.gradle b/settings.gradle index be7b5ca..095004b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,10 @@ rootProject.name = 'korge-samples' include( - 'korge-tic-tac-toe', + 'korge-tic-tac-toe:common', + 'korge-tic-tac-toe:js', + 'korge-tic-tac-toe:jvm', + //'korge-coffee', //'korge-simon', )