Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Damn Exit | FireSworD | Treasure hunt | 8.7 |
final class polar {
float angle, magnitude;
polar() {
angle = magnitude = 0.f;
}
polar(float theta, float m) {
angle = theta;
magnitude = m;
}
}
final class vec2 {
float x, y;
vec2() {
x = y = 0.f;
}
vec2(float X, float Y) {
x = X;
y = Y;
}
vec2(const polar &in a) {
this = vec2(a.magnitude * cos(a.angle), a.magnitude * sin(a.angle));
}
vec2(const vec2 &in a) {
this = vec2(a.x, a.y);
}
vec2& opAssign(const vec2 &in a) {
x = a.x;
y = a.y;
return this;
}
vec2& opAddAssign(const vec2 &in a) {
this = this + a;
return this;
}
vec2& opSubAssign(const vec2 &in a) {
this = this - a;
return this;
}
vec2& opMulAssign(float a) {
this = this * a;
return this;
}
vec2& opDivAssign(float a) {
this = this / a;
return this;
}
bool opEquals(const vec2 &in a) const {
return x == a.x && y == a.y;
}
vec2 opNeg() const {
return vec2(-x, -y);
}
vec2 opAdd(const vec2 &in a) const {
return vec2(x + a.x, y + a.y);
}
vec2 opSub(const vec2 &in a) const {
return this + -a;
}
vec2 opMul(float a) const {
return vec2(x * a, y * a);
}
vec2 opMul_r(float a) const {
return this * a;
}
vec2 opDiv(float a) const {
return vec2(x / a, y / a);
}
}
class Tobject {
vec2 position, velocity, acceleration;
Tobject() { }
Tobject(const vec2 &in pos, const vec2 &in v = vec2(), const vec2 &in acc = vec2()) {
position = pos;
velocity = v;
acceleration = acc;
}
Tobject(const Tobject &in a) {
this = Tobject(a.position, a.velocity, a.acceleration);
}
Tobject& opAssign(const Tobject &in a) {
position = a.position;
velocity = a.velocity;
acceleration = a.acceleration;
return this;
}
void process() {
position += (velocity += acceleration);
}
}
interface drawable {
void draw(jjCANVAS@, const vec2 &in) const;
}
interface rotatable : drawable {
rotatable@ copyRotated(float) const;
}
class Tsprite : drawable {
uint curFrame;
int8 direction;
SPRITE::Mode spriteMode;
uint8 parameter;
Tsprite(uint frame = 0, int8 dir = 0, SPRITE::Mode mode = SPRITE::NORMAL, uint8 param = 0) {
curFrame = frame;
direction = dir;
spriteMode = mode;
parameter = param;
}
Tsprite(const Tsprite &in a) {
this = Tsprite(a.curFrame, a.direction, a.spriteMode, a.parameter);
}
Tsprite& opAssign(const Tsprite &in a) {
curFrame = a.curFrame;
direction = a.direction;
spriteMode = a.spriteMode;
parameter = a.parameter;
return this;
}
void draw(jjCANVAS@ canvas, const vec2 &in position) const override {
canvas.drawSpriteFromCurFrame(int(position.x), int(position.y), curFrame, direction, spriteMode, parameter);
}
}
class Tcircle : rotatable {
const drawable@ sprite;
float radius, phase;
private uint m_count;
private float angDis;
uint count {
get const {
return m_count;
}
set {
m_count = value;
angDis = 6.2831853f / value;
}
}
Tcircle(const drawable@ source, float r, uint c, float theta = 0.f) {
@sprite = source;
radius = r;
count = c;
phase = theta;
}
Tcircle(const Tcircle &in a) {
this = Tcircle(a.sprite, a.radius, a.m_count, a.phase);
}
Tcircle& opAssign(const Tcircle &in a) {
@sprite = a.sprite;
radius = a.radius;
m_count = a.m_count;
angDis = a.angDis;
phase = a.phase;
return this;
}
void draw(jjCANVAS@ canvas, const vec2 &in position) const override {
if (sprite !is null) {
for (uint i = 0; i < m_count; i++) {
sprite.draw(canvas, position + vec2(polar(phase + angDis * i, radius)));
}
}
}
rotatable@ copyRotated(float angle) const override {
Tcircle result(this);
result.phase += angle;
return result;
}
}
class Tspiral : rotatable {
const drawable@ sprite;
uint count;
float radius, angDis, phase;
Tspiral(const drawable@ source, float r, uint c, float a, float theta = 0.f) {
@sprite = source;
radius = r;
count = c;
angDis = a;
phase = theta;
}
Tspiral(const Tspiral &in a) {
this = Tspiral(a.sprite, a.radius, a.count, a.angDis, a.phase);
}
Tspiral& opAssign(const Tspiral &in a) {
@sprite = a.sprite;
radius = a.radius;
count = a.count;
angDis = a.angDis;
phase = a.phase;
return this;
}
void draw(jjCANVAS@ canvas, const vec2 &in position) const override {
float radDis = radius / count;
if (sprite !is null) {
for (uint i = 0; i < count; i++) {
sprite.draw(canvas, position + vec2(polar(phase + angDis * i, radDis * (i + 1))));
}
}
}
rotatable@ copyRotated(float angle) const override {
Tspiral result(this);
result.phase += angle;
return result;
}
}
class Trotator : drawable {
const rotatable@ sprite;
float speed;
Trotator(const rotatable@ source, float s) {
@sprite = source;
speed = s;
}
Trotator(const Trotator &in a) {
this = Trotator(a.sprite, a.speed);
}
Trotator& opAssign(const Trotator &in a) {
@sprite = a.sprite;
speed = a.speed;
return this;
}
void draw(jjCANVAS@ canvas, const vec2 &in position) const override {
if (sprite !is null)
sprite.copyRotated(speed * jjRenderFrame).draw(canvas, position);
}
}
class Tvortex : drawable {
private array<const drawable@> sprites;
private array<Tobject> lights;
Tvortex() {
sprites.insertLast(Tsprite(getCurFrame(ANIM::ROCK, 0, 0), 0, SPRITE::SINGLECOLOR, 143));
const array<uint> count = {20, 25, 25, 32, 45, 48, 64, 48, 32, 20, 16};
const array<float> arg = {.0054f, .0069f, .0084f, .01f, .0123f, .013f, .0146f, .0176f, .0192f, .0222f, .0238f};
const array<float> radius = {40.f, 46.f, 56.f, 68.f, 80.f, 97.f, 114.f, 122.f, 148.f, 164.f, 184.f};
for (int i = 0; i < 11; i++) {
sprites.insertLast(
Trotator(
Tcircle(
Trotator(
Tcircle(
Tsprite(
getCurFrame(ANIM::AMMO, 6, i + 1), 0, SPRITE::SINGLECOLOR, 142 - i
), radius[i], count[i]
), (16 - i) / 1024.f
), i + 4, 1, arg[i] * 512.f
), arg[i]
)
);
}
sprites.insertLast(Tsprite(getCurFrame(ANIM::AMMO, 75, 3), 0, SPRITE::TRANSLUCENT));
for (int i = 0; i < 3; i++) {
sprites.insertLast(
Trotator(
Tspiral(
Tsprite(
getCurFrame(ANIM::AMMO, 75, 3), 0, SPRITE::TRANSLUCENT
), 140.f, 50, -.15f, i * 2.0943951f
), .04f
)
);
}
}
void draw(jjCANVAS@ canvas, const vec2 &in position) const override {
for (uint i = 0; i < sprites.length(); i++) {
if (jjRandom() & 255 != 0)
sprites[i].draw(canvas, position);
}
}
void process(const vec2 &in position) {
if (jjRandom() & 7 == 0) {
vec2 velocity = vec2(polar(jjRandom() / 65536.f, 2.f));
lights.insertLast(Tobject(-140.f * velocity, velocity));
}
for (uint i = 0; i < lights.length(); i++) {
Tobject@ light = lights[i];
light.acceleration -= 100.f * light.position / pow(length(light.position), 2.9f);
float temp = light.position.x;
light.process();
addLight(position + lights[i].position, LIGHT::POINT);
if (temp * light.position.x < 0)
lights.removeAt(i--);
}
for (int i = 0; i < jjObjectCount; i++) {
jjOBJ@ bullet = jjObjects[i];
if (!bullet.isActive || bullet.eventID > OBJECT::BULLET)
continue;
vec2 bulletPosition = vec2(bullet.xPos, bullet.yPos) - position;
float distance = length(bulletPosition);
if (distance < 24.f) {
bullet.delete();
} else if (distance < 480.f) {
vec2 acceleration = vec2(bullet.xAcc, bullet.yAcc) - 100.f * bulletPosition / pow(distance, 2.9f);
bullet.xAcc = acceleration.x;
bullet.yAcc = acceleration.y;
}
}
}
}
class Tearthquake {
private int magnitude, halfMagnitude, startTick, endTick = -1;
void randomize() {
uint random = jjRandom();
magnitude = (2 << (random & 3)) - 1;
halfMagnitude = magnitude >> 1;
startTick = jjGameTicks + 404 + (random & 396);
endTick = startTick + 126 + (random & 124);
}
bool process(jjPLAYER@ player) const {
if (jjGameTicks >= endTick) {
player.cameraUnfreeze();
return true;
}
if (jjGameTicks >= startTick) {
uint random = jjRandom();
if (jjGameTicks & 1 == 0 && jjMaskedHLine(int(player.xPos) - 12, 24, int(player.yPos) + 21))
player.cameraFreeze(player.cameraX + (random & magnitude) - halfMagnitude, player.cameraY + (random >> 8 & magnitude) - halfMagnitude, false, true);
else
player.cameraUnfreeze();
if (jjGameTicks & 3 == 0 && random & 192 == 0)
jjSample(player.xPos, player.yPos, SOUND::ROCK_ROCK1, magnitude << 2, 4000);
}
return false;
}
}
float length(const vec2 &in a) {
return sqrt(a.x * a.x + a.y * a.y);
}
uint getCurFrame(ANIM::Set setID, uint8 anim, uint8 frame) {
jjOBJ@ obj = jjObjects[0];
int16 prevAnim = obj.curAnim;
int8 prevFrame = obj.frameID;
obj.determineCurAnim(setID, anim);
obj.frameID = frame;
uint result = obj.determineCurFrame(false);
obj.frameID = prevFrame;
obj.curAnim = prevAnim;
return result;
}
void oneTickObject(jjOBJ@ obj) {
if (obj.counter++ != 0)
obj.delete();
}
void addLight(const vec2 &in pos, LIGHT::Type type, int8 intensity = 0) {
int id = jjAddObject(OBJECT::STEADYLIGHT, pos.x, pos.y, 0, CREATOR::OBJECT, oneTickObject);
if (id != 0) {
jjOBJ@ obj = jjObjects[id];
obj.lightType = type;
obj.light = intensity;
}
}
const vec2 vortexPosition(95 * 32 + 16, 131 * 32);
Tvortex@ vortex;
Tearthquake earthquake;
void onLevelLoad() {
@vortex = Tvortex();
}
void onDrawLayer4(jjPLAYER@, jjCANVAS@ canvas) {
vortex.draw(canvas, vortexPosition);
}
void onMain() {
vortex.process(vortexPosition);
}
void onPlayer(jjPLAYER@ player) {
if (earthquake.process(player))
earthquake.randomize();
}
Jazz2Online © 1999-INFINITY (Site Credits). We have a Privacy Policy. Jazz Jackrabbit, Jazz Jackrabbit 2, Jazz Jackrabbit Advance and all related trademarks and media are ™ and © Epic Games. Lori Jackrabbit is © Dean Dodrill. J2O development powered by Loops of Fury and Chemical Beats.
Eat your lima beans, Johnny.