Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Miscellaneous stuff | Violet CLM | Multiple | N/A |
uint gradientFrame;
jjPAL Palette = jjBackupPalette;
jjOBJ@ Robot;
array<float> originalLayerXSpeeds(3);
const uint TOP = 6, BOTTOM = 18;
const uint LEFT = 31, RIGHT = 100;
const uint BLOCKHEIGHT = 10;
const uint WIGGLEROOM = 17;
uint DrawX = LEFT, DrawY = 12;
array<array<array<uint16>>> Blocks;
void onLevelLoad() {
jjTexturedBGUsed = true;
jjTexturedBGStyle = TEXTURE::WARPHORIZON;
jjTexturedBGTexture = TEXTURE::DIAMONDUSBETA;
//jjTexturedBGFadePositionY = 0.8f;
jjGenerateSettableTileArea(4, 0, 0, jjLayerWidth[4], jjLayerHeight[4]);
for (uint i = 0; i < 3; ++i)
originalLayerXSpeeds[i] = jjLayerXSpeed[5 + i];
Palette.copyFrom(112, 16, 98, Palette);
Palette.gradient(230,106,255, 86,47,106, 128,16);
Palette.gradient(192,206,249, 121,165,224);
Palette.gradient(180,192,245, 143,154,233, 160,16);
for (uint i = 0; i < 32; ++i) {
//if (i < 16)
// Palette.color[96 + i].setHSL(i * 16, 255, 128 - i*8);
Palette.color[208 + i].setHSL(i * 8, 255, 128);
}
gradientFrame = jjAnimations[jjAnimSets[ANIM::CUSTOM[0]].allocate(array<uint> = {2})];
jjPIXELMAP gradient(640, 480);
for (uint y = 1; y < 480; ++y)
for (uint x = 0; x < 640; ++x)
gradient[x,y] = y/2;
gradient.save(jjAnimFrames[gradientFrame]);
jjPIXELMAP rainbow(20, 32);
for (uint y = 0; y < 32; ++y)
for (uint x = 0; x < 20; ++x)
rainbow[x,y] = 208 + y;
rainbow.save(jjAnimFrames[++gradientFrame]);
jjAnimFrames[gradientFrame].hotSpotX = -10;
jjCharacters[CHAR::SPAZ].doubleJumpCountMax = 2;
jjObjectPresets[OBJECT::SILVERCOIN].behavior = Coin;
jjObjectPresets[OBJECT::SILVERCOIN].points = 0; //don't create a score particle when collected
jjObjectPresets[OBJECT::SILVERCOIN].deactivates = false;
jjObjectPresets[OBJECT::SILVERCOIN].lightType = LIGHT::LASER;
jjObjectPresets[OBJECT::SILVERCOIN].light = 1;
jjObjectPresets[OBJECT::CARROT].behavior = Carrot;
jjObjectPresets[OBJECT::CARROT].points = 0;
jjObjectPresets[OBJECT::CARROT].deactivates = false;
jjObjectPresets[OBJECT::DEVANROBOT].behavior = Boss;
jjObjectPresets[OBJECT::DEVANROBOT].determineCurAnim(ANIM::ROBOT, 3);
jjObjectPresets[OBJECT::DEVANROBOT].direction = -1;
jjObjectPresets[OBJECT::DEVANROBOT].playerHandling = HANDLING::ENEMYBULLET; //I guess?
jjObjectPresets[OBJECT::DEVANROBOT].animSpeed = 2;
jjObjectPresets[OBJECT::DEVANROBOT].energy = 100;
jjObjectPresets[OBJECT::DEVANROBOT].counter = 0;
jjObjectPresets[OBJECT::STEADYLIGHT].behavior = FollowingLight;
jjSetDarknessColor(jjPALCOLOR(255,255,255));
{ //make slopes
jjPIXELMAP slopeBase(0, 0, 96, 96, 4);
array<jjMASKMAP@> singleWidthSlopeMask(3);
array<array<jjMASKMAP@>> doubleWidthSlopeMask(2, array<jjMASKMAP@>(3));
array<jjPIXELMAP@> singleWidthSlopeImageLeft(3);
array<jjPIXELMAP@> singleWidthSlopeImageRight(3);
array<array<jjPIXELMAP@>> doubleWidthSlopeImageLeft(2, array<jjPIXELMAP@>(3));
array<array<jjPIXELMAP@>> doubleWidthSlopeImageRight(2, array<jjPIXELMAP@>(3));
for (uint yTile = 0; yTile < 3; ++yTile) {
@singleWidthSlopeMask[yTile] = @jjMASKMAP(false);
@singleWidthSlopeImageLeft[yTile] = @jjPIXELMAP((yTile < 2) ? 0 : 25);
@singleWidthSlopeImageRight[yTile] = @jjPIXELMAP((yTile < 2) ? 0 : 25);
for (uint xTile = 0; xTile < 2; ++xTile) {
@doubleWidthSlopeMask[xTile][yTile] = @jjMASKMAP(false);
@doubleWidthSlopeImageLeft[xTile][yTile] = @jjPIXELMAP((yTile < 2) ? 0 : 25);
@doubleWidthSlopeImageRight[xTile][yTile] = @jjPIXELMAP((yTile < 2) ? 0 : 25);
}
}
for (uint y = 0; y < 96; ++y)
for (uint x = 0; x < 64; ++x) {
if (x < 32) {
singleWidthSlopeMask[y / 32][x, y & 31] = (y + x) >= 52;
if (y + x >= 32 && y + x < 96)
singleWidthSlopeImageLeft[y / 32][x, y & 31] = slopeBase[x,y+x];
if (y - x >= 0 && y - x < 64)
singleWidthSlopeImageRight[y / 32][x, y & 31] = slopeBase[x, y - x + 32];
}
uint xh = x/2;
doubleWidthSlopeMask[x / 32][y / 32][x & 31, y & 31] = (y + xh) >= 52;
if (y + xh >= 32 && y + xh < 96)
doubleWidthSlopeImageLeft[x / 32][y / 32][x, y & 31] = slopeBase[32+x,y+xh];
if (y - xh >= 0 && y - xh < 64)
doubleWidthSlopeImageRight[x / 32][y / 32][x, y & 31] = slopeBase[32+x, y - xh + 32];
}
for (uint yTile = 0; yTile < 3; ++yTile) {
singleWidthSlopeMask[yTile].save(93 + yTile*10);
singleWidthSlopeMask[yTile].save(98 + yTile*10 + TILE::HFLIPPED, true);
singleWidthSlopeImageLeft[yTile].save(93 + yTile*10);
singleWidthSlopeImageRight[yTile].save(98 + yTile*10);
for (uint xTile = 0; xTile < 2; ++xTile) {
doubleWidthSlopeMask[xTile][yTile].save(94 + xTile + yTile*10);
doubleWidthSlopeMask[xTile][yTile].save(97 - xTile + yTile*10 + TILE::HFLIPPED, true);
doubleWidthSlopeImageLeft[xTile][yTile].save(94 + xTile + yTile*10);
doubleWidthSlopeImageRight[xTile][yTile].save(96 + xTile + yTile*10);
}
}
}
FindBlocks();
onLevelReload();
jjSetFadeColors();
}
void onLevelBegin() {
jjLocalPlayers[0].lightType = LIGHT::NONE;
}
void onLevelReload() {
Palette.apply();
speedCounter = 3000;
DefeatCounter = 0;
playerTrail.resize(0);
@Robot = jjObjects[jjAddObject(OBJECT::DEVANROBOT, 0, -64)];
playerSpeed = 4; //initial distance between blocks
DrawY = 12;
LayoutLevel(false);
}
bool onDrawScore(jjPLAYER@ play, jjCANVAS@ screen) {
if (!jjLowDetail) {
const float scale = float(jjResolutionWidth) / 640.f;
screen.drawResizedSpriteFromCurFrame(0, int(64 + jjSin(jjGameTicks << 1) * 64), gradientFrame - 1, scale, scale, SPRITE::ALPHAMAP, 176);
}
if (CoinsNeeded <= 9000 && Robot.counter == 0)
screen.drawString(0x8000, 30, "" + play.coins + "/" + CoinsNeeded, STRING::MEDIUM);
return true;
}
bool onDrawAmmo(jjPLAYER@ play, jjCANVAS@ screen) { return true; }
void FollowingLight(jjOBJ@ obj) {
if (obj.state == STATE::START)
obj.behave(BEHAVIOR::STEADYLIGHT); //pick up parameters
obj.xPos = obj.xOrg + jjLocalPlayers[0].cameraX - (jjGameTicks%192);
}
class position {
int xPos, yPos;
position(float x, float y) { xPos = int(x); yPos = int(y); }
position(){} //just so the script will compile
}
uint speedCounter = 0;
array<position> playerTrail;
float playerSpeed = 4;
bool playerOnFloor(jjPLAYER@ play) {
return jjMaskedPixel(int(play.xPos), int(play.yPos) + 24);
}
void onPlayer(jjPLAYER@ play) {
{
play.idle = 0;
if ((Robot.counter > 0 || Robot.behavior != Boss) && playerOnFloor(play)) { //robot in pain!
speedCounter = 3000; //start over
play.xSpeed = 0;
play.specialMove = 0;
play.coins = 0;
play.keyRight = false;
play.keyLeft = false;
play.keyDown = false;
play.keyUp = false;
play.keyFire = false;
play.keyJump = false;
play.invincibility = -70;
return;
}
if (play.xSpeed == 0 && play.buttstomp > 120 && Robot.counter == 0)
play.hurt();
play.keyRight = true;
play.keyRun = true;
while (playerTrail.length > uint(jjResolutionWidth / 2))
playerTrail.removeLast();
if (play.xSpeed > 1) //moving
playerTrail.insertAt(0, position(play.xPos, play.yPos - 16));
for (uint i = 0; i < playerTrail.length; ++i) {
jjDrawSpriteFromCurFrame(playerTrail[i].xPos, playerTrail[i].yPos, gradientFrame, 0, SPRITE::BLEND_NORMAL, i);
}
//jjDrawString(play.xPos, play.yPos - 30, "" + play.xSpeed);
if (play.buttstomp > 40 || play.specialMove > 0) { //not buttstomping
playerSpeed = sqrt(speedCounter += 3) / 16.f;
if (play.buttstomp <= 120 && play.fly == 0 && play.specialMove == 0) //started buttstomping
play.xSpeed = playerSpeed / 2;
else if (play.specialMove > 0)
play.xSpeed = playerSpeed * 2;
else play.xSpeed = playerSpeed;
}
if (speedCounter == 3003)
play.morphTo(CHAR::SPAZ);
if (speedCounter == 3099) {
CoinsNeeded = 3 + jjDifficulty + DefeatCounter;
play.showText("@@@@@#Collect " + CoinsNeeded + " Coins!", STRING::LARGE);
play.activateBoss();
play.boss = Robot.objectID;
}
if (play.xSpeed > 1 && playerOnFloor(play) && play.specialMove == 0 && jjGameTicks % int(play.xSpeed * 2) == 0)
jjObjects[jjAddObject(OBJECT::EXPLOSION, play.xPos, play.yPos + 16)].determineCurAnim(ANIM::AMMO, 72);
if (play.keyFire && play.specialMove == 0 && (playerOnFloor(play) || play.doubleJumpCount != -2)) {
play.specialMove = 16;
play.doubleJumpCount = -2;
jjSample(play.xPos, play.yPos, SOUND::SPAZSOUNDS_KARATE7);
}
play.keyFire = false;
if (play.xPos > RIGHT*32) {
const int distanceX = int(RIGHT - LEFT - WIGGLEROOM) * 32;
for (uint i = 0; i < 3; ++i)
jjSetLayerXSpeed(5 + i, 0, false);
play.offsetPosition(-distanceX, 0);
for (uint i = 0; i < 3; ++i)
jjSetLayerXSpeed(5 + i, originalLayerXSpeeds[i], false);
for (uint i = 0; i < playerTrail.length; ++i)
playerTrail[i].xPos -= distanceX;
for (int i = jjObjectCount - 1; i >= 1; --i) {
jjOBJ@ obj = jjObjects[i];
if (obj.isActive)
obj.xPos -= distanceX; //particularly the silver coins
}
LayoutLevel(true);
}
}
/*if (play.ySpeed == 0 && play.buttstomp >= 121) { //on ground, can serve as checkpoint
play.xOrg = play.xPos;
play.yOrg = play.yPos;
}*/
if (abs(play.doubleJumpCount) == 1) {
play.doubleJumpCount = 2;
for (uint i = 0; i < 64; ++i) {
jjPARTICLE@ spark = jjAddParticle(PARTICLE::SPARK);
if (spark !is null) {
spark.xPos = play.xPos;
spark.yPos = play.yPos;
spark.xSpeed = jjSin(i * 16) * 3;
spark.ySpeed = jjCos(i * 16);
spark.spark.color = (i & 0b11111000) + 8;
spark.spark.colorStop = (i & 0b11111000) + 15;
}
}
}
}
void Coin(jjOBJ@ obj) {
obj.behave(BEHAVIOR::PICKUP, false);
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos + 4 * jjSin(int((jjGameTicks + obj.objectID * 8 + obj.xOrg + obj.yPos * 256) * 16)), obj.curFrame, obj.direction, SPRITE::SINGLEHUE, 208 + (jjGameTicks & 31));
obj.xSpeed = obj.ySpeed = 0; //don't get shot
if (obj.xPos < jjLocalPlayers[0].xPos - 96) {
obj.particlePixelExplosion(0);
obj.particlePixelExplosion(2);
obj.delete();
jjLocalPlayers[0].coins = 0;
jjSamplePriority(SOUND::ROBOT_SHOOT);
jjSamplePriority(SOUND::ROBOT_JMPCAN8);
}
}
void Carrot(jjOBJ@ obj) {
obj.behave(BEHAVIOR::PICKUP);
obj.xSpeed = obj.ySpeed = 0; //don't get shot
if (obj.xPos < jjLocalPlayers[0].xPos - WIGGLEROOM*32)
obj.delete();
}
array<SOUND::Sample> MetalNoises = {SOUND::ROBOT_METAL1, SOUND::ROBOT_METAL2, SOUND::ROBOT_METAL3, SOUND::ROBOT_METAL4};
uint DefeatCounter = 0;
int CoinsNeeded = 9001; //will soon be reset
void Boss(jjOBJ@ obj) {
if (obj.counter > 0) {
--obj.counter;
if (obj.counter > 250) {
if (jjGameTicks & 31 == 0)
jjLocalPlayers[0].cameraFreeze(obj.xPos, obj.yPos, true, false);
if (jjGameTicks & 3 > 0) {
jjOBJ@ shard = jjObjects[jjAddObject(OBJECT::SHARD, obj.xPos, obj.yPos, 0, CREATOR::OBJECT, BEHAVIOR::ROBOTSHARD)];
shard.determineCurAnim(ANIM::ROBOT, 6 + (jjRandom() & 7));
shard.lightType = LIGHT::POINT2;
jjSamplePriority(MetalNoises[jjRandom() & 3]);
} else {
jjOBJ@ expl = jjObjects[jjAddObject(OBJECT::EXPLOSION, obj.xPos + (jjRandom() & 31) - 16, obj.yPos + (jjRandom() & 31) - 16)];
expl.determineCurAnim(ANIM::AMMO, 77);
expl.frameID = 4;
expl.determineCurFrame();
jjSamplePriority(SOUND::ROBOT_JMPCAN8);
obj.justHit = 2;
}
} else if (obj.counter == 90) {
if (obj.energy > 0)
jjSamplePriority(SOUND::ROBOT_HYDRO2);
else {
obj.state = STATE::DONE;
obj.particlePixelExplosion(0);
obj.particlePixelExplosion(2);
}
} else if (obj.counter == 34) {
jjLocalPlayers[0].cameraUnfreeze(false);
if (obj.energy == 0)
jjNxt("BossrushV3");
}
}
if (obj.state != STATE::DONE) {
jjPLAYER@ play = jjLocalPlayers[0];
if (obj.yPos < play.yPos - 96 - 1.5)
obj.yPos += 2;
else if (obj.yPos > play.yPos - 96 + 1.5)
obj.yPos -= 2;
obj.xPos = play.xPos + 300 + jjSin(jjGameTicks * 5) * 8;
if (play.coins >= CoinsNeeded) {
play.coins = 0;
++DefeatCounter;
obj.energy -= 25;
obj.counter = 6 * 70;
}
obj.frameID = jjGameTicks >> 2;
obj.determineCurFrame();
obj.draw();
if (obj.counter == 0 && CoinsNeeded <= 9000) {
if (play.coins != obj.var[0]) {
if (play.coins > obj.var[0])
obj.counterEnd = 40;
obj.var[0] = play.coins;
}
if (obj.counterEnd > 0) --obj.counterEnd;
for (int i = 0; i < CoinsNeeded; ++i) {
int distance = (CoinsNeeded + 1 - play.coins);
const int angle = int(i * 1024.f / float(CoinsNeeded)) + jjGameTicks*2;
distance = (distance*10 + obj.counterEnd/4);
jjDrawSpriteFromCurFrame(
obj.xPos + jjSin(angle) * distance,
obj.yPos - 10 + jjCos(angle) * distance,
jjAnimations[jjAnimSets[ANIM::ROBOT]]
);
if (i < play.coins)
jjDrawSpriteFromCurFrame(
obj.xPos + jjSin(angle) * distance,
obj.yPos - 10 + jjCos(angle) * distance,
jjAnimations[jjObjectPresets[OBJECT::SILVERCOIN].curAnim],
0,
SPRITE::TRANSLUCENTSINGLEHUE, 208 + (jjGameTicks & 31)
);
}
}
}
}
void FindBlocks() {
for (int blockL = LEFT; blockL < jjLayerWidth[4]; ++blockL) {
int eventMarker = jjEventGet(blockL, 0);
if (eventMarker == AREA::BELTLEFT) {
int blockR = blockL + 1;
while (jjEventGet(blockR, 0) != AREA::BELTRIGHT) ++blockR;
array<array<uint16>> newBlock(blockR + 1 - blockL, array<uint16>(BLOCKHEIGHT, 0));
for (uint x = 0; blockL <= blockR; ++blockL) {
for (uint y = 1; y < BLOCKHEIGHT + 1; ++y) {
uint16 tileID = jjTileGet(4, blockL, y);
if (tileID != 0) {
newBlock[x][y - 1] = tileID;
//jjTileSet(4, blockL, y, 0); //not needed
}
}
++x;
}
Blocks.insertLast(newBlock);
}
}
}
void LayoutLevel(bool transition) {
const int SpaceBetweenBlocks = uint(playerSpeed);
const uint layerHeight = jjLayerHeight[4];
if (transition) {
uint copyX = RIGHT - WIGGLEROOM;
uint pasteX = LEFT;
for (; copyX < DrawX; ++copyX) {
for (uint y = 0; y < layerHeight; ++y)
jjTileSet(4, pasteX, y, jjTileGet(4, copyX, y));
++pasteX;
}
DrawX = pasteX;
} else
DrawX = LEFT;
while (DrawX < RIGHT + WIGGLEROOM) {
int space = SpaceBetweenBlocks;
while (space-- >= 0) {
for (uint y = 0; y < layerHeight; ++y)
jjTileSet(4, DrawX, y, 0); //clear column
++DrawX;
if (space == 1)
jjAddObject((jjRandom() & 31 > 0) ? OBJECT::SILVERCOIN : OBJECT::CARROT, DrawX * 32, (DrawY + BLOCKHEIGHT/2 - 1) * 32);
}
array<array<uint16>>@ block = @Blocks[jjRandom() % Blocks.length];
for (uint x = 0; x < block.length; ++x) {
for (uint y = 0; y < layerHeight; ++y) {
uint yTile = y;
if (y < DrawY) //spread out to cover top/bottom with mask if needed
yTile = DrawY;
else if (y >= DrawY + BLOCKHEIGHT)
yTile = DrawY + BLOCKHEIGHT - 1;
jjTileSet(4, DrawX, y, block[x][yTile - DrawY]);
}
++DrawX;
}
uint rand = jjRandom();
if (DrawY > TOP && (rand & 1) == 1)
DrawY -= 2;
else if (DrawY < BOTTOM && (rand & 2) == 2)
DrawY += 2;
}
}
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.