Skip to content

AIO Lasers

XiaoGeNintendo edited this page Oct 9, 2021 · 3 revisions

AIO Laser is a newly-added feature in TestSTG5. It brings support for curvy lasers and moving lasers. It even supports laser breaking just like Zun!!

How it works

AIO laser is a chain list of normal bullets. A bullet without previous node is called a laser head.By attaching the same task to different nodes, they move like one.

Render is done by iterating the laser of a laser head.

How to use

Call this API:

//STG.kt

/**
 * Create an All-in-one(AIO) laser
 */
suspend fun laser(
    env: CoroutineTask,
    width: Float,
    length: Float,
    hitPercent: Float = 0.8f, //hitbox width compared to render width
    verticalMargin: Float = 10f, //hitbox height compared to render height (*inaccurate)
    maxSample: Int = 512, //max sample nodes used to create this laser
    sampleDelay: Int = 1, //delay between samples (frame)
    color: Color = RED_HSV,
    /**
     * After how many frames will this node start to be considered stable
     *
     * A stable node can be removed if it is moribund
     */
    protectionFrame: Int = 20,
    /**
     * The task to create the laser. The given parameter is laser index. (Should not be used anyway)
     */
    creationTask: (Int) -> BasicBullet
) {
    ...
}

Bombing Laser

You can break lasers apart by using a bomb. This can bring some interesting effects like in official Touhou games.

Please note that this feature has several bugs, including: laser body misposition, extra laser being generated, wrong animation and hitbox etc

Consider setting destroyable=false unless you really need bombing a laser

Creating a RNGBank

Note that calling random function in the creation task may cause dissync. You can fix this by using a RNGBank.

Please see the example below.

AIO Example

            val b1 = RNGBank<Int>() //create an rng bank with Int as index
            laser(self, 1f, 150f) { //create a laser with current environment, 1 px wide, 150 px max length
                BasicBullet(tx, ty, 3f, base, defaultShotSheet["DS_BALL_M_A_BLUE"]).apply{destroyable=false}.task { //return a basic bullet. the shot sheet/type you use doesn't matter. You can apply destroyable=false to make it immune to bombs
                    wait(30)
                    var cnt=0
                    var omega=0f
                    while(true){
                        cnt++
                        bullet.angle+=omega
                        if(cnt%10==0){
                            omega=b1.random(cnt,-5f,5f) //parameter is id,l,r. The rng bank makes sure that the same id returns the same rng.
//                            omega=random(-5f,5f) NEVER USE THIS. USE RNG BANK INSTEAD
                        }
                        yield()
                    }
                } as BasicBullet
            }

Performance

Laser will not be removed from the screen unless requested by scripter. And a laser can create up to 600 objects. Please pay attention.

Clone this wiki locally