Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Find It Out (Single Player) | Superjazz | Single player | 9.1 |
#include "Fio_utils.asc"
namespace fioDraw {
const int ANIMATION_GEM_TICKS = 70;
const int QUEST_BOX_HEIGHT = 120;
const int QUEST_DISPLAY_TICKS = 770;
const int TEXT_BOX_HEIGHT = 160;
const int TEXT_DISPLAY_TICKS = 770;
const int TOOL_TIP_DISPLAY_TICKS = 630;
bool levelHasCoins = false;
float gemScale = DEFAULT_GEM_SCALE;
int elapsedGem = ANIMATION_GEM_TICKS;
int elapsedQuestDisplay = 0;
int elapsedTextDisplay = 0;
int purpleGemAmount = 0;
int questTextIndex = 0;
int textIndex = -1;
// Cheap hack for displaying score penalty warnings, etc.
string textCustom;
array<string> texts;
array<string> questTexts;
void animateHud() {
if (elapsedGem < ANIMATION_GEM_TICKS / 2) {
gemScale += 0.05;
elapsedGem++;
} else if (elapsedGem < ANIMATION_GEM_TICKS) {
gemScale -= 0.05;
elapsedGem++;
}
}
bool canPlayerAffordAnArmoryItem() {
for (uint i = 0; i < armoryItems.length(); i++) {
if (play.coins >= armoryItems[i].cost) {
return true;
}
}
return false;
}
void controlHud() {
if (elapsedTextDisplay > 0) {
elapsedTextDisplay--;
}
if (elapsedQuestDisplay > 0) {
elapsedQuestDisplay--;
}
}
void doGemAnimation() {
gemScale = DEFAULT_GEM_SCALE;
elapsedGem = 0;
}
void doShowOptionalQuest(int setQuestTextIndex) {
elapsedQuestDisplay = QUEST_DISPLAY_TICKS;
questTextIndex = setQuestTextIndex;
}
void doShowText(int setTextIndex) {
if (uint(setTextIndex) < texts.length()) {
elapsedTextDisplay = TEXT_DISPLAY_TICKS;
textIndex = setTextIndex;
} else {
jjAlert("|WARNING: Attempted to show a text with index " + setTextIndex + " being out of bounds!");
}
}
void doShowTextCustom(string setTextCustom) {
elapsedTextDisplay = TEXT_DISPLAY_TICKS + 140; // To allow for longer texts to be displayed just slightly longer
textCustom = setTextCustom;
}
void drawArmoryAtPos(jjCANVAS@ canvas, int xPos, int yPos, uint8 color = 25) {
canvas.drawSprite(xPos, yPos, ANIM::BONUS, 0, jjGameTicks / 7 % 10, 0, SPRITE::TINTED, color);
}
// drawAlternative hack just for Fio3_b...
void drawArmoryInterface(jjCANVAS@ canvas, uint8 armoryBackgroundColor = 30, bool drawAlternative = false) {
const string coinsStringColor = canPlayerAffordAnArmoryItem() ? "|" : "";
const string currentCoinsString = "Current coins: " + coinsStringColor + play.coins + "x";
const string header = drawAlternative ? "||||Armory of Zyrus" : "||||Infernal Armory";
const string subHeaderOne = drawAlternative ? "Welcome to the underground armory of Zyrus!" : "The keeper of the infernal armory sells several";
const string subHeaderTwo = drawAlternative ? "You may find valuable items for your excursion here for a feasible price!" : "items and upgrades to the mortals in the underworld.";
const int armoryTextBeginningY = jjSubscreenHeight / 4 * 3 - 32;
canvas.drawRectangle(0, 0, jjSubscreenWidth, jjSubscreenHeight, armoryBackgroundColor);
for (uint i = 0; i < armoryItems.length(); i++) {
armoryItems[i].draw(canvas, i, armoryItems.length());
}
// Item curtain top
canvas.drawRectangle(0, 0, jjSubscreenWidth, jjSubscreenHeight / 10, armoryBackgroundColor);
canvas.drawRectangle(0, jjSubscreenHeight / 10, jjSubscreenWidth, jjSubscreenHeight / 10 + 10, armoryBackgroundColor, SPRITE::BLEND_NORMAL, 128);
canvas.drawRectangle(0, armoryTextBeginningY - 56, jjSubscreenWidth, jjSubscreenHeight, armoryBackgroundColor);
// Item curtain bottom (won't fit to the screen on smaller resolutions than 800x600)
if (jjSubscreenHeight >= 600) {
canvas.drawRectangle(0, armoryTextBeginningY - 128, jjSubscreenWidth, 64, armoryBackgroundColor, SPRITE::BLEND_NORMAL, 128);
}
canvas.drawString(jjSubscreenWidth / 2, armoryTextBeginningY, header, STRING::MEDIUM, centeredText);
canvas.drawString(jjSubscreenWidth / 2, armoryTextBeginningY + 32, subHeaderOne, STRING::SMALL, centeredText);
canvas.drawString(jjSubscreenWidth / 2, armoryTextBeginningY + 48, subHeaderTwo, STRING::SMALL, centeredText);
canvas.drawString(jjSubscreenWidth / 2, armoryTextBeginningY + 80, "Choose an item by arrow keys.", STRING::SMALL, centeredText);
canvas.drawString(jjSubscreenWidth / 2, armoryTextBeginningY + 96, "Press space/enter to buy.", STRING::SMALL, centeredText);
canvas.drawString(jjSubscreenWidth / 2, armoryTextBeginningY + 128, currentCoinsString, STRING::SMALL, centeredText);
canvas.drawSprite(jjSubscreenWidth / 2 + 16 + jjGetStringWidth(currentCoinsString, STRING::SMALL, centeredText) / 2, armoryTextBeginningY + 124,
ANIM::PICKUPS, 84, 0 ,0);
canvas.drawString(jjSubscreenWidth / 2, jjSubscreenHeight - 8, "||(Coins won't carry over to the next level)", STRING::SMALL, centeredText);
if (!areArmoryItemsInMotion) {
if (selectedArmoryItem > 0) {
canvas.drawRotatedSprite(jjSubscreenWidth / 2, 32, ANIM::FLAG, 0, 0, 195, 1, 1, SPRITE::PALSHIFT, 40);
}
if (selectedArmoryItem < armoryItems.length() - 1) {
canvas.drawRotatedSprite(jjSubscreenWidth / 2, armoryTextBeginningY - 48, ANIM::FLAG, 0, 0, 695, 1, 1, SPRITE::PALSHIFT, 40);
}
}
canvas.drawRotatedSprite(44, jjSubscreenHeight - 32, ANIM::FLAG, 0, 0, 445, 1, 1, SPRITE::PALSHIFT, 40);
canvas.drawRotatedSprite(jjSubscreenWidth - 44, jjSubscreenHeight - 32, ANIM::FLAG, 0, 0, 945, 1, 1, SPRITE::PALSHIFT, 40);
canvas.drawString(32, jjSubscreenHeight - 8, "EXIT", STRING::SMALL, centeredText);
canvas.drawString(jjSubscreenWidth - 32, jjSubscreenHeight - 8, "EXIT", STRING::SMALL, centeredText);
}
void drawArrowUp(jjCANVAS@ canvas, int x, int y, float scale = 1) {
canvas.drawRotatedSprite(
x,
y,
ANIM::FLAG,
0,
0,
ARROW_UP_ANGLE,
scale,
scale,
SPRITE::PALSHIFT,
40
);
}
void drawBox(jjCANVAS@ canvas, int originX, int originY, int width, int height, uint8 bodyColor,
SPRITE::Mode spriteMode = SPRITE::NORMAL, bool borders = false, uint8 borderColor = 0) {
canvas.drawRectangle(originX, originY, width, height, bodyColor, spriteMode);
if (borders) {
canvas.drawRectangle(originX, originY, width, 1, borderColor, spriteMode);
canvas.drawRectangle(originX, originY, 1, height, borderColor, spriteMode);
canvas.drawRectangle(originX, originY + height, width, 1, borderColor, spriteMode);
canvas.drawRectangle(originX + width, originY, 1, height, borderColor, spriteMode);
}
}
void drawCoins(jjPLAYER@ play, jjCANVAS@ canvas) {
drawItem(canvas,
(totalGemsInLevel > 0 ? 269 : 179),
30, -15, 84, 0, 1.f, 1.f, 58, -10,
(play.coins < 10 ? "0" + play.coins : "" + play.coins));
}
void drawFrameAtPlayerPos(jjPLAYER@ play, jjCANVAS@ canvas, int setId, uint8 animation,
uint8 frame, int8 direction = 0,
SPRITE::Mode spriteMode = SPRITE::NORMAL, uint8 spriteParam = 0) {
canvas.drawSprite(int(play.xPos), int(play.yPos), setId, animation, frame, direction, spriteMode, spriteParam);
}
void drawGems(jjPLAYER@ play, jjCANVAS@ canvas) {
const string questColor = play.gems[GEM::PURPLE] >= totalGemsInLevel
? "|||"
: play.gems[GEM::PURPLE] >= questGemsInLevel
? "|" : "";
drawItem(canvas, 179, 20, -16, 22, 0, gemScale, gemScale, 58, -10,
questColor + play.gems[GEM::PURPLE] + "/" + (play.gems[GEM::PURPLE] >= questGemsInLevel ? totalGemsInLevel : questGemsInLevel),
SPRITE::GEM, 3);
}
void drawHud(jjPLAYER@ play, jjCANVAS@ canvas, bool isInCutscene = false) {
if (elapsedTextDisplay > 0 && (textIndex >= 0 || textCustom.length() > 0)) {
drawTextBox(canvas);
} else if (elapsedTextDisplay <= 0) {
textCustom = "";
}
if (elapsedQuestDisplay > 0 && questTexts.length() > 0) {
drawQuestBox(canvas);
} else if (!isInCutscene) {
if (@currentGameSession !is null) {
drawPocketCarrots(canvas);
drawInvincibilities(canvas);
}
if (questGemsInLevel > 0) {
drawGems(play, canvas);
}
if (levelHasCoins) {
drawCoins(play, canvas);
}
}
}
void drawInvincibilities(jjCANVAS@ canvas) {
drawItem(canvas, 89, 24, -10, 72, 5, 0.85, 0.85, 58, -10, currentGameSession.invincibilities + "/" + MAX_INVINCIBILITIES);
if (fio::canConsumeInvincibility()) {
canvas.drawString(170, jjSubscreenHeight - 22, "I", STRING::SMALL, centeredText);
}
}
void drawItem(jjCANVAS@ canvas, int originX, int spriteOffsetX, int spriteOffsetY, uint8 spriteAnimation, uint8 spriteFrame,
float spriteScaleX, float spriteScaleY, int textOffsetX, int textOffsetY, string text,
SPRITE::Mode spriteMode = SPRITE::NORMAL, uint8 spriteModeParam = 0) {
drawBox(canvas, originX, jjSubscreenHeight - 34, 90, 34, HUD_BAR_BACKGROUND_COLOR, SPRITE::TRANSLUCENT, true, HUD_BAR_BORDER_COLOR);
canvas.drawResizedSprite(originX + spriteOffsetX, jjSubscreenHeight + spriteOffsetY, ANIM::PICKUPS, spriteAnimation, spriteFrame,
spriteScaleX, spriteScaleY, spriteMode, spriteModeParam);
canvas.drawString(originX + textOffsetX, jjSubscreenHeight + textOffsetY, text, STRING::SMALL, centeredText);
}
void drawPocketCarrots(jjCANVAS@ canvas) {
drawItem(canvas, -1, 22, -14, 21, 0, 0.85, 0.85, 58, -10, currentGameSession.pocketCarrots + "/" + MAX_POCKET_CARROTS);
if (fio::canConsumePocketCarrot()) {
canvas.drawString(78, jjSubscreenHeight - 22, "P", STRING::SMALL, centeredText);
}
}
void drawQuestBox(jjCANVAS@ canvas) {
drawBox(canvas, -1, jjSubscreenHeight - 120, jjSubscreenWidth + 1, QUEST_BOX_HEIGHT,
HUD_BAR_BACKGROUND_COLOR, SPRITE::TRANSLUCENT, true, HUD_BAR_BORDER_COLOR);
canvas.drawString(jjSubscreenWidth / 2, jjSubscreenHeight - 96, questTexts[questTextIndex], STRING::MEDIUM, centeredText);
if (elapsedQuestDisplay < TOOL_TIP_DISPLAY_TICKS) {
string tooltip = "Press up ( ) to close (Automatically closing in " + elapsedQuestDisplay / SECOND + "... )";
int arrowX = jjSubscreenWidth / 2 - jjGetStringWidth(tooltip, STRING::SMALL, centeredText) + 380;
drawArrowUp(canvas, arrowX, jjSubscreenHeight - 10, 0.66);
canvas.drawString(
jjSubscreenWidth / 2,
jjSubscreenHeight - 16,
tooltip,
STRING::SMALL,
centeredText);
}
}
void drawTextBox(jjCANVAS@ canvas) {
const int textBoxOriginX = jjSubscreenWidth / 6;
const int textBoxOriginY = 32;
const int textBoxWidth = jjSubscreenWidth / 3 * 2;
// Check that textIndex points to an actual index to ensure no text is attempted to be displayed prematurely at the beginning of the level
drawBox(canvas, textBoxOriginX, textBoxOriginY, textBoxWidth, TEXT_BOX_HEIGHT,
HUD_BAR_BACKGROUND_COLOR, SPRITE::TRANSLUCENT, true, HUD_BAR_BORDER_COLOR);
if (textIndex >= 0) {
string processedText = fioUtils::processText(texts[textIndex], jjSubscreenWidth / 2);
canvas.drawString(jjSubscreenWidth / 2, getTextYPosByNumberOfRows(processedText, textBoxOriginY), processedText,
STRING::SMALL, centeredText);
} else if (textCustom.length() > 0) {
string processedTextCustom = fioUtils::processText(textCustom, jjSubscreenWidth / 2);
canvas.drawString(jjSubscreenWidth / 2, getTextYPosByNumberOfRows(processedTextCustom, textBoxOriginY), processedTextCustom,
STRING::SMALL, centeredText);
}
if (elapsedTextDisplay < TOOL_TIP_DISPLAY_TICKS) {
string elapsedText = ":X (" + elapsedTextDisplay / SECOND + "... )";
drawArrowUp(canvas,
textBoxOriginX + textBoxWidth - jjGetStringWidth(elapsedText, STRING::SMALL, centeredText) - 10,
textBoxOriginY + TEXT_BOX_HEIGHT - 6,
0.66);
canvas.drawString(
textBoxOriginX + textBoxWidth - 46,
textBoxOriginY + TEXT_BOX_HEIGHT - 12,
elapsedText,
STRING::SMALL,
centeredText);
}
// Apparently some (or all?) onDraw-hooks are called more often than 70 times per second, so don't decrement elapsedTextDisplay here,
// but in controlHud and call it in e.g. onMain()
}
int getTextYPosByNumberOfRows(string text, int textBoxOriginY) {
array<string> rows = text.split("@");
return textBoxOriginY + (TEXT_BOX_HEIGHT / 2) - ((rows.length() - 1) * 8);
}
void initializeDrawing(
array<string> newTexts,
array<string> newQuestTexts,
bool newLevelHasCoins = false) {
texts = newTexts;
questTexts = newQuestTexts;
levelHasCoins = newLevelHasCoins;
if (levelHasCoins) {
jjAnimSets[ANIM::BONUS].load();
}
gemScale = DEFAULT_GEM_SCALE;
elapsedGem = ANIMATION_GEM_TICKS;
elapsedQuestDisplay = 0;
elapsedTextDisplay = 0;
questTextIndex = 0;
textIndex = -1;
}
}
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.