diff --git a/animations/src/commonMain/kotlin/main.kt b/animations/src/commonMain/kotlin/main.kt index c07422e..65c8b8a 100644 --- a/animations/src/commonMain/kotlin/main.kt +++ b/animations/src/commonMain/kotlin/main.kt @@ -1,6 +1,5 @@ import com.soywiz.klock.* import com.soywiz.korge.* -import com.soywiz.korge.tween.* import com.soywiz.korge.view.* import com.soywiz.korim.color.* import com.soywiz.korge.animate.* @@ -27,14 +26,14 @@ suspend fun main() = Korge(width = 512, height = 512, virtualWidth = 512, virtua wait() parallel { //rect1.moveTo(0, 150) - rect1.moveToWithSpeed(512 - 100, 0) - rect2.moveToWithSpeed(0, 512 - 100 - 100) + rect1.moveToWithSpeed(512.0 - 100, 0.0) + rect2.moveToWithSpeed(0.0, 512.0 - 100 - 100) //rect1.moveTo(0, height - 100) } parallel { //rect1.moveTo(0, 150) - rect1.moveTo(512 - 100, 512 - 100) - rect2.moveTo(512 - 100, 512 - 100) + rect1.moveTo(512.0 - 100, 512.0 - 100) + rect2.moveTo(512.0 - 100, 512.0 - 100) //rect1.moveTo(0, height - 100) } parallel(time = 1.seconds) { diff --git a/asteroids/src/commonMain/kotlin/main.kt b/asteroids/src/commonMain/kotlin/main.kt index 3c50a06..2119e8e 100644 --- a/asteroids/src/commonMain/kotlin/main.kt +++ b/asteroids/src/commonMain/kotlin/main.kt @@ -1,7 +1,6 @@ import com.soywiz.kds.* import com.soywiz.klock.* -import com.soywiz.klock.hr.hrMicroseconds -import com.soywiz.klock.hr.hrMilliseconds +import com.soywiz.klock.hr.* import com.soywiz.korev.* import com.soywiz.korge.* import com.soywiz.korge.view.* @@ -89,7 +88,7 @@ suspend fun main() = Korge( // bullet.delayFrame() // } //} - bullet.addUpdater { bulletFrame(it) } + bullet.addUpdater { bulletFrame(it) } } } @@ -98,6 +97,7 @@ suspend fun main() = Korge( class Asteroid(val assets: Assets, val asteroidSize: Int = 3) : Image(assets.asteroidBitmap) { var angle = 30.degrees + init { anchor(.5, .5) scale = asteroidSize.toDouble() / 3.0 @@ -144,8 +144,6 @@ fun View.advance(amount: Double, rot: Angle = (-90).degrees) = this.apply { y += (this.rotation + rot).sine * amount } -inline fun View.advance(amount: Number, rot: Angle = (-90).degrees) = advance(amount.toDouble(), rot) - class Assets(val views: Views, val shipSize: Int = 24) { val asteroidSize = shipSize * 2 val shipBitmap = NativeImage(shipSize, shipSize).context2d { @@ -164,8 +162,8 @@ class Assets(val views: Views, val shipSize: Int = 24) { lineWidth = 1.0 lineCap = LineCap.ROUND stroke(Colors.WHITE) { - moveTo(width / 2, 0) - lineToV(height) + moveTo(width / 2.0, 0.0) + lineToV(height.toDouble()) } } val asteroidBitmap = Bitmap32(asteroidSize, asteroidSize).context2d { // Let's use software vector rendering here, for testing purposes diff --git a/atlas/src/commonMain/kotlin/main.kt b/atlas/src/commonMain/kotlin/main.kt index 2f4b727..f676b52 100644 --- a/atlas/src/commonMain/kotlin/main.kt +++ b/atlas/src/commonMain/kotlin/main.kt @@ -1,8 +1,6 @@ import com.soywiz.korge.* import com.soywiz.korge.atlas.* import com.soywiz.korge.view.* -import com.soywiz.korio.* -import com.soywiz.korio.dynamic.* import com.soywiz.korio.file.std.* suspend fun main() = Korge(width = 640, height = 480, virtualWidth = 320, virtualHeight = 240) { @@ -10,7 +8,7 @@ suspend fun main() = Korge(width = 640, height = 480, virtualWidth = 320, virtua } suspend fun Stage.atlasMain() { - val logos = resourcesVfs["logos.atlas.json"].readAtlas(views) + val logos = resourcesVfs["logos.atlas.json"].readAtlas() image(logos["korau.png"]).position(0, 0) image(logos["korim.png"]).position(64, 32) image(logos["korge.png"]).position(128, 64) diff --git a/bmpfont/src/commonMain/kotlin/main.kt b/bmpfont/src/commonMain/kotlin/main.kt index f82a787..642f6af 100644 --- a/bmpfont/src/commonMain/kotlin/main.kt +++ b/bmpfont/src/commonMain/kotlin/main.kt @@ -9,19 +9,22 @@ import com.soywiz.korio.file.std.* suspend fun main() = Korge(bgcolor = Colors["#333"]) { val font1 = resourcesVfs["font1.fnt"].readBitmapFont() - text("Hello World!", textSize = 128.0, font = font1) + val text1 = text("Hello World!", textSize = 96.0, font = font1) + val text2 = text("Hello World!", textSize = 96.0, font = font1) { + filtering = false + alignTopToBottomOf(text1) + } + val text3 = text("Hello World!", textSize = 96.0, font = font1) { + filter = Convolute3Filter(Convolute3Filter.KERNEL_GAUSSIAN_BLUR) + alignTopToBottomOf(text2) + } text("Hello World 2!", textSize = 32.0, font = font1) { val text = this - fun center() { - position(views.virtualWidth / 2 - width.toInt() / 2, views.virtualHeight / 2) - } - //filter = Convolute3Filter(Convolute3Filter.KERNEL_GAUSSIAN_BLUR) - center() launchImmediately { var n = 0 while (true) { text.text = "Hello World! ${n++}" - center() + centerOn(root) delay(1.milliseconds) } } diff --git a/box2d/src/commonMain/kotlin/Sample1.kt b/box2d/src/commonMain/kotlin/Sample1.kt index b0df290..6afc20e 100644 --- a/box2d/src/commonMain/kotlin/Sample1.kt +++ b/box2d/src/commonMain/kotlin/Sample1.kt @@ -20,7 +20,7 @@ suspend fun main() = Korge(quality = GameWindow.Quality.PERFORMANCE, title = "My println("STARTED!") - addUpdatable { + addUpdater { //println("FRAME!") } @@ -33,28 +33,16 @@ suspend fun main() = Korge(quality = GameWindow.Quality.PERFORMANCE, title = "My } views.clearColor = Colors.DARKGREEN - solidRect(300, 200, Colors.DARKCYAN) - sgraphics { - fill(Colors.DARKCYAN) { - rect(-1, -1, 3, 2) - } - fill(Colors.AQUAMARINE) { - circle(0, 0, 1) - } - fill(Colors.AQUAMARINE) { - circle(1, 0, 1) - } - position(100, 100) - }.scale(100, 100).interactive() + worldView { - position(400, 400).scale(20) + position(400, 400).scale(20.0) createBody { setPosition(0, -10) }.fixture { shape = BoxShape(100, 20) density = 0f - }.setViewWithContainer(solidRect(100, 20, Colors.RED).position(-50, -10).interactive()) + }.setView(solidRect(100, 20, Colors.RED).position(-50, -10).interactive()) // Dynamic Body createBody { @@ -64,7 +52,7 @@ suspend fun main() = Korge(quality = GameWindow.Quality.PERFORMANCE, title = "My shape = BoxShape(2f, 2f) density = 0.5f friction = 0.2f - }.setView(solidRect(2f, 2f, Colors.GREEN).anchor(.5, .5).interactive()) + }.setView(solidRect(2.0, 2.0, Colors.GREEN).anchor(.5, .5).interactive()) createBody { type = BodyType.DYNAMIC @@ -88,11 +76,11 @@ suspend fun main() = Korge(quality = GameWindow.Quality.PERFORMANCE, title = "My friction = 3f }.setView(sgraphics { fillStroke(ColorPaint(Colors.BLUE), ColorPaint(Colors.RED), Context2d.StrokeInfo(thickness = 0.3)) { - circle(0, 0, 2) + circle(0.0, 0.0, 2.0) //rect(0, 0, 400, 20) } fill(Colors.DARKCYAN) { - circle(1, 1, 0.2) + circle(1.0, 1.0, 0.2) } hitTestUsingShapes = true }.interactive()) @@ -100,7 +88,7 @@ suspend fun main() = Korge(quality = GameWindow.Quality.PERFORMANCE, title = "My image(resourcesVfs["korge.png"].readBitmap()) } -fun T.interactive(): T = this.apply { +fun T.interactive(): T = apply { alpha = 0.5 onOver { alpha = 1.0 } onOut { alpha = 0.5 } diff --git a/filters/src/commonMain/kotlin/main.kt b/filters/src/commonMain/kotlin/main.kt index 5bb96e7..9781fa1 100644 --- a/filters/src/commonMain/kotlin/main.kt +++ b/filters/src/commonMain/kotlin/main.kt @@ -1,29 +1,86 @@ import com.soywiz.klock.* import com.soywiz.korge.* +import com.soywiz.korge.animate.* import com.soywiz.korge.tween.* import com.soywiz.korge.view.* import com.soywiz.korge.view.filter.* import com.soywiz.korim.color.* import com.soywiz.korim.format.* import com.soywiz.korio.file.std.* -import com.soywiz.korma.geom.* import com.soywiz.korma.interpolation.* -suspend fun main() = Korge(width = 512, height = 512, bgcolor = Colors["#2b2b2b"]) { - val minDegrees = (-16).degrees - val maxDegrees = (+16).degrees +suspend fun main() = Korge(width = 768, height = 512, bgcolor = Colors["#2b2b2b"]) { + val bitmap = resourcesVfs["korge.png"].readBitmap() val wave = WaveFilter() - val image = image(resourcesVfs["korge.png"].readBitmap()) { - rotation = maxDegrees - anchor(.5, .5) - scale(.8) - position(256, 256) + image(bitmap) { + scale(.5) + position(0, 0) filter = wave } - while (true) { - image.tween(image::rotation[minDegrees], wave::time[1.seconds], time = 1.seconds, easing = Easing.EASE_IN_OUT) - image.tween(image::rotation[maxDegrees], wave::time[0.seconds], time = 1.seconds, easing = Easing.EASE_IN_OUT) + val blur = BlurFilter() + image(bitmap) { + scale(.5) + position(256, 0) + filter = blur + } + + val color = ColorMatrixFilter(ColorMatrixFilter.GRAYSCALE_MATRIX) + image(bitmap) { + scale(.5) + position(512, 0) + filter = color + } + + val page = PageFilter() + image(bitmap) { + scale(.5) + position(0, 256) + filter = page + } + + val conImg = image(bitmap) { + scale(.5) + position(256, 256) + filter = Convolute3Filter(Convolute3Filter.KERNEL_SHARPEN) + } + + val swizzle = SwizzleColorsFilter() + image(bitmap) { + scale(.5) + position(512, 256) + filter = swizzle + } + + animateParallel { + sequence(looped = true) { + tween(wave::time[1.seconds], time = 1.seconds, easing = Easing.EASE_IN_OUT) + tween(wave::time[0.seconds], time = 1.seconds, easing = Easing.EASE_IN_OUT) + } + sequence(looped = true) { + tween(blur::radius[16], time = 1.seconds, easing = Easing.EASE_IN_OUT) + tween(blur::radius[0], time = 1.seconds, easing = Easing.EASE_IN_OUT) + } + sequence(looped = true) { + tween(color::blendRatio[0], time = 1.seconds, easing = Easing.EASE_IN_OUT) + tween(color::blendRatio[1], time = 1.seconds, easing = Easing.EASE_IN_OUT) + } + sequence(looped = true) { + tween(page::hratio[0], time = 1.seconds, easing = Easing.EASE_IN_OUT) + tween(page::hratio[1], time = 1.seconds, easing = Easing.EASE_IN_OUT) + } + sequence(looped = true) { + block { conImg.filter = Convolute3Filter(Convolute3Filter.KERNEL_SHARPEN) } + wait(1.seconds) + block { conImg.filter = Convolute3Filter(Convolute3Filter.KERNEL_IDENTITY) } + wait(1.seconds) + } + sequence(looped = true) { + arrayOf("rgga", "bgga", "bgba", "grba", "gbba", "gbga", "bbga").forEach { + block { swizzle.swizzle = it } + wait(0.5.seconds) + } + } } } diff --git a/gradle.properties b/gradle.properties index c6ed78c..61e3a0e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -korgePluginVersion=1.13.3.0 +korgePluginVersion=1.13.8.0 #korgeVersion=1.13.3-SNAPSHOT #korviVersion=0.2.1-SNAPSHOT #korimVersion=1.12.25-SNAPSHOT diff --git a/input/src/commonMain/kotlin/main.kt b/input/src/commonMain/kotlin/main.kt index 2fe4ff3..726cc1b 100644 --- a/input/src/commonMain/kotlin/main.kt +++ b/input/src/commonMain/kotlin/main.kt @@ -6,14 +6,14 @@ import com.soywiz.korge.view.* suspend fun main() = Korge { var line = 0 - fun textLine(text: String) = text(text).position(0, line++ * 16).apply { this.filtering = false } - fun nowUnix() = DateTime.now().unixMillisLong + fun textLine(text: String) = text(text).position(2, line++ * 20 + 5).apply { filtering = false } + fun nowTime() = DateTime.now().local.format(DateFormat("HH:mm:ss.SSS")) textLine("Events :") - val keysEvText = textLine("KeysEv") + val keysEvText = textLine("Keys") val keysDownText = textLine("Keys:Down") val keysUpText = textLine("Keys:Up") - val mouseEvText = textLine("Mouse1") + val mouseEvText = textLine("Mouse") val mouseMoveText = textLine("MouseMove") val mouseDownText = textLine("MouseDown") val mouseUpText = textLine("MouseUp") @@ -25,12 +25,12 @@ suspend fun main() = Korge { val gamepadUpdateText = textLine("GamepadUpdateEv") val gamepadUpdate2Text = textLine("GamepadUpdate2Ev") - //stage.addEventListener { keysEvText.text = "${nowUnix()}:$it" } - //stage.addEventListener { mouseEvText.text = "${nowUnix()}:$it" } - //stage.addEventListener { resizeText.text = "${nowUnix()}:$it" } - //stage.addEventListener { gamepadConnectedText.text = "${nowUnix()}:$it" } + //stage.addEventListener { keysEvText.text = "${nowTime()}:$it" } + //stage.addEventListener { mouseEvText.text = "${nowTime()}:$it" } + stage.addEventListener { resizeText.text = "Resize ${nowTime()} $it" } + //stage.addEventListener { gamepadConnectedText.text = "${nowTime()}:$it" } //stage.addEventListener { - // gamepadUpdateText.text = "${nowUnix()}:$it" + // gamepadUpdateText.text = "${nowTime()}:$it" // gamepadUpdate2Text.text = "" + it.gamepads.lastOrNull { it.connected }?.rawButtonsPressed //} @@ -40,14 +40,14 @@ suspend fun main() = Korge { } keys { - onKeyDown { keysDownText.text = "Key:Down:${nowUnix()}:${it.key}" } - onKeyUp { keysUpText.text = "Key:Up:${nowUnix()}:${it.key}" } + onKeyDown { keysDownText.text = "Key:Down ${nowTime()} ${it.key}" } + onKeyUp { keysUpText.text = "Key:Up ${nowTime()} ${it.key}" } } mouse { - onMove { mouseMoveText.text = "Mouse:Move:${nowUnix()}:$it" } - onDown { mouseDownText.text = "Mouse:Down:${nowUnix()}:$it" } - onUp { mouseUpText.text = "Mouse:Up:${nowUnix()}:$it" } - onClick { mouseClickText.text = "Mouse:Click:${nowUnix()}:$it" } + onMove { mouseMoveText.text = "Mouse:Move ${nowTime()} $it" } + onDown { mouseDownText.text = "Mouse:Down ${nowTime()} $it" } + onUp { mouseUpText.text = "Mouse:Up ${nowTime()} $it" } + onClick { mouseClickText.text = "Mouse:Click ${nowTime()} $it" } } } diff --git a/korio/.gitignore b/korio/.gitignore deleted file mode 100644 index 796b96d..0000000 --- a/korio/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/korio/build.gradle.kts b/korio/build.gradle.kts deleted file mode 100644 index f5a0afb..0000000 --- a/korio/build.gradle.kts +++ /dev/null @@ -1,7 +0,0 @@ -import com.soywiz.korge.gradle.* - -apply() - -korge { - id = "com.soywiz.samples.korio" -} diff --git a/korio/src/commonMain/kotlin/main.kt b/korio/src/commonMain/kotlin/main.kt deleted file mode 100644 index bc47b72..0000000 --- a/korio/src/commonMain/kotlin/main.kt +++ /dev/null @@ -1,6 +0,0 @@ -import com.soywiz.korio.* -import com.soywiz.korio.file.std.* - -suspend fun main() = Korio { - println(resourcesVfs["hello.txt"].readString()) -} diff --git a/korio/src/commonMain/resources/hello.txt b/korio/src/commonMain/resources/hello.txt deleted file mode 100644 index 4e3dffe..0000000 --- a/korio/src/commonMain/resources/hello.txt +++ /dev/null @@ -1 +0,0 @@ -HELLO WORLD diff --git a/korio/src/commonTest/kotlin/test.kt b/korio/src/commonTest/kotlin/test.kt deleted file mode 100644 index 5366632..0000000 --- a/korio/src/commonTest/kotlin/test.kt +++ /dev/null @@ -1,7 +0,0 @@ -import kotlin.test.* - -class SimpleTest { - @Test - fun test() { - } -} diff --git a/korio/src/jvmMain/kotlin/main2.kt b/korio/src/jvmMain/kotlin/main2.kt deleted file mode 100644 index 223b9af..0000000 --- a/korio/src/jvmMain/kotlin/main2.kt +++ /dev/null @@ -1,11 +0,0 @@ -import com.soywiz.korio.dynamic.* -import java.net.* - -object Main2 { - @JvmStatic - fun main(args: Array) { - val cl = ClassLoader.getSystemClassLoader() - val data = KDynamic { cl["ucp"]["path"] } as List - println(data) - } -} diff --git a/lipsync/src/commonMain/kotlin/main.kt b/lipsync/src/commonMain/kotlin/main.kt index 6a223d9..4915d8e 100644 --- a/lipsync/src/commonMain/kotlin/main.kt +++ b/lipsync/src/commonMain/kotlin/main.kt @@ -1,13 +1,15 @@ +import com.soywiz.klock.* import com.soywiz.korev.* import com.soywiz.korge.* import com.soywiz.korge.atlas.* +import com.soywiz.korge.input.* import com.soywiz.korge.lipsync.* import com.soywiz.korge.view.* import com.soywiz.korio.async.* import com.soywiz.korio.file.std.* suspend fun main() = Korge { - val atlas = resourcesVfs["lips.atlas.json"].readAtlas(views) + val atlas = resourcesVfs["lips.atlas.json"].readAtlas() val lips = image(atlas["lisa-A.png"]) val lips2 = image(atlas["lisa-A.png"]).position(400, 0) addEventListener { @@ -16,10 +18,12 @@ suspend fun main() = Korge { lips2.texture = atlas["lisa-${it.lip}.png"] } } - launchImmediately { - fun handler(it: LipSyncEvent) { - views.dispatch(it) - lips.texture = atlas["lisa-${it.lip}.png"] + var playing = true + fun play() = launchImmediately { + fun handler(event: LipSyncEvent) { + views.dispatch(event) + lips.texture = atlas["lisa-${event.lip}.png"] + playing = event.time > 0.milliseconds } resourcesVfs["001.voice.wav"].readVoice().play("lisa") { handler(it) } @@ -28,4 +32,9 @@ suspend fun main() = Korge { //resourcesVfs["004.voice.wav"].readVoice().play("lisa") { handler(it) } //resourcesVfs["simple.voice.mp3"].readVoice().play("lisa") { handler(it) } } + + onClick { + if (!playing) play() + } + play() } diff --git a/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/Board.kt b/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/Board.kt index c326110..3bd62bf 100644 --- a/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/Board.kt +++ b/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/Board.kt @@ -10,177 +10,171 @@ import com.soywiz.korio.lang.* import com.soywiz.korma.random.* import kotlin.random.* -// Proceso que se encarga del tablero -open class Board( +// Process of the board +class Board( parent: Container, - val imageset: BmpSlice, - val imagenes: List, + val imageSet: BmpSlice, + val imageSlices: List, val click: NativeSound, val boom: NativeSound, - // Se establecen el ancho, el alto y la cantidad de minas - // Características del tablero: ancho, alto, cantidad de minas - var bwidth: Int, - var bheight: Int, - var minas: Int + // Width, height and quantity of mines are established + // Board characteristics: width, height, number of mines + val bwidth: Int, + val bheight: Int, + var mineNumber: Int ) : Process(parent) { - // Matriz con el tablero + // Matrix with board var board: Array = arrayOf() - // Matriz de máscara (indica que partes del tablero están destapadas) + // Mask matrix (indicates which parts of the board are uncovered) var mask: Array = arrayOf() - // Matriz de marcado (indica que partes del tablero están marcadas como "posible mina") (click derecho) + // Marking matrix (indicates which parts of the board are marked as "possible mine") (right click) var mark: Array = arrayOf() - // Variables utilizadas para el contador - var stime: DateTime = DateTime.EPOCH + // Variables used for the counter + var tstart: DateTime = DateTime.EPOCH var tstop: DateTime = DateTime.EPOCH var timeText: Text var lastx: Int = 0 var lasty: Int = 0 - // Constructor del proceso en el cual se le pasan el ancho, el alto y la cantidad de minas + override var width = bwidth * imageSet.height.toDouble() + override var height = bheight * imageSet.height.toDouble() + init { - // Se crea el texto del contador + // Creating text with time //timeText = new Text("", 50, 50, Text.Align.center, Text.Align.middle, Color.white, new Font("Arial", 40)); //timeText = Text("", 50, 50, Text.Align.center, Text.Align.middle, Color.white, Font.fromResource("font.ttf", 40)); - val FONT_HEIGHT = 32.0 - timeText = text("", textSize = FONT_HEIGHT).xy((bwidth * imageset.height) / 2, -FONT_HEIGHT).apply { - format = Html.Format(align = Html.Alignment.CENTER, size = FONT_HEIGHT.toInt()) - //format = Html.Format(align = Html.Alignment.CENTER, face = defaultUIFont) + val FONT_HEIGHT = 24.0 + timeText = text("00:00", textSize = FONT_HEIGHT).apply { + centerXBetween(0.0, this@Board.width) + y = -FONT_HEIGHT - 5 + format.align = Html.Alignment.CENTER } - // Se pinta el contador como hijo del tablero - //timeText.group.z = this; - // Y se actualiza su texto - updateTimeText() - // Se centra el tablero en la pantalla - x = Screen.width / 2 - (bwidth * imageset.height) / 2 - y = Screen.height / 2 - (bheight * imageset.height - 10 - FONT_HEIGHT) / 2 + //The board is centered on the screen + //x = screen.width / 2 - width / 2 + //y = screen.height / 2 - (height - 10 - FONT_HEIGHT) / 2 + centerOnStage() + y += FONT_HEIGHT / 2 - // Se establecen algunas características del texto, posición, borde y sombra - //timeText.shadow = 5; - //timeText.border = 1; - - // Se reinicia el tablero - clear() + // Restart board + restart() } - // Destructor, aquí se quita el texto cuando se borra el tablero - override protected fun onDestroy() { + // Destructor, the text is removed when the board is being destroyed + override fun onDestroy() { timeText.removeFromParent() } - // Devuelve el tiempo actual (en milisegundos) + // Returns the current time val time: DateTime get() = DateTime.now() - // Resetea el contador fun resetTimer() { - stime = time + tstart = time tstop = DateTime.EPOCH } - // Para el contador fun stopTimer() { tstop = time } - // Devuelve el tiempo ha pasado en segundos desde que se inició el contador + // Returns the time in seconds that has passed since the timer started val elapsed: Int get() = run { var ctime = time if (tstop != DateTime.EPOCH) ctime = tstop - return (ctime - stime).seconds.toInt() + return (ctime - tstart).seconds.toInt() } - // Actualiza el texto del contador con el formato %02d:%02d MM:SS + // Update the counter text in the format %02d:%02d MM:SS fun updateTimeText() { timeText.text = "%02d:%02d".format(elapsed / 60, elapsed % 60) } - // Función que se encarga de borrar el tablero y crear uno nuevo - fun clear() { - // Ahora que vamos a borrar un nuevo tablero (y que vamos a crear una nueva partida) - // reiniciamos el contador + // Function that is responsible for deleting the board and creating a new one + fun restart() { + //Now that we are going to delete a new board (and that we are going to create a new game) + //we reset the timer resetTimer() - // Creamos las matrices con el tablero, la máscara de visión y la máscara de marcado (de posibles minas) + // We create the matrices with the board, the vision mask and the marking mask (of possible mines) board = Array(bheight) { IntArray(bwidth) } mask = Array(bheight) { BooleanArray(bwidth) } mark = Array(bheight) { BooleanArray(bwidth) } - // Comprobamos que no se intenten colocar mas minas que posiciones hay, evitando así un bucle infinito - // en realidad solo se colocan como mucho una cantidad de minas igual a las posiciones del tablero - 1 - // para que pueda haber partida (si no se ganaría directamente) - if (minas > bwidth * bheight - 1) minas = bwidth * bheight - 1 + // We check that there are no attempts to place more mines than there are positions, thus avoiding an infinite loop + // actually only a maximum number of mines equal to the board positions - 1 are placed + if (mineNumber > bwidth * bheight - 1) mineNumber = bwidth * bheight - 1 - // Ahora procederemos a colocar las minas en el tablero - for (n in 0 until minas) { - // Declaramos px, py que utilizaremos para almacenar las posiciones temporales de la mina - var px: Int = 0 - var py: Int = 0 + // Now we will proceed to place the mines on the board + repeat(mineNumber) { + // We declare px and py that we will use to store the temporary positions of a mine + var px: Int + var py: Int do { - // Obtenemos una posible posición de la mina + // We get a possible mine position px = Random[0, bwidth - 1] py = Random[0, bheight - 1] - // Comprobamos si en esa posición hay una mina y estaremos buscando posiciones hasta - // que en esa posición no haya mina + // We check if there is a mine in that position and we will be looking for positions until + // there is no mine in that position } while (board[py][px] == 10) - // Ahora que sabemos que en esa posición no hay mina, colocamos una + // Now that we know that there is no mine in that position, we place it board[py][px] = 10 } - // Ahora que hemos colocado las minas, vamos a colocar los números alrededor de ellas - // Esta es una parte interesante del buscaminas, aquí se colcan los numeros alrededor de las minas + // Now that we have placed the mines, we are going to place the numbers around them + // This is an interesting part of the minesweeper, here the numbers are placed around the mines - // Nos recorremos el tablero entero + // We go over the entire board for (y in 0 until bheight) { for (x in 0 until bwidth) { - // Comprobamos que en esa posición no haya mina, si hay mina, "pasamos", hacemos un continue y seguimos a la siguiente posición - // sin ejecutar lo que viene después + // We check that there is no mine in that position, if there is a mine, we "pass": + // we continue to the next position without processing this one if (board[y][x] == 10) continue - // Ahora vamos a contar las minas que hay alrededor de esta posición (ya que en esta posición no hay mina y es posible que tengamos - // que poner un número si tiene alguna mina contigua) + // Now we are going to count the mines around this position + // (since there is no mine in this position and we may have to put a number if it has a contiguous mine) var count = 0 - // Recorremos con x1 € [-1,1], y1 € [-1, 1] for (y1 in -1..+1) { for (x1 in -1..+1) { - // Ahora x + x1 y y + y1 tomaran posiciones de la matriz contiguas a la posición actual - // empezando por x - 1, y - 1 para acabar en x + 1, y + 1 - // Comprobamos que la posición esté dentro de la matriz, ya que por ejemplo en la posición 0 - // la posición 0 - 1, 0 - 1, sería la -1, -1, que no está dentro de la matriz y si no está dentro - // de los límites de la matriz, pasamos - if (!in_bounds(x + x1, y + y1)) continue - // Si en esta posición contigua hay una mina entonces incrementamos el contador + // Now x + x1 and y + y1 will take matrix positions contiguous to the current position + // from x - 1, y - 1 to x + 1, y + 1 + // We check that the position is inside the matrix, since for example in position 0 + // 0 - 1, 0 - 1 would be -1, -1, which is not inside the matrix + // so if it is not inside the limits of the matrix, we pass + if (!inBounds(x + x1, y + y1)) continue + // If there is a mine in this adjacent position, we increase the counter if (board[y + y1][x + x1] == 10) count++ } } - // Introducimos en el tablero la nueva imagen (puesto que la imagen con 0 posiciones es la 1 y las siguientes - // son 1, 2, 3, 4, 5, 6, 7, 8) ponemos la imagen correspondiente a count + 1 + // We introduce the new image on the board (since the image with 0 positions is 1 + // and the following are 1, 2, 3, 4, 5, 6, 7, 8) we put the corresponding image to count + 1 board[y][x] = count + 1 } } - // Ahora ya tenemos el tablero preparado + // Now we have the board ready } - // Indica si una posición está dentro de la matriz - fun in_bounds(px: Int, py: Int): Boolean { - // Si la posición es negativa o si la posición está mas a la derecha del ancho del tablero, devuelve false (no está dentro) + // Indicates if a position is inside the matrix + fun inBounds(px: Int, py: Int): Boolean { + // If the x position is negative or if the position is more to the right of the width of the board, + // it returns false (it is not inside) if (px < 0 || px >= bwidth) return false - // Si ocurre lo mismo con la posición y, también devolvemos false + // If the same thing happens with the y position, we also return false if (py < 0 || py >= bheight) return false - // Si no hemos devuelto ya false, quiere decir que la posición si que está dentro del tablero, así que devolvemos true + // If we have not already returned false, it means the position is inside the board, so we return true return true } var fillpos = 0 - // Rellena una posición (recursivamente; la forma mas clara y sencilla) + // Fill in a position (recursively, the clearest and simplest form) suspend fun fill(px: Int, py: Int) { - if (!in_bounds(px, py)) return + if (!inBounds(px, py)) return if (mask[py][px] || mark[py][px]) return mask[py][px] = true @@ -199,17 +193,15 @@ open class Board( fill(px - 1, py + 1) } - suspend fun show_board_lose() { - // Subfunción de show_board_lose que se encarga de - // desenmascarar una posición despues de comprobar - // si es correcta + suspend fun showBoardLose() { + // It's a sub-function that unmasks a position after checking for correctness fun unmask(x: Int, y: Int): Boolean { - if (!in_bounds(x, y)) return false + if (!inBounds(x, y)) return false mask[y][x] = true return true } - // Propagación con forma de diamante + // Diamond shaped propagation var dist = 0 while (true) { var drawing = false @@ -225,11 +217,10 @@ open class Board( dist++ frame() - //if (dist >= max(width * 2, height * 2)) break; } } - suspend fun show_board_win() { + suspend fun showBoardWin() { for (y in 0 until bheight) { for (x in 0 until bwidth) { if (board[y][x] == 10) { @@ -244,15 +235,15 @@ open class Board( } suspend fun check(px: Int, py: Int): Boolean { - if (!in_bounds(px, py)) return false + if (!inBounds(px, py)) return false - // Guardamos la última posición en la que hicimos click + // We save the last position that was clicked lastx = px; lasty = py - // Estamos ante una mina + // The next is a mine if (board[py][px] == 10) return true - // Estamos ante una casilla vacía + // The next is an empty box if (board[py][px] == 1) { fps = 140.0 fillpos = 0 @@ -269,8 +260,8 @@ open class Board( return false } - // Comprueba si el tablero está en un estado en el cual podemos dar por ganada la partida - fun check_win(): Boolean { + // Check if the board is in a state when we can consider the game won + fun checkWin(): Boolean { var count = 0 for (y in 0 until bheight) { for (x in 0 until bwidth) { @@ -278,30 +269,30 @@ open class Board( } } - return (count == bwidth * bheight - minas) + return (count == bwidth * bheight - mineNumber) } - // La acción principal redirecciona a la acción de juego + // The main action redirects to the game action override suspend fun main() = action(::play) - // La acción principal de juego que se encarga de gestionar los clicks de ratón + // The main game action that is responsible for managing mouse clicks suspend fun play() { while (true) { //println("Mouse.x: ${Mouse.x}, x=$x") - if (Mouse.x >= x && Mouse.x < x + bwidth * imageset.height) { - if (Mouse.y >= y && Mouse.y < y + bheight * imageset.height) { - val px = ((Mouse.x - x) / imageset.height).toInt() - val py = ((Mouse.y - y) / imageset.height).toInt() + if (mouse.x >= x && mouse.x < x + bwidth * imageSet.height) { + if (mouse.y >= y && mouse.y < y + bheight * imageSet.height) { + val px = ((mouse.x - x) / imageSet.height).toInt() + val py = ((mouse.y - y) / imageSet.height).toInt() - if (Mouse.released[0]) { + if (mouse.released[0]) { if (!mark[py][px]) { if (check(px, py)) { action(::lose) - } else if (check_win()) { + } else if (checkWin()) { action(::win) } } - } else if (Mouse.released[1] || Mouse.released[2]) { + } else if (mouse.released[1] || mouse.released[2]) { mark[py][px] = !mark[py][px] } } @@ -311,15 +302,15 @@ open class Board( } } - // Acción del tablero que ocurre cuando el jugador ha perdido + // Board action that occurs when the player has lost suspend fun lose() { audio.play(boom, 0) stopTimer() - show_board_lose() + showBoardLose() while (true) { - if (Mouse.left || Mouse.right) { - clear() + if (mouse.left || mouse.right) { + restart() for (n in 0 until 10) frame() action(::play) } @@ -327,14 +318,14 @@ open class Board( } } - // Acción del tablero que ocurre cuando el jugador ha ganado + // Board action that occurs when the player has won suspend fun win() { stopTimer() - show_board_win() + showBoardWin() while (true) { - if (Mouse.left || Mouse.right) { - clear() + if (mouse.left || mouse.right) { + restart() for (n in 0 until 10) frame() action(::play) } @@ -344,7 +335,7 @@ open class Board( val images = Array(bheight) { py -> Array(bwidth) { px -> - image(Bitmaps.transparent).xy(px * imageset.height, py * imageset.height).scale(0.9) + image(Bitmaps.transparent).xy(px * imageSet.height, py * imageSet.height).scale(0.9) } } @@ -352,15 +343,14 @@ open class Board( for (py in 0 until bheight) { for (px in 0 until bwidth) { val image = if (!mask[py][px]) { - imagenes[if (mark[py][px]) 11 else 0] + imageSlices[if (mark[py][px]) 11 else 0] } else { - imagenes[board[py][px]] + imageSlices[board[py][px]] } images[py][px].texture = image } } - super.renderInternal(ctx) } } diff --git a/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/Process.kt b/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/Process.kt index 67b7a23..c107797 100644 --- a/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/Process.kt +++ b/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/Process.kt @@ -1,7 +1,6 @@ package com.soywiz.korge.samples.minesweeper import com.soywiz.kds.* -import com.soywiz.klock.* import com.soywiz.kmem.* import com.soywiz.korau.sound.* import com.soywiz.korev.* @@ -11,7 +10,6 @@ import com.soywiz.korge.view.* import com.soywiz.korim.format.* import com.soywiz.korio.async.* import com.soywiz.korio.file.std.* -import com.soywiz.korma.geom.* import kotlinx.coroutines.* import kotlin.reflect.* @@ -25,14 +23,11 @@ abstract class Process(parent: Container) : Container() { var fps: Double = 60.0 val key get() = stage.views.key - val Mouse get() = views.mouseV - val Screen get() = views.screenV + val mouse get() = views.mouseV val audio get() = views.audioV suspend fun frame() { delayFrame() - //views.stage.delayFrame() - //delay((1.0 / fps).seconds) } fun action(action: KSuspendFunction0) { @@ -78,23 +73,7 @@ abstract class Process(parent: Container) : Container() { class ChangeActionException(val action: KSuspendFunction0) : Exception() - inline fun collision(): T? = views.stage.findCollision(this) - fun collision(matcher: (View) -> Boolean): View? = views.stage.findCollision(this, matcher) -} - - -inline fun Container.findCollision(subject: View): T? = findCollision(subject) { it is T && it != subject } as T? - -fun Container.findCollision(subject: View, matcher: (View) -> Boolean): View? { - var collides: View? = null - this.foreachDescendant { - if (matcher(it)) { - if (subject.collidesWith(it)) { - collides = it - } - } - } - return collides + inline fun collision(): T? = views.stage.findCollision(this) } class KeyV(val views: Views) { @@ -113,13 +92,10 @@ class MouseV(val views: Views) { val _released = BooleanArray(8) } -class ScreenV(val views: Views) { - val width: Double get() = views.virtualWidth.toDouble() - val height: Double get() = views.virtualHeight.toDouble() -} - class AudioV(val views: Views) { fun play(sound: NativeSound, repeat: Int = 0) { + val times = (1 + repeat).playbackTimes + sound.play(times) } } @@ -127,7 +103,6 @@ val Views.keysPressed by Extra.Property { LinkedHashMap() } val Views.key by Extra.PropertyThis { KeyV(this) } val Views.mouseV by Extra.PropertyThis { MouseV(this) } -val Views.screenV by Extra.PropertyThis { ScreenV(this) } val Views.audioV by Extra.PropertyThis { AudioV(this) } fun Views.registerProcessSystem() { @@ -165,4 +140,4 @@ fun Views.registerProcessSystem() { } suspend fun readImage(path: String) = resourcesVfs[path].readBitmapSlice() -suspend fun readSound(path: String) = resourcesVfs[path].readNativeSoundOptimized() +suspend fun readSound(path: String) = resourcesVfs[path].readSound() diff --git a/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/RandomLight.kt b/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/RandomLight.kt index d14def8..d7b3723 100644 --- a/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/RandomLight.kt +++ b/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/RandomLight.kt @@ -22,18 +22,17 @@ class RandomLight( init { image(light, 0.5, 0.5).apply { - this.blendMode = BlendMode.ADD + blendMode = BlendMode.ADD } } override suspend fun main() { - sx = random[-w2, w2] - sy = random[-h2, h2] - inca = random[0.0001, 0.03] - incs = random[0.5, 2.0] - excx = random[0.7, 1.3] - excy = random[0.7, 1.3] - alpha = random[0.4, 0.7] + sx = random[-w2, w2] + sy = random[-h2, h2] + inca = random[0.0001, 0.03] + incs = random[0.5, 2.0] + excx = random[0.7, 1.3] + excy = random[0.7, 1.3] alpha = 0.1 while (true) { @@ -42,8 +41,8 @@ class RandomLight( y = h2 - sin(rotationDegrees) * h2 * excy + sy scale = 1 + (cos(rotationDegrees) / 6) * incs - // Comprueba si una esfera de luz ha chocado con otra - // El sistema de colisión por defecto es inner circle + // Check if a light sphere collided with another one + // The default collision system is inner circle if (this.collision() != null) { alpha = (alpha + 0.01).coerceIn(0.1, 0.8) } else { @@ -53,15 +52,4 @@ class RandomLight( frame() } } - - suspend fun fadeout() { - while (alpha > 0) { - alpha -= 0.1 - frame() - } - } - - fun draw() { - //graph.draw(__x, __y, alpha, 0, size, alpha, alpha, alpha, GL_ONE, GL_ONE); - } } diff --git a/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/main.kt b/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/main.kt index a0d69d8..6a5a10d 100644 --- a/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/main.kt +++ b/minesweeper/src/commonMain/kotlin/com/soywiz/korge/samples/minesweeper/main.kt @@ -27,22 +27,21 @@ class MainProcess(parent: Container) : Process(parent) { override suspend fun main() { image(readImage("bg.jpg")).dockedTo(Anchor.TOP_LEFT, ScaleMode.EXACT) val light = readImage("light.png") - val imageset = readImage("buscaminas.png") - val imagenes = imageset.split(imageset.height, imageset.height) + val imageSet = readImage("cells.png") + val images = imageSet.split(imageSet.height, imageSet.height) val click = readSound("click.wav") val boom = readSound("boom.wav") - for (n in 0 until 20) { + repeat(20) { lights += RandomLight(this, light) } - val board = Board(this, imageset, imagenes, click, boom, 22, 15, 40) + val board = Board(this, imageSet, images, click, boom, 22, 15, 40) val nativeProcess = NativeProcess(views) while (true) { if (key[Key.ESCAPE]) { nativeProcess.close() - } if (key[Key.UP]) { lights += RandomLight(this, light) diff --git a/minesweeper/src/commonMain/resources/buscaminas.png b/minesweeper/src/commonMain/resources/cells.png similarity index 100% rename from minesweeper/src/commonMain/resources/buscaminas.png rename to minesweeper/src/commonMain/resources/cells.png diff --git a/onscreen-controller/src/commonMain/kotlin/OnScreenController.kt b/onscreen-controller/src/commonMain/kotlin/OnScreenController.kt index 2d1663b..f0c62fa 100644 --- a/onscreen-controller/src/commonMain/kotlin/OnScreenController.kt +++ b/onscreen-controller/src/commonMain/kotlin/OnScreenController.kt @@ -8,14 +8,27 @@ import com.soywiz.korma.geom.* import com.soywiz.korma.geom.vector.* import kotlin.math.* -fun Container.addTouchGamepad(width: Double = 320.0, height: Double = 224.0, radius: Double = height / 8, onStick: (x: Double, y: Double) -> Unit = { x, y -> }, onButton: (button: Int, pressed: Boolean) -> Unit = { button, pressed -> }) { +fun Container.addTouchGamepad( + width: Double = 320.0, + height: Double = 224.0, + radius: Double = height / 8, + onStick: (x: Double, y: Double) -> Unit = { _, _ -> }, + onButton: (button: Int, pressed: Boolean) -> Unit = { _, _ -> } +) { val view = this lateinit var ball: View val diameter = radius * 2 + container { - position(+radius * 1.1, height - radius * 1.1) - graphics { fill(Colors.BLACK) { circle(0, 0, radius) } }.alpha(0.2) - ball = graphics { fill(Colors.WHITE) { circle(0, 0, radius * 0.7) } }.alpha(0.2) + position(radius * 1.1, height - radius * 1.1) + graphics { + fill(Colors.BLACK) { circle(0.0, 0.0, radius) } + alpha(0.2) + } + ball = graphics { + fill(Colors.WHITE) { circle(0.0, 0.0, radius * 0.7) } + alpha(0.2) + } } fun T.decorateButton(button: Int) = this.apply { @@ -35,7 +48,12 @@ fun Container.addTouchGamepad(width: Double = 320.0, height: Double = 224.0, rad } for (n in 0 until 2) { - val button = graphics { position(width - radius * 1.1 - (diameter * n), height - radius * 1.1).fill(Colors.WHITE) { circle(0, 0, radius * 0.7) } }.alpha(0.2).decorateButton(n) + graphics { + position(width - radius * 1.1 - (diameter * n), height - radius * 1.1) + fill(Colors.WHITE) { circle(0.0, 0.0, radius * 0.7) } + alpha(0.2) + decorateButton(n) + } } var dragging = false @@ -44,19 +62,19 @@ fun Container.addTouchGamepad(width: Double = 320.0, height: Double = 224.0, rad view.addComponent(object : MouseComponent { override val view: View = view - override fun onMouseEvent(views: Views, it: MouseEvent) { - val px = view.globalMatrixInv.transformX(it.x.toDouble(), it.y.toDouble()) - val py = view.globalMatrixInv.transformY(it.x.toDouble(), it.y.toDouble()) + override fun onMouseEvent(views: Views, event: MouseEvent) { + val px = view.globalMatrixInv.transformX(event.x.toDouble(), event.y.toDouble()) + val py = view.globalMatrixInv.transformY(event.x.toDouble(), event.y.toDouble()) - when (it.type) { + when (event.type) { MouseEvent.Type.DOWN -> { - if (px >= width / 2) return@onMouseEvent + if (px >= width / 2) return start.x = px start.y = py ball.alpha = 0.3 dragging = true } - MouseEvent.Type.DRAG -> { + MouseEvent.Type.MOVE, MouseEvent.Type.DRAG -> { if (dragging) { val deltaX = px - start.x val deltaY = py - start.y diff --git a/onscreen-controller/src/commonMain/kotlin/main.kt b/onscreen-controller/src/commonMain/kotlin/main.kt index 796fc63..cb2b063 100644 --- a/onscreen-controller/src/commonMain/kotlin/main.kt +++ b/onscreen-controller/src/commonMain/kotlin/main.kt @@ -1,16 +1,12 @@ -import com.soywiz.klock.* import com.soywiz.korge.* -import com.soywiz.korge.particle.* import com.soywiz.korge.view.* import com.soywiz.korim.color.* -import com.soywiz.korio.async.* -import com.soywiz.korio.file.std.* import com.soywiz.korio.util.* suspend fun main() = Korge(bgcolor = Colors.DARKBLUE) { - val text1 = text("-").position(0, 0).also { it.filtering = false } + val text1 = text("-").position(5, 5).apply { filtering = false } val buttonTexts = (0 until 2).map { - text("-").position(0, 15 * (it + 1)).also { it.filtering = false } + text("-").position(5, 20 * (it + 1) + 5).apply { filtering = false } } addTouchGamepad( diff --git a/pong/src/commonMain/kotlin/MenuScene.kt b/pong/src/commonMain/kotlin/MenuScene.kt index 2c1535c..9a40ce8 100644 --- a/pong/src/commonMain/kotlin/MenuScene.kt +++ b/pong/src/commonMain/kotlin/MenuScene.kt @@ -1,37 +1,33 @@ -import com.soywiz.korev.Key -import com.soywiz.korge.input.keys -import com.soywiz.korge.input.onClick -import com.soywiz.korge.scene.Scene -import com.soywiz.korge.view.Container -import com.soywiz.korge.view.text +import com.soywiz.korge.input.* +import com.soywiz.korge.scene.* import com.soywiz.korge.ui.* -import com.soywiz.korge.view.position -import com.soywiz.korim.color.Colors +import com.soywiz.korge.view.* +import com.soywiz.korim.color.* class MenuScene() : Scene() { - suspend override fun Container.sceneInit() { - // set a background color - views.clearColor = Colors.BLACK + suspend override fun Container.sceneInit() { + // set a background color + views.clearColor = Colors.BLACK - // Add a text to show the name of the game - var gameNameText = text("Super Pong Bros II") { - position(views.virtualWidth/2 - 128, views.virtualHeight/2 - 128) - } + // Add a text to show the name of the game + var gameNameText = text("Super Pong Bros II") { + position(views.virtualWidth / 2 - 128, views.virtualHeight / 2 - 128) + } - var playButton = textButton(256.0, 32.0) { - text = "Play" - position(views.virtualWidth/2 - 128, views.virtualHeight/2 - 64) - onClick { - sceneContainer.changeToAsync() - } - } - var exitButton = textButton(256.0, 32.0) { - text = "Exit" - position(views.virtualWidth/2 - 128, views.virtualHeight/2) - onClick { - views.gameWindow.close() - } - } - } + var playButton = textButton(256.0, 32.0) { + text = "Play" + position(views.virtualWidth / 2 - 128, views.virtualHeight / 2 - 64) + onClick { + sceneContainer.changeTo() + } + } + var exitButton = textButton(256.0, 32.0) { + text = "Exit" + position(views.virtualWidth / 2 - 128, views.virtualHeight / 2) + onClick { + views.gameWindow.close() + } + } + } } diff --git a/pong/src/commonMain/kotlin/PlayScene.kt b/pong/src/commonMain/kotlin/PlayScene.kt index d0d54c3..7123647 100644 --- a/pong/src/commonMain/kotlin/PlayScene.kt +++ b/pong/src/commonMain/kotlin/PlayScene.kt @@ -6,208 +6,193 @@ import com.soywiz.korim.color.Colors import kotlin.math.* import kotlin.random.Random.Default.nextDouble -/* Define the various states that the game can be in */ +// Define the various states that the game can be in enum class GameStates { - Starting, // The game is just starting and some helptext will be shown. Ball will not be moving - Playing, // in this state the ball will be moving and player can score against each other - Scored, // in this state the game will pause and show that a goal was cored + Starting, // The game is just starting and some help text will be shown. Ball will not be moving + Playing, // in this state the ball will be moving and player can score against each other + Scored, // in this state the game will pause and show that a goal was cored } class PlayScene() : Scene() { - suspend override fun Container.sceneInit() { - var fpsText: Text - var scoredYellText: Text - var tickSizeText: Text - var helpText: Text - var scoreLeftText: Text - var scoreRightText: Text - var paddleLeft: SolidRect - var paddleRight: SolidRect - var ball: Circle + suspend override fun Container.sceneInit() { + // Initialize the variables which will capture the game state + var scorePlayerLeft = 0 + var scorePlayerRight = 0 + var playState = GameStates.Starting - /* Initialize the variables which will capture the game state*/ - var scorePlayerLeft = 0 - var scorePlayerRight = 0 - var playState = GameStates.Starting + // Initialize the starting game state values + val paddlePosYAtStart = views.virtualHeight / 2 - 50.0 + val ballPosXAtStart = views.virtualWidth / 2 - 10.0 + val ballPosYAtStart = views.virtualWidth / 2 + 10.0 + val ballSpeedAtStart = 200.0 - /* Initialize the starting game state values */ - val paddlePosYAtStart = views.virtualHeight / 2 - 50.0 - val ballPosXAtStart = views.virtualWidth / 2 - 10.0 - val ballPosYAtStart = views.virtualWidth / 2 + 10.0 - val ballSpeedAtStart = 200.0 + // Initialize the variables defining the paddle and ball parameters + val paddleWidth = 10.0 + val paddleHeight = 100.0 + val paddleDistanceFromWall = 10.0 + val paddleMoveSpeed = 10.0 + val ballRadius = 10.0 + val ballSpeedIncrease = 50.0 - /* Initialize the variables to be used to define the paddle and ball size */ - val paddleWidth = 10.0 - val paddleHeight = 100.0 - val paddleDistanceFromWall = 10.0 - val paddleMoveSpeed = 10.0 - val ballRadius = 10.0 - val ballSpeedIncrease = 50.0 + // Add a HUD for reporting the FPS + val fpsText = text("FPS: 0") { + position(10, 30) + addUpdater { + text = "FPS: " + views.gameWindow.fps.toString() + } + } + // Add a HUD for reporting the ticks/frame length + val tickSizeText = text("Tick: 0") { + position(10, 50) + addUpdater { + text = "Tick: " + views.gameWindow.timePerFrame.toString() + } + } - // Add a HUD for reporting the FPS - fpsText = text("FPS: 0") { - position(10, 30) - addUpdater { - text = "FPS: " + views.gameWindow.fps.toString() - } - } + // Add a help text which explains the rules of the game + val helpText = text("") { + position(10, 100) + addUpdater { + // this text is only visible if the game is not in Playing state + visible = (playState != GameStates.Playing) - // Add a HUD for reporting the ticks/frame length - tickSizeText = text("Tick: 0") { - position(10, 50) - addUpdater { - text = "Tick: " + views.gameWindow.timePerFrame.toString() - } - } + // show a different text if the game is just starting + if (playState == GameStates.Starting) { + text = "Welcome to the PONG Game!\n\n" + + "-- To move the Left Paddle, use the keys [W] and [S].\n\n" + + "-- To move the Right Paddle, use the keys [UP] and [DOWN]\n\n" + + "-- To go back to Main Menu, use [ESC]\n\n" + + "-- To Start the game, use [SPACE]" + // show a different text if the game is in Scored state + } else if (playState == GameStates.Scored) { + text = "Press [SPACE] for the next round!" + } + } + } - // Add a help text which explains the rules of the game - helpText = text("") { - position(10, 100) - addUpdater { - // this text is only visible if the game is not in Playing state - visible = (playState != GameStates.Playing) + // A simple flavour text informing that a goal was scored + val scoredYellText = text("SCORED!!!\n\n") { + position(views.virtualWidth / 2 - 100, views.virtualHeight / 2 - 20) + addUpdater { + // this is only visible when the game is in Scored state + visible = (playState == GameStates.Scored) + } + } - // show a different text if the game is just starting - if (playState == GameStates.Starting) { - text = "Welcome to the PONG Game!\n\n" + - "-- To move the Left Paddle, use the keys [W] and [S].\n\n" + - "-- To move the Right Paddle, use the keys [UP] and [DOWN]\n\n" + - "-- To go back to Main Menu, use [ESC]\n\n" + - "-- To Start the game, use [SPACE]" - // show a different text if the game is in Scored state - } else if (playState == GameStates.Scored) { - text = "Press [SPACE] for the next round!" - } - } - } - - // A simple flavour text informing that a goal was scored - scoredYellText = text("SCORED!!!\n\n") { - position(views.virtualWidth / 2 - 100, views.virtualHeight / 2 - 20) - addUpdater { - // this is only visible when the game is in Scored state - visible = (playState == GameStates.Scored) - } - } - - // text to show the score of the player on the Left side - scoreLeftText = text("0") { + // text to show the score of the player on the Left side + val scoreLeftText = text("0") { // textSize = 24.0 - position(views.virtualWidth / 4, views.virtualHeight / 2) - addUpdater { - text = scorePlayerLeft.toString() - } - } - // text to show the score of the player on the Right side - scoreRightText = text("0") { - position(views.virtualWidth * 3 / 4, views.virtualHeight / 2) - addUpdater { - text = scorePlayerRight.toString() - } - } + position(views.virtualWidth / 4, views.virtualHeight / 2) + addUpdater { + text = scorePlayerLeft.toString() + } + } + // text to show the score of the player on the Right side + val scoreRightText = text("0") { + position(views.virtualWidth * 3 / 4, views.virtualHeight / 2) + addUpdater { + text = scorePlayerRight.toString() + } + } - // the left paddle - paddleLeft = solidRect(paddleWidth, paddleHeight, Colors.RED) { - position(paddleDistanceFromWall, paddlePosYAtStart) - addUpdater { - // move the paddle up or down as long as it doesn't leaves the bounds of the game window - val keys = views.input.keys - if (keys[Key.W] && y > 0) { - y -= paddleMoveSpeed - } - if (keys[Key.S] && y < views.virtualHeight - paddleHeight) { - y += paddleMoveSpeed - } - } - } + // the left paddle + val paddleLeft = solidRect(paddleWidth, paddleHeight, Colors.RED) { + position(paddleDistanceFromWall, paddlePosYAtStart) + addUpdater { + // move the paddle up or down as long as it doesn't leaves the bounds of the game window + val keys = views.input.keys + if (keys[Key.W] && y > 0) { + y -= paddleMoveSpeed + } + if (keys[Key.S] && y < views.virtualHeight - paddleHeight) { + y += paddleMoveSpeed + } + } + } - // the right paddle - paddleRight = solidRect(paddleWidth, paddleHeight, Colors.BLUE) { - position(views.virtualWidth - paddleDistanceFromWall - paddleWidth, paddlePosYAtStart) - addUpdater { - // move the paddle up or down as long as it doesn't leaves the bounds of the game window - val keys = views.input.keys - if (keys[Key.UP] && y > 0) { - y -= paddleMoveSpeed - } - if (keys[Key.DOWN] && y < views.virtualHeight - paddleHeight) { - y += paddleMoveSpeed - } - } - } + // the right paddle + val paddleRight = solidRect(paddleWidth, paddleHeight, Colors.BLUE) { + position(views.virtualWidth - paddleDistanceFromWall - paddleWidth, paddlePosYAtStart) + addUpdater { + // move the paddle up or down as long as it doesn't leaves the bounds of the game window + val keys = views.input.keys + if (keys[Key.UP] && y > 0) { + y -= paddleMoveSpeed + } + if (keys[Key.DOWN] && y < views.virtualHeight - paddleHeight) { + y += paddleMoveSpeed + } + } + } - ball = circle(ballRadius, Colors.WHITE) { - position(ballPosXAtStart, ballPosYAtStart) + val ball = circle(ballRadius, Colors.WHITE) { + position(ballPosXAtStart, ballPosYAtStart) - // define the mutable data defning the ball's state - var spd = ballSpeedAtStart - var ang = nextDouble() * 2 * PI + // mutable data defining the ball state + var spd = ballSpeedAtStart + var ang = nextDouble() * 2 * PI - // function to reset the ball - var resetRound = fun () { - x = ballPosXAtStart - y = ballPosYAtStart - spd = ballSpeedAtStart - ang = nextDouble() * 2 * PI + // function to reset the ball + fun resetRound() { + x = ballPosXAtStart + y = ballPosYAtStart + spd = ballSpeedAtStart + ang = nextDouble() * 2 * PI - // Change game state to Scored. Game will be paused till players start the next round. - playState = GameStates.Scored - } + // Change game state to Scored. Game will be paused till players start the next round. + playState = GameStates.Scored + } - addUpdater { - // only move ball if the game is in Playing state - if (playState == GameStates.Playing) { + addUpdater { + // only move ball if the game is in Playing state + if (playState == GameStates.Playing) { - // convert the ball's velocity vector (speed, angle) to a point to move to - x += spd * cos(ang) * it.seconds; - y += spd * sin(ang) * it.seconds; + // convert the ball's velocity vector (speed, angle) to a point to move to + x += spd * cos(ang) * it.seconds; + y += spd * sin(ang) * it.seconds; - // if the ball hits the paddles, flip its direction and increase speed - if ((x < paddleLeft.x + 10 && y > paddleLeft.y && y < paddleLeft.y + 100) || - (x > paddleRight.x - 20 && y > paddleRight.y && y < paddleRight.y + 100)) { - spd += ballSpeedIncrease - ang = PI - ang - } + // if the ball hits the paddles, flip its direction and increase speed + if ((x < paddleLeft.x + 10 && y > paddleLeft.y && y < paddleLeft.y + 100) || + (x > paddleRight.x - 20 && y > paddleRight.y && y < paddleRight.y + 100)) { + spd += ballSpeedIncrease + ang = PI - ang + } - // if ball hits the walls, flip its direction and increase speed - if (y < 0 || y > views.virtualHeight - 20) { - spd += 10 - ang *= -1 - } + // if ball hits the walls, flip its direction and increase speed + if (y < 0 || y > views.virtualHeight - 20) { + spd += 10 + ang *= -1 + } - // if ball goes through the vertical walls/goalpost, handle scoring and reset the round - if (x < -20) { - /* Reset the Ball */ - resetRound() + // if ball goes through the vertical walls/goalpost, handle scoring and reset the round + if (x < -20) { + // Reset the Ball + resetRound() - // Update the score - scorePlayerRight++ - scoredYellText.text = "Right SCORED!!!" - } else if (x > views.virtualWidth) { - /* Reset the Ball */ - resetRound() + // Update the score + scorePlayerRight++ + scoredYellText.text = "Right SCORED!!!" + } else if (x > views.virtualWidth) { + // Reset the Ball + resetRound() - // Update the score - playState = GameStates.Scored - scorePlayerLeft++ - scoredYellText.text = "Left SCORED!!!" - } - } - } - } + // Update the score + playState = GameStates.Scored + scorePlayerLeft++ + scoredYellText.text = "Left SCORED!!!" + } + } + } + } - /* Add the keys needed to run the game*/ - keys { - onKeyDown { - when (it.key) { - Key.ESCAPE -> sceneContainer.changeToAsync() - Key.SPACE -> playState = GameStates.Playing - else -> { - } - } - } - } - - } + // Add the keys needed to run the game + onKeyDown { + when (it.key) { + Key.ESCAPE -> sceneContainer.changeTo() + Key.SPACE -> playState = GameStates.Playing + else -> Unit + } + } + } } diff --git a/pong/src/commonMain/kotlin/main.kt b/pong/src/commonMain/kotlin/main.kt index 7e1bf07..102ed38 100644 --- a/pong/src/commonMain/kotlin/main.kt +++ b/pong/src/commonMain/kotlin/main.kt @@ -1,9 +1,7 @@ -import com.soywiz.korge.Korge -import com.soywiz.korge.scene.Module -import com.soywiz.korge.scene.Scene -import com.soywiz.korinject.AsyncInjector -import com.soywiz.korma.geom.SizeInt -import kotlin.reflect.KClass +import com.soywiz.korge.* +import com.soywiz.korge.scene.* +import com.soywiz.korinject.* +import com.soywiz.korma.geom.* suspend fun main() = Korge(Korge.Config(module = MyModule)) diff --git a/shapes/src/commonMain/kotlin/Sample1.kt b/shapes/src/commonMain/kotlin/Sample1.kt index 6c12321..e23da00 100644 --- a/shapes/src/commonMain/kotlin/Sample1.kt +++ b/shapes/src/commonMain/kotlin/Sample1.kt @@ -1,24 +1,68 @@ import com.soywiz.klock.* import com.soywiz.korge.* +import com.soywiz.korge.input.* import com.soywiz.korge.view.* import com.soywiz.korgw.* import com.soywiz.korim.color.* import com.soywiz.korio.async.* +import com.soywiz.korma.geom.* import com.soywiz.korma.geom.vector.* -suspend fun main() = Korge(quality = GameWindow.Quality.PERFORMANCE, title = "My Awesome Box2D Game!") { +suspend fun main() = Korge(quality = GameWindow.Quality.PERFORMANCE, title = "KorGE Shapes!") { setupCircle() + setupRects() + + solidRect(300, 200, Colors.DARKCYAN) + sgraphics { + fill(Colors.DARKCYAN) { + rect(-1.0, -1.0, 3.0, 2.0) + } + fill(Colors.AQUAMARINE) { + circle(0.0, 0.0, 1.0) + } + fill(Colors.AQUAMARINE) { + circle(1.0, 0.0, 1.0) + } + position(100, 100) + }.scale(100.0, 100.0).interactive() } fun Stage.setupCircle() { val circle = Circle(radius = 32.0) addChild(circle) + circle.position(512, 256) + var growing = true launch { while (true) { - circle.x++ - circle.y++ - circle.radius++ + when { + circle.radius > 128.0 -> { + growing = false + circle.radius-- + } + circle.radius < 32.0 -> { + growing = true + circle.radius++ + } + else -> if (growing) circle.radius++ else circle.radius-- + } delay(16.milliseconds) } } } + +fun Stage.setupRects() { + val rect1 = roundRect(80.0, 100.0, 5.0, color = Colors.GREEN).position(820, 128) + val rect2 = roundRect(80.0, 100.0, 5.0, color = Colors.GREEN).position(1020, 128).anchor(0.5, 0.5) + addFixedUpdater(60.timesPerSecond) { + rect1.rotation += 1.degrees + rect2.rotation += 1.degrees + //no need for delay + //delay(16.milliseconds) + } +} + +fun T.interactive(): T = apply { + alpha = 0.5 + onOver { alpha = 1.0 } + onOut { alpha = 0.5 } +} diff --git a/spriteanim/src/commonMain/kotlin/Main.kt b/spriteanim/src/commonMain/kotlin/Main.kt index 7535b81..d641aa4 100644 --- a/spriteanim/src/commonMain/kotlin/Main.kt +++ b/spriteanim/src/commonMain/kotlin/Main.kt @@ -3,7 +3,6 @@ import com.soywiz.korev.* import com.soywiz.korge.* import com.soywiz.korge.input.* import com.soywiz.korge.view.* -import com.soywiz.korim.bitmap.* import com.soywiz.korim.format.* import com.soywiz.korio.file.std.* @@ -51,12 +50,12 @@ suspend fun main() = Korge(width = 512, height = 512) { ) val player1 = Sprite(spriteAnimationDown).apply { - scale(3) - xy(100,200) + scale(3.0) + xy(100, 200) } val player2 = Sprite(spriteAnimationDown).apply { - scale(3) - xy(100,100) + scale(3.0) + xy(100, 100) } addChild(player1) @@ -66,37 +65,34 @@ suspend fun main() = Korge(width = 512, height = 512) { val scale = 16.milliseconds / time val disp = 2 * scale val keys = views.input.keys - if (keys[Key.LEFT]) {player1.playAnimation(spriteAnimationLeft); player1.x-=disp } - if (keys[Key.RIGHT]) { player1.playAnimation(spriteAnimationRight); player1.x+=disp} - if (keys[Key.DOWN]) {player1.playAnimation(spriteAnimationDown); player1.y+=disp} - if (keys[Key.UP]) {player1.playAnimation(spriteAnimationUp); player1.y-=disp} - if (keys[Key.A]) {player2.playAnimation(spriteAnimationLeft); player2.x-=disp } - if (keys[Key.D]) { player2.playAnimation(spriteAnimationRight); player2.x+=disp} - if (keys[Key.S]) {player2.playAnimation(spriteAnimationDown); player2.y+=disp} - if (keys[Key.W]) {player2.playAnimation(spriteAnimationUp); player2.y-=disp} - if (keys[Key.L]) {player1.playAnimationLooped(spriteAnimationDown, 100.milliseconds)} - if (keys[Key.T]) {player1.playAnimation(spriteAnimation = spriteAnimationDown, times = 3, spriteDisplayTime = 200.milliseconds)} - if (keys[Key.C]) {player1.playAnimationForDuration(1.seconds, spriteAnimationDown); player1.y-=2} - if (keys[Key.ESCAPE]) {player1.stopAnimation()} + if (keys[Key.LEFT]) { player1.playAnimation(spriteAnimationLeft); player1.x-=disp } + if (keys[Key.RIGHT]) { player1.playAnimation(spriteAnimationRight); player1.x+=disp } + if (keys[Key.DOWN]) { player1.playAnimation(spriteAnimationDown); player1.y+=disp } + if (keys[Key.UP]) { player1.playAnimation(spriteAnimationUp); player1.y-=disp } + if (keys[Key.A]) { player2.playAnimation(spriteAnimationLeft); player2.x-=disp } + if (keys[Key.D]) { player2.playAnimation(spriteAnimationRight); player2.x+=disp } + if (keys[Key.S]) { player2.playAnimation(spriteAnimationDown); player2.y+=disp } + if (keys[Key.W]) { player2.playAnimation(spriteAnimationUp); player2.y-=disp } + if (keys[Key.L]) { player1.playAnimationLooped(spriteAnimationDown, 100.milliseconds) } + if (keys[Key.T]) { player1.playAnimation(spriteAnimation = spriteAnimationDown, times = 3, spriteDisplayTime = 200.milliseconds) } + if (keys[Key.C]) { player1.playAnimationForDuration(1.seconds, spriteAnimationDown); player1.y-=2 } + if (keys[Key.ESCAPE]) { player1.stopAnimation() } } - - //keys { - // onKeyDown{ - // when (it.key){ - // Key.LEFT -> {player1.playAnimation(spriteAnimationLeft); player1.x-=2 } - // Key.RIGHT ->{ player1.playAnimation(spriteAnimationRight); player1.x+=2} - // Key.DOWN -> {player1.playAnimation(spriteAnimationDown); player1.y+=2} - // Key.UP -> {player1.playAnimation(spriteAnimationUp); player1.y-=2} - // Key.A -> {player2.playAnimation(spriteAnimationLeft); player2.x-=2 } - // Key.D ->{ player2.playAnimation(spriteAnimationRight); player2.x+=2} - // Key.S -> {player2.playAnimation(spriteAnimationDown); player2.y+=2} - // Key.W -> {player2.playAnimation(spriteAnimationUp); player2.y-=2} - // Key.L -> {player1.playAnimationLooped(spriteAnimationDown, 100.milliseconds)} - // Key.T -> {player1.playAnimation(spriteAnimation = spriteAnimationDown, times = 3, spriteDisplayTime = 200.milliseconds)} - // Key.C -> {player1.playAnimationForDuration(1.seconds, spriteAnimationDown); player1.y-=2} - // Key.ESCAPE -> {player1.stopAnimation()} - // else -> {} - // } - // } - //} + /*onKeyDown { + when (it.key) { + Key.LEFT -> {player1.playAnimation(spriteAnimationLeft); player1.x-=2} + Key.RIGHT ->{player1.playAnimation(spriteAnimationRight); player1.x+=2} + Key.DOWN -> {player1.playAnimation(spriteAnimationDown); player1.y+=2} + Key.UP -> {player1.playAnimation(spriteAnimationUp); player1.y-=2} + Key.A -> {player2.playAnimation(spriteAnimationLeft); player2.x-=2} + Key.D -> {player2.playAnimation(spriteAnimationRight); player2.x+=2} + Key.S -> {player2.playAnimation(spriteAnimationDown); player2.y+=2} + Key.W -> {player2.playAnimation(spriteAnimationUp); player2.y-=2} + Key.L -> {player1.playAnimationLooped(spriteAnimationDown, 100.milliseconds)} + Key.T -> {player1.playAnimation(spriteAnimation = spriteAnimationDown, times = 3, spriteDisplayTime = 200.milliseconds)} + Key.C -> {player1.playAnimationForDuration(1.seconds, spriteAnimationDown); player1.y-=2} + Key.ESCAPE -> {player1.stopAnimation()} + else -> {} + } + }*/ } diff --git a/sprites10k/src/commonMain/kotlin/Main.kt b/sprites10k/src/commonMain/kotlin/Main.kt index 320b117..cc2cfbc 100644 --- a/sprites10k/src/commonMain/kotlin/Main.kt +++ b/sprites10k/src/commonMain/kotlin/Main.kt @@ -1,8 +1,5 @@ -import com.soywiz.klock.* import com.soywiz.klock.hr.hrMilliseconds -import com.soywiz.korev.* import com.soywiz.korge.* -import com.soywiz.korge.input.* import com.soywiz.korge.view.* import com.soywiz.korim.bitmap.* import com.soywiz.korim.format.* @@ -20,50 +17,45 @@ suspend fun main() = Korge(width = 1600, height = 1200) { val greenAnimations = animations(greenSpriteMap) val redAnimations = animations(redSpriteMap) - val greenSprites = Array(numberOfGreen) { - Sprite(greenAnimations[it % greenAnimations.size]).xy((10..1590).random(), (10..1190).random()).scale(2.0) + val greenSprites = Array(numberOfGreen) { + sprite(greenAnimations[it % greenAnimations.size]).xy((10..1590).random(), (10..1190).random()).scale(2.0) } - val redSprites = Array(numberOfRed) { - Sprite(redAnimations[it % redAnimations.size]).xy((10..1590).random(), (10..1190).random()).scale(2.0) + val redSprites = Array(numberOfRed) { + sprite(redAnimations[it % redAnimations.size]).xy((10..1590).random(), (10..1190).random()).scale(2.0) } - redSprites.forEach { - addChild(it) + greenSprites.forEachIndexed { index, sprite -> + sprite.playAnimationLooped(greenAnimations[index % greenAnimations.size]) } - - greenSprites.forEach { - addChild(it) + redSprites.forEachIndexed { index, sprite -> + sprite.playAnimationLooped(redAnimations[index % redAnimations.size]) } addHrUpdater { val scale = if (it == 0.hrMilliseconds) 0.0 else (it / 16.666666.hrMilliseconds) greenSprites.forEachIndexed { index, sprite -> - sprite.playAnimationLooped(greenAnimations[index % greenAnimations.size]).apply { walkdirection(sprite, index % greenAnimations.size, scale) } + sprite.walkDirection(index % greenAnimations.size, scale) } - redSprites.forEachIndexed { index, sprite -> - sprite.playAnimationLooped(redAnimations[index % redAnimations.size]).apply { walkdirection(sprite, index % redAnimations.size, scale) } - } - - } -} - -fun animations(spriteMap: Bitmap) = arrayOf( - SpriteAnimation(spriteMap,16,32,96,1,4,1), // left - SpriteAnimation(spriteMap,16,32,32,1,4,1), // right - SpriteAnimation(spriteMap,16,32,64,1,4,1), // up - SpriteAnimation(spriteMap,16,32,0,1,4,1)) // down - -fun walkdirection(sprite : Sprite, indexOfAnimation : Int, scale: Double = 1.0) { - sprite.apply { - val delta = 2 * scale - when (indexOfAnimation) { - 0 -> x-=delta - 1 -> x+=delta - 2 -> y-=delta - 3 -> y+=delta + sprite.walkDirection(index % redAnimations.size, scale) } } } + +fun animations(spriteMap: Bitmap) = arrayOf( + SpriteAnimation(spriteMap, 16, 32, 96, 1, 4, 1), // left + SpriteAnimation(spriteMap, 16, 32, 32, 1, 4, 1), // right + SpriteAnimation(spriteMap, 16, 32, 64, 1, 4, 1), // up + SpriteAnimation(spriteMap, 16, 32, 0, 1, 4, 1)) // down + +fun Sprite.walkDirection(indexOfAnimation: Int, scale: Double = 1.0) { + val delta = 2 * scale + when (indexOfAnimation) { + 0 -> x -= delta + 1 -> x += delta + 2 -> y -= delta + 3 -> y += delta + } +} diff --git a/tictactoe-swf/src/commonMain/kotlin/Board.kt b/tictactoe-swf/src/commonMain/kotlin/Board.kt index b111f4b..5aded74 100644 --- a/tictactoe-swf/src/commonMain/kotlin/Board.kt +++ b/tictactoe-swf/src/commonMain/kotlin/Board.kt @@ -4,7 +4,7 @@ import com.soywiz.korma.geom.* 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() { + class Cell(x: Int, y: Int) : Extra by Extra.Mixin() { val pos = PointInt(x, y) var value = Chip.EMPTY } @@ -19,7 +19,7 @@ class Board(val width: Int = 3, val height: Int = width, val lineSize: Int = wid return (0 until size).map { cells[x + dx * it, y + dy * it] } } - val lines = kotlin.collections.ArrayList>() + val lines = ArrayList>() init { fun addLine(line: List?) { @@ -48,15 +48,13 @@ class Board(val width: Int = 3, val height: Int = width, val lineSize: Int = wid val winnerLine: List? get() { - val out = kotlin.collections.ArrayList() + val out = 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 - } + get() = winnerLine?.firstOrNull()?.value } fun Board(str: String): Board { diff --git a/tictactoe-swf/src/commonMain/kotlin/BoardMediator.kt b/tictactoe-swf/src/commonMain/kotlin/BoardMediator.kt index f10221e..8d906d7 100644 --- a/tictactoe-swf/src/commonMain/kotlin/BoardMediator.kt +++ b/tictactoe-swf/src/commonMain/kotlin/BoardMediator.kt @@ -9,7 +9,6 @@ import com.soywiz.korma.interpolation.* import kotlin.coroutines.* 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) { diff --git a/tictactoe-swf/src/commonMain/kotlin/main.kt b/tictactoe-swf/src/commonMain/kotlin/main.kt index e2e440d..7b1ce2b 100644 --- a/tictactoe-swf/src/commonMain/kotlin/main.kt +++ b/tictactoe-swf/src/commonMain/kotlin/main.kt @@ -1,7 +1,6 @@ import com.soywiz.korge.* import com.soywiz.korge.animate.* import com.soywiz.korge.animate.serialization.* -import com.soywiz.korge.ext.swf.* import com.soywiz.korge.input.* import com.soywiz.korge.scene.* import com.soywiz.korge.view.* @@ -72,12 +71,10 @@ class TicTacToeMainScene : Scene() { } } sceneView += results - results["hit"]?.mouse?.onClick?.waitOne() + results["hit"]?.mouse?.click?.waitOne() //sceneView -= results results.removeFromParent() - } - } } @@ -134,6 +131,5 @@ class InteractivePlayer(val board: Board, override val chip: Chip) : Player { } override suspend fun move(): PointInt = clicked.waitOne() - } diff --git a/triangulation/src/commonMain/kotlin/main.kt b/triangulation/src/commonMain/kotlin/main.kt index 6dc4504..5095cb3 100644 --- a/triangulation/src/commonMain/kotlin/main.kt +++ b/triangulation/src/commonMain/kotlin/main.kt @@ -9,13 +9,13 @@ import com.soywiz.korma.triangle.triangulate.* suspend fun main() = Korge(width = 512, height = 512) { val stage = this - text("Add Points by clicking with the mouse") + text("Add Points by clicking with the mouse", 14.0).position(5.0, 5.0) graphics { val graphics = this graphics.useNativeRendering = false position(100, 100) - val points = arrayListOf() + val points = arrayListOf() var additionalPoint: Point? = null @@ -56,7 +56,7 @@ suspend fun main() = Korge(width = 512, height = 512) { for (n in 0 until edges.size - 1) { val e0 = Point(edges[n]) val e1 = Point(edges[n + 1]) - var last = n == edges.size - 2 + val last = n == edges.size - 2 stroke(if (last) Colors.RED else Colors.BLUE, Context2d.StrokeInfo(thickness = 2.0)) { line(e0, e1) } @@ -64,13 +64,13 @@ suspend fun main() = Korge(width = 512, height = 512) { } stage.mouse { - onClick { e -> + onClick { points.add(graphics.localMouseXY(views)) repaint(finished = true) //println("CLICK") } - onMove { e -> + onMove { additionalPoint = graphics.localMouseXY(views) repaint(finished = false) } diff --git a/ui/src/commonMain/kotlin/SampleUi.kt b/ui/src/commonMain/kotlin/SampleUi.kt index b58c43b..9c1c8c5 100644 --- a/ui/src/commonMain/kotlin/SampleUi.kt +++ b/ui/src/commonMain/kotlin/SampleUi.kt @@ -1,30 +1,26 @@ import com.soywiz.klock.* import com.soywiz.korge.* +import com.soywiz.korge.font.* import com.soywiz.korge.html.* import com.soywiz.korge.input.* -import com.soywiz.korge.ui.* -import com.soywiz.korge.render.* -import com.soywiz.korge.scene.* +import com.soywiz.korge.service.process.* import com.soywiz.korge.tween.* +import com.soywiz.korge.ui.* import com.soywiz.korge.view.* import com.soywiz.korgw.* import com.soywiz.korim.bitmap.* import com.soywiz.korim.color.* -import com.soywiz.korim.font.* import com.soywiz.korim.format.* -import com.soywiz.korio.async.* -import com.soywiz.korio.file.* import com.soywiz.korio.file.std.* -import com.soywiz.korio.net.* import com.soywiz.korio.util.* import com.soywiz.korma.interpolation.* suspend fun main() = Korge(quality = GameWindow.Quality.PERFORMANCE, title = "UI") { val nativeProcess = NativeProcess(views) - //uiSkin(OtherUISkin()) { defaultUISkin = OtherUISkin() defaultUIFont = Html.FontFace.Bitmap(resourcesVfs["uifont.fnt"].readBitmapFontWithMipmaps()) + textButton(256.0, 32.0) { text = "Disabled Button" position(128, 128) @@ -42,6 +38,7 @@ suspend fun main() = Korge(quality = GameWindow.Quality.PERFORMANCE, title = "UI } enable() } + uiScrollBar(256.0, 32.0, 0.0, 32.0, 64.0) { position(64, 64) onChange { @@ -66,7 +63,6 @@ suspend fun main() = Korge(quality = GameWindow.Quality.PERFORMANCE, title = "UI uiScrollableArea(config = { position(480, 128) }) { - for (n in 0 until 16) { textButton(text = "HELLO $n").position(0, n * 64) } @@ -104,19 +100,3 @@ suspend fun OtherUISkin(): UISkin = OtherUISkinOnce { //font = Html.FontFace.Bitmap(resourcesVfs["uifont.fnt"].readBitmapFontWithMipmaps()) ) } - -private suspend fun VfsFile.readBitmapFontWithMipmaps(imageFormat: ImageFormat = RegisteredImageFormats, mipmaps: Boolean = true): BitmapFont = - readBitmapFont(imageFormat).also { it.atlas.mipmaps(mipmaps) } - - -private class NativeProcess(views: Views) : NativeProcessBase(views) { -} - -private open class NativeProcessBase(val views: Views) { - open suspend fun alert(message: String) = views.gameWindow.alert(message) - open suspend fun confirm(message: String): Boolean = views.gameWindow.confirm(message) - open suspend fun openFileDialog(filter: String? = null, write: Boolean = false, multi: Boolean = false) = views.gameWindow.openFileDialog(filter, write, multi) - open suspend fun browse(url: URL) = views.gameWindow.browse(url) - open suspend fun close() = views.gameWindow.close() -} -