Last active
August 12, 2019 18:01
-
-
Save bluebear94/0d8307c8c95b378180ced1f5899cb694 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void TDRTestStage0::startBoss() { | |
tdr::EnemyHandle boss = | |
g->getEnemyList().createBoss(tdr::PV(416 - 32, 150), 24, 64); | |
boss.setTexcoords(agl::UIRect16{0, 0, 128, 128}); | |
tdr::BossScene& scene = g->registerBossScene(boss); | |
scene.setId(0); | |
scene.addBossAttack( | |
0, | |
{ | |
/* .handler = */ [=, &scene]() { | |
std::cerr << "nonspell 1\n"; | |
const tdr::BossAttack* at = scene.currentAttack(); | |
kcr::Manager& man = getManager(); | |
man.spawn([=, &scene]() { | |
tdr::BulletList& bl = g->getBulletList(); | |
int counter = 0; | |
int nFrames = 0; | |
while (true) { | |
counter += 10; | |
while (counter >= 100) { | |
kfp::s16_16 x = | |
g->getRng().next<kfp::s16_16>(0, g->getDimensions().x); | |
kfp::frac32 a = g->getRng().next<kfp::frac32>( | |
"0.245"_frac32, "0.255"_frac32); | |
if (scene.currentAttack() != at) return; | |
bl.createLooseLaser( | |
tdr::PV(x, 0), 3, a, 100, 8, shot::greenBall, 0); | |
counter -= 100; | |
} | |
kcr::yield(); | |
++nFrames; | |
} | |
}); | |
man.spawn([=, &scene]() { | |
tdr::BulletList& bl = g->getBulletList(); | |
while (true) { | |
if (scene.currentAttack() != at) return; | |
kfp::frac32 angle = | |
kfp::frac32::raw(g->getRng().getBits<uint32_t, 32>()); | |
bl.createShotA1( | |
boss.getPosition(), 3, angle, shot::purpleBall, 0); | |
kcr::yield(); | |
} | |
}); | |
man.spawn( | |
[=, &scene](tdr::EnemyHandle boss) { | |
auto& rng = g->getRng(); | |
while (true) { | |
tdr::cwait(90); | |
if (scene.currentAttack() != at) return; | |
tdr::PV destination = { | |
rng.next<kfp::s16_16>(50, g->getDimensions().x - 50), | |
rng.next<kfp::s16_16>(50, 350)}; | |
tdr::moveTowardAtSpeed(boss, destination, 5, [=, &scene]() { | |
return scene.currentAttack() == at; | |
}); | |
} | |
}, | |
boss); | |
}, | |
/* .score = */ 0, // nonspell | |
/* .startTime = */ 60 * 60, | |
/* .health = */ 5000, | |
/* .id = */ 0, | |
/* .isTimeout = */ false, | |
}); | |
scene.addBossAttack( | |
0, | |
{ | |
/* .handler = */ [=, &scene]() { | |
// Port of Vija's first spell in NTP | |
std::cerr << "spell 1\n"; | |
const tdr::BossAttack* at = scene.currentAttack(); | |
kcr::Manager& man = getManager(); | |
tdr::PV centre = g->getPlayfield().getDimensions() / 2; | |
man.spawn( | |
[=, &scene](tdr::EnemyHandle boss) { | |
tdr::PV destination = centre; | |
tdr::moveTowardAtSpeed(boss, destination, 5, [=, &scene]() { | |
return scene.currentAttack() == at; | |
}); | |
}, | |
boss); | |
man.spawn([=, &scene]() { | |
using namespace kfp::literals; | |
int width = g->getPlayfield().getWidth(); | |
int height = g->getPlayfield().getHeight(); | |
tdr::BulletList& bl = g->getBulletList(); | |
int d = 1; | |
int graphPeriod = 5 - d / 2; | |
// This is doubled from the original source code, because | |
// TDRTest runs at twice the resolution of NTP. | |
kfp::s16_16 graphInterval = 30 - "2.6"_s16_16 * d; | |
int ways = 8 + 2 * d; | |
kfp::frac32 phi; | |
/* local */ { | |
tdr::PV src = boss.getPosition(), | |
dest = g->getPlayer().getPosition(); | |
tdr::PV d = dest - src; | |
kfp::s16_16 l; | |
kfp::rectp(d.x, d.y, l, phi); | |
} | |
kfp::frac32 theta = phi; | |
kfp::frac32 phase = 0; | |
tdr::BulletHandle orb = | |
bl.createShotA1(centre, 4, theta, shot::orangeBubble, 0); | |
orb.setSpellResistant(true); | |
orb.setDeleteWhenOutOfBounds(false); | |
int r = 200 + 40 * d; | |
kfp::frac32 av = kfp::frac32::raw(11930464 + 5965232 * d); | |
tdr::cwait(r / 4); | |
kfp::s16_16 x = 0; | |
kfp::frac32 ss = "0.25"_frac32; | |
kfp::s16_16 gs = "0.9"_s16_16 - "0.15"_s16_16 * d; | |
kfp::s16_16 gss = 2 + "0.2"_s16_16 * d; | |
for (size_t frame = 0; scene.currentAttack() == at; ++frame) { | |
theta += av; | |
phase += av * "3.1729"_u16_16; | |
kfp::s2_30 c, s; | |
kfp::sincos(phase, c, s); | |
kfp::s16_16 rp = (1 + "0.2"_s16_16 * s) * r; | |
kfp::sincos(theta, c, s); | |
orb.setPosition(boss.getPosition() + tdr::PV{rp * c, rp * s}); | |
if (frame % 30 == 0) { | |
kfp::frac32 a = g->getRng().next<kfp::frac32>(); | |
for (int i = 0; i < ways; ++i) { | |
bl.createShotA1(orb.getPosition(), 2, a, shot::redStar, 0); | |
a += kfp::frac32::raw((uint32_t)((1LL << 32) / ways)); | |
} | |
} | |
if (frame % graphPeriod == 0) { | |
kfp::frac32 angleToPlayer; | |
/* local */ { | |
tdr::PV src = orb.getPosition(), | |
dest = g->getPlayer().getPosition(); | |
tdr::PV d = dest - src; | |
kfp::s16_16 l; | |
kfp::rectp(d.x, d.y, l, angleToPlayer); | |
} | |
kfp::s16_16 y = | |
(kfp::s16_16)(kfp::u16_16(height) * angleToPlayer); | |
tdr::BulletHandle shot = | |
bl.createShotA1({x, y}, 0, ss, shot::orangeMissile, 30); | |
kcr::spawn( | |
[=, | |
graph = (s > 0) ? shot::redMissile : shot::blueMissile]( | |
tdr::BulletHandle shot) { | |
tdr::cwait(90); | |
if (shot.isMarkedForDeletion()) return; | |
shot.setSpeed((1 + gs) * gss); | |
shot.setGraphic(graph); | |
}, | |
shot); | |
ss = -ss; | |
x += graphInterval; | |
if (x > width) x -= width; | |
} | |
kcr::yield(); | |
} | |
}); | |
}, | |
/* .score = */ 4'000'000, | |
/* .startTime = */ 60 * 60, | |
/* .health = */ 14000, | |
/* .id = */ 1, | |
/* .isTimeout = */ false, | |
}); | |
scene.addBossAttack( | |
1, | |
{ | |
/* .handler = */ [=, &scene]() { | |
std::cerr << "spell 2\n"; | |
const tdr::BossAttack* at = scene.currentAttack(); | |
kcr::Manager& man = getManager(); | |
man.spawn( | |
[=, &scene](tdr::EnemyHandle boss) { | |
using namespace kfp::literals; | |
auto& rng = g->getRng(); | |
tdr::BulletList& bl = g->getBulletList(); | |
while (true) { | |
tdr::cwait(90); | |
if (scene.currentAttack() != at) return; | |
tdr::PV destination = { | |
rng.next<kfp::s16_16>(50, g->getDimensions().x - 50), | |
rng.next<kfp::s16_16>(50, 350)}; | |
tdr::moveTowardAtSpeed(boss, destination, 7, [=, &scene]() { | |
return scene.currentAttack() == at; | |
}); | |
if (scene.currentAttack() != at) return; | |
for (size_t i = 0; i < 15; ++i) { | |
kfp::s16_16 speed = rng.next("7.5"_s16_16, "11.5"_s16_16); | |
kfp::frac32 angle = rng.next<kfp::frac32>(); | |
bl.createShotA1( | |
boss.getPosition(), speed, angle, shot::pulsatingOrb, | |
15); | |
} | |
for (size_t i = 0; i < 15; ++i) { | |
kfp::s16_16 speed = rng.next("2.5"_s16_16, "5.5"_s16_16); | |
kfp::frac32 angle = rng.next<kfp::frac32>(); | |
bl.createShotA1( | |
boss.getPosition(), speed, angle, shot::pulsatingOrb, | |
15); | |
} | |
} | |
}, | |
boss); | |
man.spawn([=, &scene]() { | |
using namespace kfp::literals; | |
tdr::BulletList& bl = g->getBulletList(); | |
auto& rng = g->getRng(); | |
tdr::cwait(120); | |
while (true) { | |
if (scene.currentAttack() != at) return; | |
kfp::frac32 angle = rng.next<kfp::frac32>(); | |
bl.createLooseLaser( | |
boss.getPosition() + tdr::PV{-30, -10}, 6, angle, 150, 8, | |
shot::blueMissile, 0); | |
angle = rng.next<kfp::frac32>(); | |
bl.createLooseLaser( | |
boss.getPosition() + tdr::PV{30, -10}, 6, angle, 150, 8, | |
shot::blueMissile, 0); | |
tdr::cwait(10); | |
} | |
}); | |
}, | |
/* .score = */ 4'500'000, | |
/* .startTime = */ 75 * 60, | |
/* .health = */ 9000, | |
/* .id = */ 2, | |
/* .isTimeout = */ false, | |
}); | |
getManager().spawn([boss, g = this->g]() { | |
while (!boss.isMarkedForDeletion()) { kcr::yield(); } | |
tdr::cwait(240); | |
g->finishStage(); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment