diff --git a/Exercises/Drop/android/src/main/kotlin/com/badlogic/drop/android/AndroidLauncher.kt b/Exercises/Drop/android/src/main/kotlin/com/badlogic/drop/android/AndroidLauncher.kt index 5f6f1d9..b9b115a 100644 --- a/Exercises/Drop/android/src/main/kotlin/com/badlogic/drop/android/AndroidLauncher.kt +++ b/Exercises/Drop/android/src/main/kotlin/com/badlogic/drop/android/AndroidLauncher.kt @@ -1,16 +1,16 @@ package com.badlogic.drop.android import android.os.Bundle +import com.badlogic.drop.Drop import com.badlogic.gdx.backends.android.AndroidApplication import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration -import com.badlogic.drop.Main /** Launches the Android application. */ class AndroidLauncher : AndroidApplication() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - initialize(Main(), AndroidApplicationConfiguration().apply { + initialize(Drop(), AndroidApplicationConfiguration().apply { // Configure your application here. useImmersiveMode = true // Recommended, but not required. }) diff --git a/Exercises/Drop/core/src/main/kotlin/com/badlogic/drop/Drop.kt b/Exercises/Drop/core/src/main/kotlin/com/badlogic/drop/Drop.kt new file mode 100644 index 0000000..3e08317 --- /dev/null +++ b/Exercises/Drop/core/src/main/kotlin/com/badlogic/drop/Drop.kt @@ -0,0 +1,34 @@ +package com.badlogic.drop + +import com.badlogic.gdx.Game +import com.badlogic.gdx.Gdx +import com.badlogic.gdx.graphics.g2d.BitmapFont +import com.badlogic.gdx.graphics.g2d.SpriteBatch +import com.badlogic.gdx.utils.viewport.FitViewport + +class Drop : Game() { + lateinit var batch: SpriteBatch + lateinit var font: BitmapFont + //lateinit var viewport: FitViewport // Use camera instead of viewport + + override fun create(): Unit { + batch = SpriteBatch() + //viewport = FitViewport(8f, 5f) + /*font = BitmapFont().apply { + setUseIntegerPositions(false) + data.scale(viewport.worldHeight / Gdx.graphics.height) + }*/ + font = BitmapFont() + + this.screen = MainMenuScreen(this) + } + + override fun render() { + super.render() + } + + override fun dispose() { + batch.dispose() + font.dispose() + } +} diff --git a/Exercises/Drop/core/src/main/kotlin/com/badlogic/drop/GameScreen.kt b/Exercises/Drop/core/src/main/kotlin/com/badlogic/drop/GameScreen.kt new file mode 100644 index 0000000..cc78c47 --- /dev/null +++ b/Exercises/Drop/core/src/main/kotlin/com/badlogic/drop/GameScreen.kt @@ -0,0 +1,146 @@ +package com.badlogic.drop + +import com.badlogic.gdx.Gdx +import com.badlogic.gdx.Screen +import com.badlogic.gdx.graphics.Texture +import com.badlogic.gdx.graphics.OrthographicCamera +import com.badlogic.gdx.Gdx.audio +import com.badlogic.gdx.Input +import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.graphics.g2d.Sprite +import com.badlogic.gdx.math.MathUtils +import com.badlogic.gdx.math.Rectangle +import com.badlogic.gdx.math.Vector2 +import com.badlogic.gdx.math.Vector3 +import com.badlogic.gdx.utils.ScreenUtils +import ktx.assets.toInternalFile + +class GameScreen(val game: Drop) : Screen { + val camera = OrthographicCamera().apply { setToOrtho(false, 800f, 480f) } + + val backgroundTexture = Texture("background.png") + val bucketTexture = Texture("bucket.png") + val dropTexture = Texture("drop.png") + val dropSound = audio.newSound("drop.mp3".toInternalFile()) + val music = audio.newMusic("music.mp3".toInternalFile()).apply { + isLooping = true + volume = 0.5f + } + val bucketSprite = Sprite(bucketTexture).apply { setSize(64f, 64f) } + val touchPos = Vector3() + val dropSprites = mutableListOf() + val dropSpeed = -128f + var dropTimer = 0f + val bucketRectangle = Rectangle() + val dropRectangle = Rectangle() + var dropsGathered = 0 + + override fun show() { + music.play() + } + + override fun render(delta: Float) { + input() + logic() + draw() + } + + private fun input() { + val speed = 4f + val delta: Float = Gdx.graphics.deltaTime + + if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) { + bucketSprite.translateX(speed * delta) + } + if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) { + bucketSprite.translateX(-speed * delta) + } + + if (Gdx.input.isTouched) { + touchPos.set(Gdx.input.x.toFloat(), Gdx.input.y.toFloat(), 0f) + camera.unproject(touchPos) + bucketSprite.setCenterX(touchPos.x) + } + } + + private fun logic() { + val worldWidth: Float = camera.viewportWidth + val worldHeight: Float = camera.viewportHeight + val bucketWidth: Float = bucketSprite.width + val bucketHeight: Float = bucketSprite.height + val delta: Float = Gdx.graphics.deltaTime + + bucketSprite.x = MathUtils.clamp(bucketSprite.x, 0f, worldWidth - bucketWidth) + bucketRectangle.set(bucketSprite.x, bucketSprite.y, bucketWidth, bucketHeight) + + for (dropSprite in dropSprites.reversed()) { + val dropWidth: Float = dropSprite.width + val dropHeight: Float = dropSprite.height + + dropSprite.translateY(dropSpeed * delta * (MathUtils.clamp((dropsGathered.toFloat() + 1f) / 5f, 1f, Float.MAX_VALUE))) + dropRectangle.set(dropSprite.x, dropSprite.y, dropWidth, dropHeight) + + if (dropSprite.y < -dropHeight) dropSprites.remove(dropSprite) + else if (bucketRectangle.overlaps(dropRectangle)) { + dropsGathered++ + dropSprites.remove(dropSprite) + dropSound.play() + } + } + + dropTimer += delta + if (dropTimer > 1f) { + dropTimer = 0f + createDroplet() + } + } + + private fun draw() { + ScreenUtils.clear(Color.BLACK) + + camera.update() + game.batch.projectionMatrix = camera.combined + + game.batch.begin() + val worldWidth: Float = camera.viewportWidth + val worldHeight: Float = camera.viewportHeight + game.batch.draw(backgroundTexture, 0f, 0f, worldWidth, worldHeight) + bucketSprite.draw(game.batch) + + game.font.draw(game.batch, "Drops collected: $dropsGathered", 0f, worldHeight) + + for (dropSprite in dropSprites) dropSprite.draw(game.batch) + + game.batch.end() + } + + private fun createDroplet() { + val dropWidth = 64f + val dropHeight = 64f + val worldWidth: Float = camera.viewportWidth + val worldHeight: Float = camera.viewportHeight + + val dropSprite = Sprite(dropTexture).apply { + setSize(dropWidth, dropHeight) + x = MathUtils.random(0f, worldWidth - dropWidth) + y = worldHeight + } + dropSprites.add(dropSprite) + } + + override fun resize(width: Int, height: Int) = Unit + + override fun pause() = Unit + + override fun resume() = Unit + + override fun hide() = Unit + + override fun dispose() { + backgroundTexture.dispose() + dropSound.dispose() + music.dispose() + dropTexture.dispose() + bucketTexture.dispose() + } +} diff --git a/Exercises/Drop/core/src/main/kotlin/com/badlogic/drop/Main.kt b/Exercises/Drop/core/src/main/kotlin/com/badlogic/drop/Main.kt deleted file mode 100644 index 88d0b95..0000000 --- a/Exercises/Drop/core/src/main/kotlin/com/badlogic/drop/Main.kt +++ /dev/null @@ -1,138 +0,0 @@ -package com.badlogic.drop - -import com.badlogic.gdx.Gdx -import com.badlogic.gdx.Gdx.audio -import com.badlogic.gdx.audio.Music -import com.badlogic.gdx.audio.Sound -import com.badlogic.gdx.graphics.Color -import com.badlogic.gdx.graphics.Texture -import com.badlogic.gdx.graphics.Texture.TextureFilter.Linear -import com.badlogic.gdx.graphics.g2d.Sprite -import com.badlogic.gdx.graphics.g2d.SpriteBatch -import com.badlogic.gdx.math.MathUtils -import com.badlogic.gdx.math.Rectangle -import com.badlogic.gdx.math.Vector2 -import com.badlogic.gdx.utils.ScreenUtils -import com.badlogic.gdx.utils.viewport.FitViewport -import ktx.app.KtxGame -import ktx.app.KtxScreen -import ktx.assets.disposeSafely -import ktx.assets.toInternalFile -import ktx.async.KtxAsync -import ktx.graphics.use - -class Main : KtxGame() { - override fun create() { - KtxAsync.initiate() - - addScreen(FirstScreen()) - setScreen() - } - class FirstScreen : KtxScreen { - private val backgroundTexture: Texture = Texture("background.png".toInternalFile(), true).apply { setFilter(Linear, Linear) } - private val bucketTexture: Texture = Texture("bucket.png".toInternalFile(), true).apply { setFilter(Linear, Linear) } - private val dropTexture: Texture = Texture("drop.png".toInternalFile(), true).apply { setFilter(Linear, Linear) } - - private val dropSound: Sound = audio.newSound("drop.mp3".toInternalFile()) - private val music: Music = audio.newMusic("music.mp3".toInternalFile()).apply { - isLooping = true - volume = 0.5f - play() - } - - private val bucketSprite: Sprite = Sprite(bucketTexture).apply { setSize(1f, 1f) } - - private val image = Texture("logo.png".toInternalFile(), true).apply { setFilter(Linear, Linear) } - private val batch = SpriteBatch() - private val viewport = FitViewport(8f, 5f) - - private var touchPos: Vector2 = Vector2() - - private var dropletSpriteList: MutableList = mutableListOf() - - private var dropTimer: Float = 0f - - private val bucketRectangle: Rectangle = Rectangle() - private val dropletRectangle: Rectangle = Rectangle() - - override fun resize(width: Int, height: Int) { - viewport.update(width, height, true) - } - - override fun render(delta: Float) { - input() - logic() - draw() - } - - override fun dispose() { - image.disposeSafely() - batch.disposeSafely() - } - - private fun input() { - if (Gdx.input.isTouched) { - touchPos.set(Gdx.input.x.toFloat(), Gdx.input.y.toFloat()) - viewport.unproject(touchPos) - bucketSprite.setCenterX(touchPos.x) - } - } - - private fun logic() { - val worldWidth: Float = viewport.worldWidth - - bucketSprite.x = MathUtils.clamp(bucketSprite.x, 0f, worldWidth - bucketSprite.width) - - val delta: Float = Gdx.graphics.deltaTime - bucketRectangle.set(bucketSprite.x, bucketSprite.y, bucketSprite.width, bucketSprite.height) - - for (sprite in dropletSpriteList.reversed()) { - sprite.translateY(-2f * delta) - - dropletRectangle.set(sprite.x, sprite.y, sprite.width, sprite.height) - - if (sprite.y < -sprite.height) dropletSpriteList.remove(sprite) - else if (bucketRectangle.overlaps(dropletRectangle)) { - dropletSpriteList.remove(sprite) - dropSound.play() - } - } - - dropTimer += delta - if (dropTimer >= 1f) - { - dropTimer = 0f - dropletSpriteList.add(createDroplet()) - } - //Gdx.app.log("Droplets", dropletSpriteList.size.toString() + " in List") - } - - private fun draw() { - ScreenUtils.clear(Color.BLACK) - viewport.apply() - batch.setProjectionMatrix(viewport.camera.combined) - batch.use { - it.draw(backgroundTexture, 0f, 0f, viewport.worldWidth, viewport.worldHeight) - for (s in dropletSpriteList) { - s.draw(it) - } - bucketSprite.draw(it) - } - } - - private fun createDroplet(): Sprite { - val dropWidth: Float = 1f - val dropHeight: Float = 1f - val worldWidth: Float = viewport.worldWidth - val worldHeight: Float = viewport.worldHeight - - val dropSprite: Sprite = Sprite(dropTexture).apply { - setSize(dropWidth, dropHeight) - x = MathUtils.random(0f, worldWidth - dropWidth) - y = worldHeight //- dropHeight // Spawn droplet above world for cleaner transition in? - } // We don't add the object to the set here because apply is really meant for doing stuff with members - - return dropSprite - } - } -} diff --git a/Exercises/Drop/core/src/main/kotlin/com/badlogic/drop/MainMenuScreen.kt b/Exercises/Drop/core/src/main/kotlin/com/badlogic/drop/MainMenuScreen.kt new file mode 100644 index 0000000..2a47d11 --- /dev/null +++ b/Exercises/Drop/core/src/main/kotlin/com/badlogic/drop/MainMenuScreen.kt @@ -0,0 +1,48 @@ +package com.badlogic.drop + +import com.badlogic.gdx.Screen +import com.badlogic.gdx.Gdx +import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.graphics.OrthographicCamera +import com.badlogic.gdx.utils.ScreenUtils + +class MainMenuScreen(val game: Drop) : Screen { + private val camera = OrthographicCamera() + + init { + camera.setToOrtho(false, 800f, 480f) + } + + override fun show() = Unit + + override fun render(delta: Float) { + ScreenUtils.clear(Color.BLACK) + + //game.viewport.apply() + //game.batch.projectionMatrix = game.viewport.camera.combined + camera.update() + game.batch.projectionMatrix = camera.combined + + game.batch.begin() + + game.font.draw(game.batch, "Welcome to Drop!!!", 100f, 150f) + game.font.draw(game.batch, "Tap anywhere to begin!", 100f, 100f) + + game.batch.end() + + if (Gdx.input.isTouched) { + game.screen = GameScreen(game) + } + + } + + override fun resize(width: Int, height: Int) = Unit + + override fun pause() = Unit + + override fun resume() = Unit + + override fun hide() = Unit + + override fun dispose() = Unit +}