Merge simple-game-extended into main #1

Merged
snap merged 2 commits from simple-game-extended into main 2026-02-07 00:14:06 +00:00
5 changed files with 230 additions and 140 deletions

View File

@@ -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.
})

View File

@@ -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()
}
}

View File

@@ -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<Sprite>()
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()
}
}

View File

@@ -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<KtxScreen>() {
override fun create() {
KtxAsync.initiate()
addScreen(FirstScreen())
setScreen<FirstScreen>()
}
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<Sprite> = 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
}
}
}

View File

@@ -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
}