Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Anniversary Bash 21 Levels | Jazz2Online | Multiple | N/A | |||||
Rift | blurredd | Battle | N/A |
#pragma require "Heaven.j2t"
#pragma require "DM-Rift-Extra.j2l"
void onLevelLoad() {
loadExtraLayers();
loadRiftParts();
for (int eventID = OBJECT::BLASTERBULLET; eventID <= OBJECT::BULLET; ++eventID) {
jjObjectPresets[eventID].behavior = BulletWrapper(jjObjectPresets[eventID].behavior);
}
Rift(jjObjectPresets[OBJECT::APPLE]);
}
class BulletWrapper : jjBEHAVIORINTERFACE {
private jjBEHAVIOR nativeBehavior;
BulletWrapper(const jjBEHAVIOR &in nb) {
nativeBehavior = nb;
}
void onBehave(jjOBJ@ obj) {
obj.behave(nativeBehavior);
float xPixelLimit = 1;
if (obj.xPos > (jjLayers[4].width) * 32 - (xPixelLimit + 1) && obj.xSpeed > 0) {
obj.xPos = xPixelLimit;
} else if (obj.xPos < xPixelLimit && obj.xSpeed < 0) {
obj.xPos = jjLayers[4].width * 32 + (xPixelLimit + 1);
}
}
bool onIsRFBullet(jjOBJ@ obj) {
return nativeBehavior == BEHAVIOR::RFBULLET;
}
}
void loadExtraLayers() {
const int oldTileCount = jjTileCount;
if (!jjTilesFromTileset("Heaven.j2t", 520, 100)) { //first tileID
jjAlert("|ERROR: Heaven.j2t not found!", false, STRING::MEDIUM);
return;
}
array<jjLAYER@> heavenLayers = jjLayersFromLevel(
"DM-Rift-Extra.j2l",
array<uint> = {6,7}, //Which (1-indexed) layers to copy
oldTileCount - 520
);
if (heavenLayers.length == 0) {
jjAlert("|ERROR: Heaven.j2l not found!", false, STRING::MEDIUM);
return;
}
// This loop edited in by SE to replace spriteMode usage for a major efficiency boost.
for (int tileID = 0; tileID < 100; tileID++) {
jjTileType[oldTileCount + tileID] = 1;
}
for (uint layerID = 0; layerID < heavenLayers.length; ++layerID) {
heavenLayers[layerID].yOffset = 10 * 32;
heavenLayers[layerID].limitVisibleRegion = false;
//heavenLayers[layerID].spriteMode = SPRITE::TRANSLUCENTTILE;
}
jjLAYER@ blackLayer = jjLAYER(4, jjLayers[6].height);
blackLayer.generateSettableTileArea();
blackLayer.xSpeed = jjLayers[6].xSpeed;
blackLayer.ySpeed = jjLayers[6].ySpeed;
blackLayer.tileWidth = true;
for (int y = 70; y < blackLayer.height; y++) {
for (int x = 0; x < blackLayer.width; x++) {
blackLayer.tileSet(x, y, 404); //black tile
}
}
array<jjLAYER@> extraBuildingLayers;
addBuilderLayers( 0, 4, 8, extraBuildingLayers);
addBuilderLayers(16, 4, 12, extraBuildingLayers);
addBuilderLayers(36, 4, 10, extraBuildingLayers);
addBuilderLayers(48, 4, 8, extraBuildingLayers);
addBuilderLayers(64, 4, 12, extraBuildingLayers);
addBuilderLayers(86, 4, 10, extraBuildingLayers);
addBuilderLayers(102, 4, 8, extraBuildingLayers);
//recreate first two to imitate tiled width
addBuilderLayers(120, 4, 8, extraBuildingLayers);
addBuilderLayers(136, 4, 12, extraBuildingLayers);
//recreate last to imitate tiled width
addBuilderLayers(-18, 4, 8, extraBuildingLayers);
jjTexturedBGTexture = TEXTURE::WISETYNESS;
jjSetFadeColors(70, 64, 66); //above, but a bit darker
jjUseLayer8Speeds = true;
jjLayers[7].spriteMode = SPRITE::TRANSLUCENTTILE; //barely visible moon
array<jjLAYER@> layers;
layers.insertLast(jjLayers[1]);
layers.insertLast(jjLayers[2]);
layers.insertLast(jjLayers[3]);
layers.insertLast(jjLayers[4]);
layers.insertLast(jjLayers[5]);
layers.insertLast(jjLayers[6]);
layers.insertLast(blackLayer);
layers.insertAt(layers.length(), extraBuildingLayers);
layers.insertLast(heavenLayers[0]);
layers.insertLast(heavenLayers[1]);
layers.insertLast(jjLayers[7]);
layers.insertLast(jjLayers[8]);
jjLayerOrderSet(layers);
}
void addBuilderLayers(int xTile, int yStart, int buildingWidth, array<jjLAYER@>@ layers) {
int layerWidth = (buildingWidth + 3) & ~0x03;
int xStart = 0;
jjLAYER@ baseLayer = jjLAYER(layerWidth, 100);
baseLayer.generateSettableTileArea();
baseLayer.xSpeed = 0.75f;
baseLayer.ySpeed = 0.75f;
baseLayer.xOffset = 32 * (-1 - (xTile - buildingWidth / 2));
addBuilding(baseLayer, xStart, yStart, buildingWidth);
layers.insertLast(baseLayer);
int i = 10;
jjLAYER@ layer = jjLAYER(baseLayer);
layer.spriteMode = SPRITE::SINGLECOLOR;
layer.spriteParam = 200;
float speedOffset = (i + 1) / 256.0;
float offset = (i + 1) * ((5.375 * xTile) - (4 * buildingWidth) + 16) / 32;
layer.xSpeed -= speedOffset;
layer.xOffset += offset;
layers.insertLast(layer);
}
void addBuilding(jjLAYER@ layer, int xStart, int yStart, int width) {
uint16 topLeft = 640;
uint16 topMiddle = 641;
uint16 topRight = 642;
uint16 left = 650;
uint16 middle = 671; //light on
uint16 right = 652;
int xEnd = xStart + width;
int yEnd = layer.height;
for (int x = xStart; x < xEnd; x++) {
for (int y = yStart; y < yEnd; y++) {
uint16 tileID;
if (y == yStart) {
if (x == xStart) {
tileID = topLeft;
} else if (x == xEnd - 1) {
tileID = topRight;
} else {
tileID = topMiddle;
}
} else if (x == xStart) {
tileID = left;
} else if (x == xEnd - 1) {
tileID = right;
} else {
tileID = middle;
}
layer.tileSet(x, y, tileID);
}
}
}
int min(int a, int b) {
return a < b ? a : b;
}
void onPlayer(jjPLAYER@ player) {
float xPixelLimit = 1;
if (player.xPos > (jjLayers[4].width) * 32 - (xPixelLimit + 1) && player.xSpeed > 0) {
player.offsetPosition(int(-(player.xPos - xPixelLimit)), 0);
} else if (player.xPos < xPixelLimit && player.xSpeed < 0) {
player.offsetPosition(int(-(player.xPos - (jjLayers[4].width) * 32 - (xPixelLimit + 1))), 0);
}
}
namespace math {
int mod(int a, int b) {
int r = a % b;
return r < 0 ? r + b : r;
}
int min(int a, int b) {
return a < b ? a : b;
}
int max(int a, int b) {
return a > b ? a : b;
}
}
array<LineRiftPart@> parts;
void loadRiftParts() {
uint customAnimID = 0;
uint animCount = 4;
uint frameCount = 64; //must be a power of 2
array<uint> frameCounts(animCount, frameCount);
jjANIMSET@ animset = jjAnimSets[ANIM::CUSTOM[customAnimID++]].allocate(frameCounts);
uint curAnim = animset.firstAnim;
//speed, type, amplitude, height
//{xOffset, segmentHeightShift, segmentMask}
parts.insertLast(LineRiftPart(curAnim++, 1, 0, 4, 4 * 32,
array<array<int>> = {
{14, 4, 0x1FF},
{15, 4, 0xC3},
{16, 4, 0x1FF}
}
));
parts.insertLast(LineRiftPart(curAnim++, 2, -1, 31, 4 * 32,
array<array<int>> = {
{0, 4, 0x3}
}
));
parts.insertLast(LineRiftPart(curAnim++, 1, 1, 7, 8 * 32,
array<array<int>> = {
{2, 3, 0x1}
}
));
parts.insertLast(LineRiftPart(curAnim++, 0, 0, 10, 8 * 32,
array<array<int>> = {
{5, 3, 0x1}
}
));
}
class Rift : jjBEHAVIORINTERFACE {
Rift(jjOBJ@ objectPreset) {
objectPreset.behavior = this;
objectPreset.scriptedCollisions = true;
objectPreset.playerHandling = HANDLING::PARTICLE;
objectPreset.bulletHandling = HANDLING::IGNOREBULLET;
objectPreset.counterEnd = 100;
objectPreset.isTarget = false;
objectPreset.isFreezable = false;
objectPreset.triggersTNT = false;
objectPreset.deactivates = false;
objectPreset.causesRicochet = false;
objectPreset.energy = 0;
objectPreset.points = 0;
objectPreset.direction = 1;
}
void onBehave(jjOBJ@ obj) {
switch (obj.state) {
case STATE::START:
{
int xPos = int(obj.xPos);
int yStart = int(obj.yPos);
int yEnd = yStart;
while (!jjMaskedPixel(xPos, yStart - 1)) {
yStart--;
}
while (!jjMaskedPixel(xPos, yEnd)) {
yEnd++;
}
if (yEnd == yStart) {
yEnd = yStart + 32; //better than nothing
}
//adjust one tile up and down:
yStart -= 32;
yEnd += 32;
obj.var[0] = yStart;
obj.var[1] = yEnd;
}
obj.state = STATE::SLEEP;
break;
}
}
void onDraw(jjOBJ@ obj) {
int yStart = obj.var[0];
int yEnd = obj.var[1];
for (uint i = 0; i < parts.length; i++) {
parts[i].draw(yStart, yEnd);
}
}
}
class LineRiftPart {
uint curAnim;
uint frameCount;
int speed;
array<int> xStarts;
int height;
LineRiftPart(uint curAnim, int speed, int type, int amplitude, int height, array<array<int>> values) {
this.curAnim = curAnim;
this.frameCount = jjAnimations[curAnim].frameCount;
this.speed = speed;
this.height = height;
init(type, amplitude, values);
}
void init(int type, int amplitude, array<array<int>> values) {
int xCenter = 0; //could be customized if needed
int height = this.height;
int colorCount = 16;
uint anim = jjAnimations[curAnim].firstFrame;
int xOffsetMax = 0;
for (uint valuesIndex = 0; valuesIndex < values.length(); valuesIndex++) {
array<int> value = values[valuesIndex];
int xOffset = value[0];
if (xOffset > xOffsetMax) {
xOffsetMax = xOffset;
}
}
float period = 1024.0f / height;
//int amplitude = height / 16;
int width = (amplitude + xOffsetMax) * 2 + 1;
int xCenterInImage = width / 2;
int xStart = xCenter - xCenterInImage;
this.xStarts.insertLast(xStart);
this.xStarts.insertLast(math::mod(xStart - 1, jjLayerWidth[4] * 32) + 1);
int yEndInImage = height;
int yStartInImage = 0;
for (uint frameID = 0; frameID < frameCount; frameID++) {
jjPIXELMAP image(width, height);
int yFrameStart = frameID * height / frameCount;
for (uint valuesIndex = 0; valuesIndex < values.length(); valuesIndex++) {
array<int> value = values[valuesIndex];
int xOffset = value[0];
int segmentHeightShift = value[1];
int segmentHeight = 1 << segmentHeightShift;
uint segmentMask = value[2];
for (int yOffset = 0; yOffset < height; yOffset++) {
int xBase = xCenterInImage + int(jjSin(uint(yOffset * period)) * amplitude);
int x1 = xBase - xOffset;
int x2 = xBase + xOffset;
int y1 = yStartInImage + yOffset;
int y2 = yEndInImage - yOffset - 1;
int baseIndex = yFrameStart + yOffset;
int segmentIndex = baseIndex & (height - 1);
int colorIndex = (baseIndex >> segmentHeightShift) & ((height >> segmentHeightShift) - 1);
if (colorIndex <= colorCount && (segmentMask >> (segmentIndex & (segmentHeight - 1))) & 1 != 0) {
uint8 color;
if (colorIndex == 0) {
color = 15; //white
} else {
uint8 baseColor = 96; //very light yellowish orange
color = baseColor + (colorIndex - 1); //gets darker
}
if (type <= 0) {
if (x1 < 0 || y1 < 0 || x1 >= width || y1 >= height) {
jjDebug("Invalid (x1, y1): (" + x1 + ", " + y1 + "), w: " + width + ", h: " + height);
continue;
}
image[x1, y1] = color;
}
if (type >= 0) {
if (x2 < 0 || y2 < 0 || x2 >= width || y2 >= height) {
jjDebug("Invalid (x2, y2): (" + x2 + ", " + y2 + "), w: " + width + ", h: " + height);
continue;
}
image[x2, y2] = color;
}
}
}
}
if (!image.save(jjAnimFrames[anim + frameID])) {
jjDebug("Could not save image: " + frameID);
return;
}
}
}
void draw(int yStart, int yEnd) {
uint frameID = (jjGameTicks >> this.speed) & (frameCount - 1);
uint sprite = jjAnimations[curAnim].firstFrame + frameID;
int height = this.height;
int yMid = yStart + ((yEnd - yStart) >> 1);
for (int y = yMid - height; y >= yStart - height; y -= height) {
for (uint n = 0; n < xStarts.length(); n++) {
jjDrawSpriteFromCurFrame(xStarts[n], y, sprite);
}
}
for (int y = yMid; y < yEnd; y += height) {
for (uint n = 0; n < xStarts.length(); n++) {
jjDrawSpriteFromCurFrame(xStarts[n], y, sprite);
}
}
}
}
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.