Skip to content

Commit

Permalink
Fighter
Browse files Browse the repository at this point in the history
  • Loading branch information
lasanthak committed Sep 3, 2023
1 parent 3ca8f66 commit f72244d
Show file tree
Hide file tree
Showing 67 changed files with 97 additions and 55 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Animation graphics project using JavaFX and Kotlin.
* [Asteroids](https://github.com/Seif-Sallam/Asteroids/tree/master/Astroids/rsc) by Seif-Sallam.
* Earth [sprite sheet](https://support.singular.live/hc/en-us/articles/360025546472-Sprite-Sheet).
* [Moon sprite](https://gold356.itch.io/moon-sprite-sheet-32-x-32) by Gold356.
* [endless-sky](https://github.com/endless-sky/endless-sky) project.
* Music
* [Return](https://pixabay.com/music/upbeat-return-120581/) by nojisuma.
* [Supernatural Explosion](https://pixabay.com/sound-effects/supernatural-explosion-104295/) by Pixabay.
25 changes: 25 additions & 0 deletions src/main/kotlin/org/lasantha/fxplanets/AppConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.lasantha.fxplanets

import kotlin.random.Random

class AppConfig {
companion object {
//60 fps -> frame duration 17 ms
//50 fps -> frame duration 20 ms
//40 fps -> frame duration 25 ms
//33 fps -> frame duration 30 ms
//25 fps -> frame duration 40 ms
var fps = 60

var fxRandom: Random = Random.Default

var mainAudioEnabled = false
var soundEnabled = true
var musicEnabled = true

var width = 1600.0
var height = 1200.0

var debug = true
}
}
24 changes: 11 additions & 13 deletions src/main/kotlin/org/lasantha/fxplanets/FXShape.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ class FXShape(
private val gc: GraphicsContext,
private val image: ImageWrapper,
private val locator: FXLocator,
private val clipW: Double = image.width,
private val clipH: Double = image.height
) {
private var running = true

Expand All @@ -19,8 +17,8 @@ class FXShape(
private var lastX = Double.NaN
private var lastY = Double.NaN

private val clipHalfW = clipW / 2.0
private val clipHalfH = clipH / 2.0
private val halfW = image.width / 2.0
private val halfH = image.height / 2.0

fun update(time: Long) {
if (running(time)) {
Expand Down Expand Up @@ -59,33 +57,33 @@ class FXShape(

fun clipBox(target: FXShape): Boolean {
val xClips = if (x < target.getX()) {
target.getX() - x < clipW
target.getX() - x < image.width
} else {
x - target.getX() < target.clipW
x - target.getX() < target.image.width
}

if (xClips) {
return if (y < target.getY()) {
target.getY() - y < clipH
target.getY() - y < image.height
} else {
y - target.getY() < target.clipH
y - target.getY() < target.image.height
}
}

return false
}

fun clipCircle(target: FXShape): Boolean =
((x - target.getX()).pow(2) + (y - target.getY()).pow(2)) < (clipHalfH + target.clipHalfH).pow(2)
((x - target.getX()).pow(2) + (y - target.getY()).pow(2)) < (halfH + target.halfH).pow(2)

fun getX() = x
fun getY() = y

fun getCenterX() = x + clipHalfW
fun getCenterY() = y + clipHalfH
fun getCenterX() = x + halfW
fun getCenterY() = y + halfH

fun mapX(centerX: Double) = centerX - clipHalfW
fun mapY(centerY: Double) = centerY - clipHalfH
fun mapX(centerX: Double) = centerX - halfW
fun mapY(centerY: Double) = centerY - halfH

override fun toString(): String =
"${javaClass.simpleName}{name=$name, x=${String.format("%.2f", x)}, y=${String.format("%.2f", y)}}"
Expand Down
44 changes: 36 additions & 8 deletions src/main/kotlin/org/lasantha/fxplanets/ImageLib.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import javafx.scene.image.Image
import javafx.scene.image.WritableImage

class ImageLib {
val sun = StaticImage(image("sun.png"))
val fighter = run {
val r = image("fighter.png").pixelReader
LRLoopImage(duration = 100,
frames = Array(7) { i -> WritableImage(r, i * 64, 0, 64, 64) })
}

val sun = StaticImage(WritableImage(image("sun.png").pixelReader, 4, 4, 80, 80))

val planet = StaticImage(image("planet1.png"))

Expand Down Expand Up @@ -36,17 +42,20 @@ class ImageLib {
val r1 = image("rock1.png").pixelReader
val r2 = image("rock2.png").pixelReader
val r3r = Array(48) { image("rock3/$it.png").pixelReader }
val r4r = Array(60) { image("rock4/$it.png").pixelReader }
val blr = Array(60) { image("blob/$it.png").pixelReader }
val shr = Array(6) { image("ship/s${it + 1}.png").pixelReader }
listOf(
MultiLoopImage(100, Array(16) { WritableImage(r1, (it * 64) + 11, 11, 40, 40) }),
MultiLoopImage(100, Array(16) { WritableImage(r1, (15 - it) * 64 + 11, 11, 40, 40) }),
MultiLoopImage(100, Array(16) { WritableImage(r1, (it * 64) + 15, 15, 34, 34) }),
MultiLoopImage(100, Array(16) { WritableImage(r1, (15 - it) * 64 + 15, 15, 34, 34) }),
MultiLoopImage(100, Array(16) { WritableImage(r2, it * 32, 0, 32, 32) }),
MultiLoopImage(100, Array(16) { WritableImage(r2, (15 - it) * 32, 0, 32, 32) }),
MultiLoopImage(70, Array(48) { i -> WritableImage(r3r[i], 2, 2, 36, 36) }),
MultiLoopImage(70, Array(48) { i -> WritableImage(r3r[47 - i], 2, 2, 36, 36) }),
MultiLoopImage(50, Array(60) { i -> WritableImage(blr[i], 9, 14, 42, 42) }),
MultiLoopImage(100, Array(6) { i -> image("ship/s${i + 1}.png") }),
)
MultiLoopImage(70, Array(48) { WritableImage(r3r[it], 2, 2, 36, 36) }),
MultiLoopImage(70, Array(48) { WritableImage(r3r[47 - it], 2, 2, 36, 36) }),
MultiLoopImage(50, Array(60) { WritableImage(r4r[it], 1, 1, 38, 38) }),
MultiLoopImage(50, Array(60) { WritableImage(blr[it], 9, 14, 42, 42) }),
MultiLoopImage(100, Array(6) { WritableImage(shr[it], 0, 5, 39, 28) }),
).shuffled(AppConfig.fxRandom)
}

fun bgImage(): Image = image("space.png")
Expand Down Expand Up @@ -111,3 +120,22 @@ class SingleLoopImage(private val startTime: Long, private val duration: Long, p

override fun frame(time: Long) = frames[((time - startTime).coerceAtLeast(0) / duration).toInt()]
}

class LRLoopImage(private val duration: Long, private val frames: Array<Image>) : ImageWrapper {
init {
assert(duration > 0)
assert(frames.isNotEmpty())
assert(frames.size % 2 == 1)
val w = frames[0].width.toInt()
val h = frames[0].height.toInt()
for (f in frames) {
assert(w == f.width.toInt())
assert(h == f.height.toInt())
}
}

override val width = frames[0].width
override val height = frames[0].height

override fun frame(time: Long) = frames[frames.size / 2]
}
58 changes: 24 additions & 34 deletions src/main/kotlin/org/lasantha/fxplanets/PlanetsApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,6 @@ import kotlin.math.cos
import kotlin.math.sin
import kotlin.random.Random

object AppConfig {
//60 fps -> frame duration 17 ms
//50 fps -> frame duration 20 ms
//40 fps -> frame duration 25 ms
//33 fps -> frame duration 30 ms
//25 fps -> frame duration 40 ms
var fps = 60

var mainAudioEnabled = false
var soundEnabled = true
var musicEnabled = true

var width = 1400.0
var height = 1000.0

var debug = true
}

class PlanetsApp : Application() {
private val scopeThreads = Executors.newFixedThreadPool(2, GameThreadFactory())
private val scopeJobs = Job()
Expand Down Expand Up @@ -131,13 +113,19 @@ class PlanetsApp : Application() {
}
}

val fighterShape = FXShape("Fighter", gc, imageLib.fighter, object : FXLocator {
override fun location(time: Long, shape: FXShape): Pair<Double, Double> =
centerX - imageLib.fighter.width / 2.0 to AppConfig.height - 100.0
})

val sunShape = FXShape("Sun", gc, imageLib.sun, object : FXLocator {
override fun location(time: Long, shape: FXShape): Pair<Double, Double> = centerX to centerY
}, clipW = 40.0, clipH = 40.0)
override fun location(time: Long, shape: FXShape): Pair<Double, Double> =
centerX - imageLib.sun.width / 2.0 to centerY - imageLib.sun.height / 2.0
})

val earthShape = FXShape("Earth", gc, imageLib.earth, object : FXLocator {
val r = 320.0
val phase = fxRandom.nextDouble() * 7.2
val phase = AppConfig.fxRandom.nextDouble() * 7.2
override fun location(time: Long, shape: FXShape): Pair<Double, Double> {
val t = time * 0.00073
return (centerX + r * cos(t + phase) * 1.5) to (centerY + r * sin(t + phase))
Expand All @@ -146,7 +134,7 @@ class PlanetsApp : Application() {

val moonShape = FXShape("Moon", gc, imageLib.moon, object : FXLocator {
private val r = 45.0
private val phase = fxRandom.nextDouble() * 7.2
private val phase = AppConfig.fxRandom.nextDouble() * 7.2
override fun location(time: Long, shape: FXShape): Pair<Double, Double> {
val t = time * 0.00377
return (earthShape.getX() + r * cos(t + phase)) to (earthShape.getY() + r * sin(t + phase) * 1.5)
Expand All @@ -155,7 +143,7 @@ class PlanetsApp : Application() {

val planetShape = FXShape("Planet", gc, imageLib.planet, object : FXLocator {
private val r = 145.0
private val phase = fxRandom.nextDouble() * 0.0072
private val phase = AppConfig.fxRandom.nextDouble() * 0.0072
override fun location(time: Long, shape: FXShape): Pair<Double, Double> {
val t = time * -0.0011
return (centerX + r * cos(t + phase)) to (centerY + r * sin(t + phase) * 1.9)
Expand All @@ -167,7 +155,8 @@ class PlanetsApp : Application() {
val collisionMap = mutableMapOf<FXShape, FXShape>()

longLivedShapes.addAll(listOf(sunShape, moonShape, earthShape, planetShape))
collidingShapes.addAll(listOf(planetShape))
shortLivedShapes.addAll(listOf(fighterShape))
collidingShapes.addAll(listOf(planetShape, fighterShape))

var lastLinearT = 0L
var nextAsteroidTick = 1500L
Expand Down Expand Up @@ -212,7 +201,7 @@ class PlanetsApp : Application() {
}

if (linearT > nextAsteroidTick) {
nextAsteroidTick = linearT + 5000 + fxRandom.nextLong(5000)
nextAsteroidTick = linearT + 5000 + AppConfig.fxRandom.nextLong(5000)
val a = randomAsteroid(linearT, gc)
shortLivedShapes.add(a)
collidingShapes.add(a)
Expand Down Expand Up @@ -254,19 +243,19 @@ class PlanetsApp : Application() {

private fun asteroidLocator(startTime: Long): FXLocator {
fun locFun(maxLen: Double, forward: Boolean, add: Boolean): (time: Long, shape: FXShape) -> Double {
val v = 0.05 + 0.1 * fxRandom.nextDouble()
val c = if (add) (maxLen * 0.8 * fxRandom.nextDouble()) else 0.0
val v = 0.05 + 0.1 * AppConfig.fxRandom.nextDouble()
val c = if (add) (maxLen * 0.8 * AppConfig.fxRandom.nextDouble()) else 0.0
return if (forward) {
{ time, _ -> c + v * (time - startTime) }
} else {
{ time, _ -> maxLen - c - (v * (time - startTime)) }
}
}

val addC = fxRandom.nextBoolean()
val addC = AppConfig.fxRandom.nextBoolean()
return object : FXLocator {
private val fx = locFun(AppConfig.width, fxRandom.nextBoolean(), addC)
private val fy = locFun(AppConfig.height, fxRandom.nextBoolean(), !addC)
private val fx = locFun(AppConfig.width, AppConfig.fxRandom.nextBoolean(), addC)
private val fy = locFun(AppConfig.height, AppConfig.fxRandom.nextBoolean(), !addC)

override fun location(time: Long, shape: FXShape): Pair<Double, Double> = fx(time, shape) to fy(time, shape)

Expand All @@ -276,12 +265,13 @@ class PlanetsApp : Application() {
}

private fun randomAsteroid(startTime: Long, gc: GraphicsContext): FXShape {
val image = imageLib.rocks[fxRandom.nextInt(imageLib.rocks.size)]
val image = imageLib.rocks[AppConfig.fxRandom.nextInt(imageLib.rocks.size)]
return FXShape("UFO-$startTime", gc, image, asteroidLocator(startTime))
}

private fun randomExplosion(s1: FXShape, s2: FXShape, startTime: Long, gc: GraphicsContext): FXShape {
val image = if (fxRandom.nextBoolean()) imageLib.explosion1(startTime) else imageLib.explosion2(startTime)
val image = if (AppConfig.fxRandom.nextBoolean()) imageLib.explosion1(startTime)
else imageLib.explosion2(startTime)
return FXShape("Explosion<${s1.name}, ${s2.name}>", gc, image, object : FXLocator {
override fun location(time: Long, shape: FXShape): Pair<Double, Double> =
shape.mapX(s2.getCenterX()) to shape.mapY(s2.getCenterY())
Expand Down Expand Up @@ -314,9 +304,9 @@ class PlanetsApp : Application() {
}
}

lateinit var fxRandom: Random


fun main() {
fxRandom = Random(666) // 62439, 234
AppConfig.fxRandom = Random(666) // 62439, 234
Application.launch(PlanetsApp::class.java)
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/main/resources/org/lasantha/fxplanets/img/sun.png

0 comments on commit f72244d

Please sign in to comment.