diff --git a/README.md b/README.md index 43d4345..e475a0e 100644 --- a/README.md +++ b/README.md @@ -50,16 +50,6 @@ Note: go to the '?' (top-right of the screen) in-game for more details. Inspired by ***Slay the Spire*** and ***Die in the Dungeon***. -Most player sprites taken from or based off of the ones found [**here**](https://aamatniekss.itch.io/fantasy-knight-free-pixelart-animated-character). +Most player sprites are taken from or based off of the ones found [**here**](https://aamatniekss.itch.io/fantasy-knight-free-pixelart-animated-character). -All other art (and music, too!) is entirely my original work. - -## *An ominous feeling...* - -*When the hands align,* - -*find the fragment of time.* - -*Else, at the edge of the sky,* - -*you shall eternally die.* +All other art (and music) is entirely my original work. diff --git a/images/cards/rarity/rare.png b/images/cards/rarity/rare.png index b81561b..d8febcc 100644 Binary files a/images/cards/rarity/rare.png and b/images/cards/rarity/rare.png differ diff --git a/images/enemies/fragment/attack.ase b/images/enemies/fragment/attack.ase index bc716a7..09e5e08 100644 Binary files a/images/enemies/fragment/attack.ase and b/images/enemies/fragment/attack.ase differ diff --git a/images/enemies/fragment/attack.png b/images/enemies/fragment/attack.png index beaef44..5a9f47f 100644 Binary files a/images/enemies/fragment/attack.png and b/images/enemies/fragment/attack.png differ diff --git a/images/enemies/fragment/idle.ase b/images/enemies/fragment/idle.ase index 963e80c..ff25ef5 100644 Binary files a/images/enemies/fragment/idle.ase and b/images/enemies/fragment/idle.ase differ diff --git a/images/enemies/fragment/idle.png b/images/enemies/fragment/idle.png index 0b6e7ce..1e44893 100644 Binary files a/images/enemies/fragment/idle.png and b/images/enemies/fragment/idle.png differ diff --git a/images/enemies/fragment/open.ase b/images/enemies/fragment/open.ase index d7abd24..bbcfda0 100644 Binary files a/images/enemies/fragment/open.ase and b/images/enemies/fragment/open.ase differ diff --git a/images/enemies/fragment/open.png b/images/enemies/fragment/open.png index 776c704..e9470a4 100644 Binary files a/images/enemies/fragment/open.png and b/images/enemies/fragment/open.png differ diff --git a/images/select/card_rare.png b/images/select/card_rare.png index 9f2866c..f352591 100644 Binary files a/images/select/card_rare.png and b/images/select/card_rare.png differ diff --git a/images/select/card_rare_unplayable.png b/images/select/card_rare_unplayable.png index f8c841e..de93403 100644 Binary files a/images/select/card_rare_unplayable.png and b/images/select/card_rare_unplayable.png differ diff --git a/js/data.js b/js/data.js index eaf934b..cc01f72 100644 --- a/js/data.js +++ b/js/data.js @@ -17,11 +17,11 @@ const infoText = { // effects - "aura blade": "Every time you attack,\none of your aura blades\nis used up for 5 + X\nextra damage, X being\nthe number of aura\nblades you have.", - burn: "At the end of each\nturn, each burn deals 1\ndamage to what it is on,\nthen one burn on that\ngoes away.", - "one use": "When a one use card is\nplayed, it will be sent\nto the void instead of\nthe discard.", - reinforce: "At the start of each\nturn, one reinforce is\nused up to retain your\nshield (even if you have\nno shield left).", - weakness: "While something has\nweakness, its attack is\n75% of normal, rounded\ndown. At the end of each\nturn, one weakness will\ngo away.", + "aura blade": "If something has X aura\nblades, every time it\nattacks, it deals 5 + X\nextra damage, then X is\nreduced by 1.", + burn: "If something has X burn,\nat the end of its turn,\nit takes X damage, then\nX is reduced by 1.", + "one use": "When a one use card is\nplayed, it is sent to\nthe void. Cards in the\nvoid stay there until\nthe end of the battle.", + reinforce: "If something has X\nreinforces, at the start\nof its turn, its shield\nis kept, then X is\nreduced by 1.", + weakness: "If something has X\nweakness, its attack is\nreduced by 25%, rounded\nup. At the end of each\nturn, X is reduced by 1.", // other "the map": "You can choose where\nyou go next. Cannot use\nduring a battle.", }, overview = "" @@ -57,8 +57,8 @@ gameplay = "" + "The energy cost of each card is shown on their top-left corner.\n" + "When you play a card, it does what it says on the card (effects are listed below).\n" + " - Damage reduces enemies' health, while shield protects your health from attacks.\n" - + " - Take note that shield goes away at the end of your turn unless something says otherwise.\n" - + " - Also, shield on enemies acts the same and goes away at the start of the enemy turn.\n" + + " - Take note that shield is not kept at the end of your turn unless something says otherwise.\n" + + " - Also, shield on enemies acts the same and goes away at the start of the enemy's turn.\n" + " - Most other effects are more complex, and have a tooltip that says what they do.\n" + "Enemy Intents" + "Take note of what's floating above the enemies' heads. That is their intent.\n" @@ -191,6 +191,7 @@ function updateData() { }; // other game.deck.cardSort(); + game.void.cardSort(); game.discard.cardSort(); if (game.select[0] === HAND) { if (game.hand.length) game.prevCard = game.select[1]; diff --git a/js/enemies.js b/js/enemies.js index 7e4a9e2..b3403f7 100644 --- a/js/enemies.js +++ b/js/enemies.js @@ -29,7 +29,7 @@ class Enemy { this.type = +type; this.maxHealth = Math.round(((random() / 10) + 0.95) * ((power * 10) + 20)); this.health = this.maxHealth; - this.maxShield = this.maxHealth / 2; + this.maxShield = Math.floor(this.maxHealth / 2); this.shield = 0; this.attackPower = Math.round(((power / 2) + 1) * 5 - 0.25); this.defendPower = Math.round(((power / 2) + 1) * 5 + 1); diff --git a/js/functions.js b/js/functions.js index f09d0db..168a266 100644 --- a/js/functions.js +++ b/js/functions.js @@ -26,7 +26,7 @@ String.prototype.title = function() { return result; }; -String.prototype.shuffle = function() { +String.prototype.randomize = function() { let arr = this.split(""); for (let index = arr.length - 1; index > 0; index--) { let rand = Math.floor(Math.random() * (index + 1)); @@ -43,16 +43,6 @@ Object.prototype.deepCopy = (o, keepProto = false) => { // technical functions -function randomize(array) { - let index = array.length, randomIndex; - while (index != 0) { - randomIndex = Math.floor(Math.random() * index); - index--; - [array[index], array[randomIndex]] = [array[randomIndex], array[index]]; - }; - return array; -}; - function interval(time, range = 1) { return (Math.abs((new Date().getTime() % (2000 * time * range) / (1000 * time)) - range) * range) - range; }; @@ -128,6 +118,16 @@ function restartRun() { // gameplay functions +function shuffle(deck) { + let index = deck.length, randomIndex; + while (index != 0) { + randomIndex = Math.floor(random() * index); + index--; + [deck[index], deck[randomIndex]] = [deck[randomIndex], deck[index]]; + }; + return deck; +}; + function shuffleDeck(...newCards) { if (newCards) { for (let card of newCards) { @@ -135,7 +135,7 @@ function shuffleDeck(...newCards) { else game.deckLocal.push(new Card("" + card)); }; }; - game.deckLocal = randomize(game.deckLocal); + game.deckLocal = shuffle(game.deckLocal); }; function drawHand() { diff --git a/js/game.js b/js/game.js index 4f47b93..a1acaf9 100644 --- a/js/game.js +++ b/js/game.js @@ -70,7 +70,7 @@ var global = { firstRoom: [], map: [], traveled: [], - seed: "" + (Math.round(new Date().getTime() * (Math.random() + 0.001)) % 1000000).toString().shuffle(), + seed: "" + (Math.round(new Date().getTime() * (Math.random() + 0.001)) % 1000000).toString().randomize(), }, actionTimer = -1, notif = [-1, 0, "", 0], menuLocation = TITLE, menuSelect = 0, enemyPos = [], handPos = [], paths = {}, gameWon = false; function musicPopup() { @@ -85,7 +85,7 @@ function musicPopup() { function enterBattle() { game.state = "battle"; game.rewards = []; - game.deckLocal = randomize(game.deck.slice(0)); + game.deckLocal = shuffle(game.deck.slice(0)); game.hand = []; game.discard = []; game.void = []; @@ -443,14 +443,20 @@ function selection() { game.mapSelect = paths[game.location].length - 1; actionTimer = 1; return; - } else if (game.mapSelect > 0) { + } else if (game.mapSelect == 0) { + game.mapSelect = paths[game.location].length; + actionTimer = 1; + return; + } else if (game.mapSelect < paths[game.location].length) { game.mapSelect = game.mapSelect - 1; actionTimer = 1; return; }; - } else if ((action === LEFT || action === DOWN) && game.mapSelect != -1) { + } else if ((action === LEFT || action === DOWN) && game.mapSelect != -1 && (game.mapSelect != paths[game.location].length || game.select[1] == 0)) { if (game.mapSelect < paths[game.location].length - 1) { game.mapSelect = game.mapSelect + 1; + } else if (game.mapSelect == paths[game.location].length) { + game.mapSelect = 0; } else { game.mapSelect = -1; }; @@ -467,6 +473,13 @@ function selection() { actionTimer = 1; return; }; + } else if (game.select[0] === IN_MAP) { + const len = (paths[game.location] || []).length; + if (action === UP || action === RIGHT) { + if (game.mapSelect == -1) game.mapSelect = len; + } else if ((action === LEFT || action === DOWN) && (game.mapSelect != len || game.select[1] == 0)) { + if (game.mapSelect == len) game.mapSelect = -1; + }; }; // select hand if (game.select[0] === -1) game.select = [HAND, 0]; @@ -606,10 +619,11 @@ function selection() { }; }; // deck selection - if ((game.select[0] === DECK || game.select[0] === VOID || game.select[0] === DISCARD) && game.select[1]) { + if ((game.select[0] === DECK || game.select[0] === VOID || game.select[0] === DISCARD || (game.select[0] === IN_MAP && game.mapSelect == (paths[game.location] || []).length)) && game.select[1]) { let coor = game.cardSelect, len = game.deckLocal.length; if (game.select[0] === VOID) len = game.void.length; else if (game.select[0] === DISCARD) len = game.discard.length; + else if (game.select[0] === IN_MAP) len = game.deck.length; if (action === LEFT) { if (coor[0] > 0) { game.cardSelect[0]--; @@ -652,6 +666,11 @@ function selection() { game.select = [MAP, 0]; actionTimer = 2; return; + } else if (action === ENTER && game.select[0] === IN_MAP && game.mapSelect == (paths[game.location] || []).length) { + if (game.select[1] == 0) game.select[1] = 1; + else game.select[1] = 0; + actionTimer = 2; + return; } else if (action === ENTER && game.select[0] === LOOKER) { if (game.select[1] == 0) game.select[1] = 1; else game.select[1] = 0; @@ -851,7 +870,7 @@ function manageGameplay() { game.rewards = []; if (game.room[4] > 0) game.rewards.push(game.room[4] + " gold"); if (get.cardRewardChoices() > 0) game.rewards.push("1 card"); - if (game.room[0] === PRIMEROOM) { + if (game.room[0] === PRIMEROOM || game.room[0] === BOSSROOM) { if (game.room[6]) { for (let index = 0; index < game.room[6].length; index++) { if (game.artifacts.includes(game.room[6][index])) { @@ -860,7 +879,6 @@ function manageGameplay() { }; game.rewards.push("1 artifact"); }; - game.rewards.push(Math.floor(get.maxHealth() * 0.25) + " health"); }; game.rewards.push("finish"); }; @@ -1002,6 +1020,9 @@ function updateVisuals() { } else if (game.select[0] === DISCARD && game.select[1]) { deckGraphics(game.discard); }; + if (game.select[0] === IN_MAP && game.select[1]) { + deckGraphics(game.deck); + }; if (!hidden()) target(); popupGraphics(); if (game.select[0] == GAME_OVER) { diff --git a/js/graphics.js b/js/graphics.js index 54f8a02..5a1d936 100644 --- a/js/graphics.js +++ b/js/graphics.js @@ -616,9 +616,9 @@ function enemyGraphics() { }; } else if (tempAnim[1] === FRAGMENT) { draw.imageSector(enemy.fragment.attack, Math.floor(tempAnim[0]) * 64, 0, 64, 64, pos[0], pos[1]); - if (tempAnim[0] == 4) draw.rect("#f00", 0, pos[1] + 4, pos[0], 60); + if (tempAnim[0] == 4 || tempAnim[0] == 5) draw.rect("#f00", 0, pos[1] + 4, pos[0], 60); tempAnim[0]++; - if (tempAnim[0] >= 6) { + if (tempAnim[0] >= 7) { tempAnim = [0, -1, STARTING, -1]; game.enemyStage = ENDING; } else if (game.enemyStage === MIDDLE) { @@ -735,16 +735,17 @@ function deckGraphics(deck) { }; target(); selected = game.cardSelect; - if (game.deckPos >= (98 * selected[1]) + 5) { - game.deckPos -= Math.abs(Math.round(((98 * selected[1]) - game.deckPos) / 20) - 5); - } else if (game.deckPos <= (98 * (selected[1] - 1)) + 11 - 5) { - game.deckPos += Math.abs(Math.round(((98 * (selected[1] - 1)) + 11 - game.deckPos) / 20) + 5); + if (game.deckPos >= 98 * selected[1]) { + game.deckPos -= Math.min(10, Math.abs(game.deckPos - (98 * selected[1]))); + } else if (game.deckPos <= (98 * (selected[1] - 1)) + 11) { + game.deckPos +=Math.min(10, Math.abs(game.deckPos - ((98 * (selected[1] - 1)) + 11))); }; }; draw.rect("#0004", 0, 0, 400, 13); if (game.select[0] === DECK) draw.lore(200 - 2, 1, "Deck", {"color": "white", "text-align": CENTER}); else if (game.select[0] === DISCARD) draw.lore(200 - 2, 1, "Discard", {"color": "white", "text-align": CENTER}); else if (game.select[0] === VOID) draw.lore(200 - 2, 1, "Void", {"color": "white", "text-align": CENTER}); + else if (game.select[0] === IN_MAP) draw.lore(200 - 2, 1, "Cards", {"color": "white", "text-align": CENTER}); draw.rect("#fff", 1, 12, 398, 1); }; @@ -804,8 +805,9 @@ const info = { }, player(type, xPlus = 0, yPlus = 0) { if (typeof type != "string") return 0; - const thing = game.eff[type.replace(/\s/g, "_") + (type.endsWith("s") ? "" : "s")]; - let y = 71 + yPlus, desc = "You have " + thing + " " + type + (thing >= 2 ? "s." : "."), move = 0; + const ending = type.endsWith("s") ? "" : "s"; + const eff = game.eff[type.replace(/\s/g, "_") + (type.endsWith("s") ? "" : "s")]; + let y = 71 + yPlus, desc = "You have " + eff + " " + type + (eff >= 2 ? ending : "") + ".", move = 0; move += draw.textBox(85 + xPlus, y + move, desc.length, desc, {"text-small": true}); move += draw.textBox(85 + xPlus, y + move, 24, infoText[type], {"text-small": true}); return move; @@ -1038,9 +1040,17 @@ function mapGraphics(onlyCalc = false) { if (game.location == "-1") draw.image(map.select_first, 13, 12); else draw.image(map.select, 13 + ((+game.location.split(", ")[0] + 1) * 32), 12); } else if (game.location != "-1") { - if (game.location.split(", ")[0] == "0") draw.image(map.select_first, 13, 12); - else draw.image(map.select, 13 + (+game.location.split(", ")[0] * 32), 12); + if (game.floor % 10 == 0) { + draw.image(map.select, 18 + (9 * 32), 12); + draw.image(map.select, 12 + (10 * 32), 12); + } else if (game.location.split(", ")[0] == "0") { + draw.image(map.select_first, 13, 12); + } else { + draw.image(map.select, 13 + (+game.location.split(", ")[0] * 32), 12); + }; }; + draw.image(extra.deck, 22, 16); + if (game.mapSelect == (paths[game.location] || []).length) draw.image(select.deck, 21, 15); draw.image(extra.end, 22, 179); if (game.mapSelect == -1) draw.image(select.round, 21, 178); draw.lore(1, 1, "floor " + game.floor + " - " + game.gold + " gold", {"color": "red"}); diff --git a/js/map.js b/js/map.js index 2620f1f..586e94b 100644 --- a/js/map.js +++ b/js/map.js @@ -30,7 +30,7 @@ function mapPiece(row, attribute = -1) { if (attribute === TREASURE) return [TREASUREROOM, randomInt(-5, 5), randomInt(-5, 5), false, randomInt(25 + (row * 1.5), 50 + (row * 2)) * 2, randomCardSet(5)]; if (attribute === PRIME) return [PRIMEROOM, randomInt(-5, 5), randomInt(-5, 5), [weakerSmallSlime(row), SLIME.PRIME, weakerSmallSlime(row)], randomInt(25 + (row * 1.5), 50 + (row * 2)) * 2, randomCardSet(5), randomArtifactSet(3)]; if (attribute === ORB) return [ORBROOM, randomInt(-5, 5), randomInt(-5, 5)]; - if (attribute === BOSS) return [BOSSROOM, 0, 0, [FRAGMENT], randomInt(25 + (row * 1.5), 50 + (row * 2)) * 3, randomCardSet(5)]; + if (attribute === BOSS) return [BOSSROOM, 0, 0, [FRAGMENT], randomInt(25 + (row * 1.5), 50 + (row * 2)) * 3, randomCardSet(5), randomArtifactSet(3)]; let type = chance(3/5) ? BATTLEROOM : false; if (rowFalses >= 4 || (twoRow && rowFalses >= 3) || (row === 0 && rowFalses >= 2)) type = BATTLEROOM; if (type) rowNodes++;