-
-
-
-
-
\ No newline at end of file
diff --git a/src/simpleGame.js b/src/simpleGame.js
deleted file mode 100644
index a16bf6c..0000000
--- a/src/simpleGame.js
+++ /dev/null
@@ -1,321 +0,0 @@
-// variables churned out of my html elements
-
-let healthBar = document.getElementById("HB");
-let attackBar = document.getElementById("attack");
-let inventory = document.getElementById("inventory");
-let storyBar = document.getElementById("story");
-let storyBoard = document.getElementById("storyboard")
-let contdBtn = document.getElementById("contdbtn");
-let actionBtn = document.getElementById("actionbtn");
-let sword = document.getElementById("sword");
-let shield = document.getElementById("shield");
-let playerHealth = document.getElementById("health");
-let playerHealth2 = document.getElementById("health2")
-let pickUpswordItem = document.getElementById("pickupsword");
-let pickUpshieldItem = document.getElementById("pickupshield")
-
-//in game variable definitions
-let gameInProgress = true;
-let initialStart = true;
-let gameState = "exploring";
-let pageFlip = 0;
-let turn = "player";
-let randAttack = Math.floor(Math.random() * 2);
-let randWeapon = Math.floor(Math.random() * 3 + 1);
-
-//THIS HOLDS SOME OF THE IN-GAME ITEMS
-
-let gameWeapons = {
- swords: ["Basic Adventurers blade", "Slithering blade"],
- shield: ["Basic Adventurers shield","Slithering shield"]
-}
-
-//inGame mechanics
-let view = {
- displayHealth(health){
- let playerHealth = document.getElementById("health");
- playerHealth.innerHTML = health;
-
- }
-}
-let gameLogic = {
- updateGameUi(){
- if(gameState === "exploring"){
- contdBtn.style.display = "block";
- shield.style.display = "none";
- sword.style.display = "none";
- }
-
- else if(gameState === "inBattle"){
- contdBtn.style.display = "none";
- shield.style.display = "none";
- sword.style.display = "block";
- }
-
- else if (gameState === "defending"){
- contdBtn.style.display = "none";
- sword.style.display = "none";
- shield.style.display = "block";
- }
-
-},
- attackHits(accuracy){
- randomNumber = Math.random();
- if(randomNumber <= accuracy){
- return true;
- }
- else{
- return false;
- }
-
-},
-
-battle(){
- this.updateGameUi();
-
- playerHit = playerChar.strike;
- if(playerHit){
- EmberDrake.health -= playerChar.damage
- attackBar.innerHTML = `EmberDrake: ${EmberDrake.health}`;
- storyBoard.innerHTML = "You striked the dragon";
- }
-
- else{
- storyBoard.innerHTML = "You missed";
- }
-
- if(EmberDrake.health == 0){
- gameState = "exploring";
- this.updateGameUi();
- EmberDrake.health = 0;
- pageFlip++;
- story = storyEvent[pageFlip].text
- storyBoard.innerHTML = story;
- return;
-
- }
- else{
- gameState = "defending";
- turn = "enemy";
- }
-
- if(gameState !== "inBattle" && turn !== "player"){
- this.updateGameUi();
- return this.defence;
-
-}
-},
-
-defence(){
- this.updateGameUi();
-
-
- enemyHit = playerChar.defend;
-
- if(enemyHit){
- playerChar.health -= EmberDrake.damage;
- view.displayHealth(playerChar.health);
- storyBoard.innerHTML = "You got hit by the EmberDrake";
- }
-
- else{
- storyBoard.innerHtml = "You dodged the attack"
- }
-
- if(playerChar.health <= 0){
- playerChar.health = 0;
- story = storyEvent[6].text;
- storyBoard.innerHTML = story;
- this.updateGameUi()
- }
- else{
- gameState = "inBattle";
- turn = "player";
- }
- if(gameState !== "defending" || turn !== "enemy"){
- this.updateGameUi();
- return this.battle;
- }
-
-}
-
-
-
-
-}
-//THIS HOLDS ALL THE PLAYERS INFO. SKILLS ACQUIRED IN THE GAME WILL LATER BE ADDED HERE AND RESET WHEN THE GAME IS RESTARTED
-let playerChar = {
- name: "Adventurer",
- health: 4,
- damage: 4,
- accuracy: 0.7,
- pickUpSword(weapon){
- playerChar.sword = weapon;
- pickUpswordItem.style.display = "none";
- if(playerChar.sword == gameWeapons.swords[0] && playerChar.shield == gameWeapons.shield[0]){
- contdBtn.style.display = "block";
- }
- },
-
- pickUpShield(guard){
- playerChar.shield = guard;
- pickUpshieldItem.style.display = "none";
- if(playerChar.sword == gameWeapons.swords[0] && playerChar.shield == gameWeapons.shield[0]){
- contdBtn.style.display = "block";
- }
- },
- strike(){
- if(this.sword == gameWeapons.swords[0]){
- let attackstrike = gameLogic.attackHits(this.accuracy);
- return attackstrike;
- }
- else if(this.sword == gameWeapons.swords[1]){
- this.damage = 5;
- this.accuracy = 0.75;
- let attackstrike = gameLogic.attackHits(this.accuracy);
- return attackstrike;
-
- }
- },
- defend(){
-
- let enemyHit = gameLogic.attackHits(EmberDrake.accuracy);
- console.log(enemyHit);
- return enemyHit;
-
- }
- }
-
-let EmberDrake = {
- name: "Ember Drake",
- health: 8,
- damage: 3,
- accuracy: 0.5,
-}
-
-let silverWizard = {
- name: "Silver wizard",
- health: 9
-}
-
-//THIS ARRAY HOLDS THE STORY THAT WILL LATER THE RANDOMLY INSERTED IN FOR THE PLAYER
-let storyEvent = [
-{
- type: "story",
- text: `The rain had not stopped for days. You boots sink into the black soil of the Ashen Vale. The air smells like smoke and old magic. In the distance a golden tower leans against the the sky like a broken finger. A whisper curls around you "Turn back, ${playerChar.name}. This land feeds on the brave." `
-},
-
-{
-
- type: "story",
- text: ` A Sudden crack splits the silence. The ground trembles. From behind a cluster of dead trees,
- a scaled beast lumbers forward, it's eyes glowing like coals beaneath ash-covered horns`
-},
-
-{
- type: "action",
- text: "You are offered two items. . A basic adventurer's blade and a basic adventurer's shield. You can't fight this Beast empty handed. pick your weapon"
-},
-
-{
-type: "battle1",
-text: `The creature snarls, "Your bones will warm my nest. The Ember Drake lunges`
-},
-
-{
- type: "story",
- text: `You fight back. Steel clashes against scale Fire scorches your shield. The creature rears back for one final blast of flame and you drive your blade forward. The drake collapses. Smoke rises from its fading body. Silence returns. From the ashes two objects remain untouched by the fire. You may choose one`
-},
-
-{
- type: "battleReward",
- text: `You may choose one:
-
- . A Jagged sword humming with heat
-
- . A blackened sheild that absorbs warmth instead of burning
-
- Pick your prize and continue toward the crooked tower`
-
-},
-
-{
- type: "Alternate ending",
-
- text: `Your vision blurs. The world tilts, your sword slips from your hand and clatters across the stone floor. You try to rise but your sword feels impossibly heavy. The last thing you see is the crooked tower window, lightning flashes beyond it... THEN --- Silence.`
-},
-
-{
- type: "story2",
- text: `The tower door creaks open before you can knock. Inside, candles float in midair, their flames burning blue. At the center of the chambers stands a tall figure in a silver robe. His eyes shine with cold amusement "Impressive ${playerChar.name}", the sorcerer says softly. "Few survive my guardian". The candles extinguish all at once`
-
-},
-
-{
- type: "battle2",
- text: `Dark energy coils around him, the air grows heavy. You charge... Shadows twist into blades, illusions flicker. The sorcerer vanishes and reappears behind you, laughing`,
- text2: `You anticipate his movements. You strike when he materializes. The spells around him shatters like glass. The veil sorcerer falls to his knees `
-}
-]
-
-
-
-function progressStory(){
- while(initialStart){
- contdBtn.innerHTML = "CONTINUE ON PATH";
- initialStart = false;
- }
-//CHECKING FOR STORY CONDITIONS
- if(storyEvent[pageFlip].type === "story" && gameState === "exploring"){
- story = storyEvent[pageFlip].text;
- storyBoard.innerHTML = story;
- pageFlip++
- }
-
- else if(storyEvent[pageFlip].type == "action"){
- contdBtn.style.display = "none";
- pickUpswordItem.style.display = "block";
- pickUpshieldItem.style.display = "block";
- story = storyEvent[pageFlip].text;
- storyBoard.innerHTML = story;
- pickUpswordItem.innerHTML = gameWeapons.swords[0];
- pickUpshieldItem.innerHTML = gameWeapons.shield[0];
- pageFlip++
- pickUpswordItem.addEventListener("click", ()=>playerChar.pickUpSword(gameWeapons.swords[0]))
- pickUpshieldItem.addEventListener("click", ()=>playerChar.pickUpShield(gameWeapons.shield[0]))
- }
-
- else if(storyEvent[pageFlip].type == "battle1"){
- gameState = "inBattle";
- gameLogic.updateGameUi();
- story = storyEvent[pageFlip].text
- storyBoard.innerHTML = story;
- }
-
-
-}
-
-
-
-
-
-sword.addEventListener("click", ()=>{
- if(gameState === "inBattle"){
- gameLogic.battle();
- }
-});
-shield.addEventListener("click", ()=>{
- if(gameState === "defending"){
- gameLogic.defence();
- }
-});
-
-
-
-//THIS WILL START THE GAME
-function startGame(){
- if(gameState === "exploring"){
- progressStory();
- }
-}
- contdBtn.addEventListener("click",startGame)
diff --git a/src/story.js b/src/story.js
new file mode 100644
index 0000000..6ef34ee
--- /dev/null
+++ b/src/story.js
@@ -0,0 +1,104 @@
+// `story.js` contains the storyline of our gameplay
+// It makes use of an array `storyEvent` that stores each sequence of stories in an object
+// Objects have a :
+// 1. gameState - signifying if its just a normal sequence of our story or an action sequence
+// 2. text - stores our story
+
+import { Characters, EmberDrake, SilverWizard } from "./characters.js";
+import { Basic_Blade, Basic_shield, Slithering_Blade, Slithering_Shield } from "./weapons.js";
+
+
+export let story = [
+{
+ gameState: "exploring",
+ text: `The rain had not stopped for days. You boots sink into the black soil of the Ashen Vale. The air smells like smoke and old magic. In the distance a golden tower leans against the the sky like a broken finger. A whisper curls around you "Turn back, Adventurer. This land feeds on the brave." `
+},
+
+{
+ gameState: "powerup",
+
+ sword: Basic_Blade,
+
+ shield: Basic_shield,
+
+ text: "You are offered two items to help continue your quest. . A basic adventurer's blade and a basic adventurer's shield. You can't fight this Beast empty handed. pick your weapon"
+},
+
+{ gameState: "exploring",
+ text: ` A Sudden crack splits the silence. The ground trembles. From behind a cluster of dead trees,
+ a scaled beast lumbers forward, it's eyes glowing like coals beaneath ash-covered horns`
+},
+
+{
+ gameState: "exploring",
+
+ text: `The creature snarls, "Your bones will warm my nest. The Ember Drake lunges`
+},
+
+{
+
+gameState: "action",
+
+villian: EmberDrake
+
+},
+
+{
+ gameState: "exploring",
+ text: `You fight back. Steel clashes against scale Fire scorches your shield. The creature rears back for one final blast of flame and you drive your blade forward. The drake collapses. Smoke rises from its fading body. Silence returns. From the ashes two objects remain untouched by the fire. You may choose one`
+},
+
+{
+ gameState: "exploring",
+
+ text: `You may choose one:
+
+ . A Jagged sword humming with heat
+
+ . A blackened sheild that absorbs warmth instead of burning
+
+ Pick your prize and continue toward the crooked tower`
+
+},
+
+{
+ gameState: "powerup",
+ sword: Slithering_Blade,
+ shield: Slithering_Shield
+
+
+},
+
+{
+ gameState: "exploring",
+ text: `The tower door creaks open before you can knock. Inside, candles float in midair, their flames burning blue. At the center of the chambers stands a tall figure in a silver robe. His eyes shine with cold amusement "Impressive Adventurer", the sorcerer says softly. "Few survive my guardian". The candles extinguish all at once`
+
+},
+
+{
+ gameState: "exploring",
+ text: `Dark energy coils around him, the air grows heavy. You charge... Shadows twist into blades, illusions flicker. The sorcerer vanishes and reappears behind you, laughing`,
+},
+
+{
+ gameState: "action",
+
+ villian: SilverWizard
+},
+
+{
+ gameState: "exploring",
+
+ text: `You anticipate his movements. You strike when he materializes. The spells around him shatters like glass. The veil sorcerer falls to his knees `
+}
+
+]
+
+export const alternate = [
+
+ { gameState: "Alternate ending",
+
+ text: `Your vision blurs. The world tilts, your sword slips from your hand and clatters across the stone floor. You try to rise but your sword feels impossibly heavy. The last thing you see is the crooked tower window, lightning flashes beyond it... THEN --- Silence.`
+ }
+
+]
\ No newline at end of file
diff --git a/src/style.css b/src/style.css
new file mode 100644
index 0000000..4299441
--- /dev/null
+++ b/src/style.css
@@ -0,0 +1,167 @@
+* {
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0;
+ min-height: 100vh;
+ font-family: 'Georgia', 'Times New Roman', serif;
+ background-color: #000;
+ background-image: linear-gradient(rgba(0,0,0,0.25), rgba(0,0,0,0.25)), url('../img/ancient-egypt-papyrus-scroll-cartoon-vector-56185862.jpg');
+ background-position: center;
+ background-size: contain;
+ background-repeat: no-repeat;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 24px;
+ color: #2b1508;
+ overflow-x: hidden;
+}
+.container {
+ width: min(760px, 100%);
+ max-width: 920px;
+ margin: 0 auto;
+ display: block;
+}
+
+.inner-container {
+ width: 100%;
+ padding: 24px;
+ box-sizing: border-box;
+}
+
+/* Container and inner-container styles are inlined into the HTML to remove class selectors while preserving responsiveness */
+
+.hero-bar {
+ width: 100%;
+ min-height: 82px;
+ padding: 12px 18px;
+ background: linear-gradient(90deg, rgba(96, 60, 24, 0.95), rgba(146, 92, 36, 0.9));
+ border: 2px solid #c89a4d;
+ border-radius: 14px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-wrap: wrap;
+ gap: 12px;
+ color: #fff7e6;
+ font-family: 'Impact', 'Arial Narrow Bold', sans-serif;
+ letter-spacing: 1px;
+ text-transform: uppercase;
+}
+
+.HB,
+.attack,
+.inventory,
+.story,
+.explorebtn,
+.sword,.shield
+ {
+ background: linear-gradient(135deg, rgba(255, 242, 212, 0.98), rgba(212, 166, 94, 0.95));
+ color: #2b1508;
+ border: 2px solid #6b4326;
+ border-radius: 8px;
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), 0 6px 14px rgba(0, 0, 0, 0.28);
+}
+
+.HB,
+.attack,
+.inventory,
+.story {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ padding: 12px 16px;
+ cursor: pointer;
+ min-width: 120px;
+ text-align: center;
+ flex: 1 1 120px;
+ max-width: 180px;
+}
+
+/* Prevent hero bar and buttons from overflowing on small screens */
+@media (max-width: 720px) {
+ .container { width: 95%; }
+ .hero-bar { padding: 8px; gap: 8px; }
+ .HB, .attack, .inventory, .story { min-width: 64px; padding: 8px 10px; max-width: 140px; }
+ .storyboard { padding: 12px; min-height: 140px; }
+ .explorebtn { width: 140px; }
+}
+
+@media (max-width: 420px) {
+ .hero-bar { flex-direction: column; align-items: stretch; }
+ .HB, .attack, .inventory, .story { width: 100%; max-width: 100%; }
+ .explorebtn { width: 100%; }
+}
+
+.HB:hover,
+.attack:hover,
+.inventory:hover,
+.story:hover,
+.explorebtn:hover,
+.sword:hover,.shield:hover {
+ border-color: #e6bb4e;
+ transform: translateY(-1px);
+ transition: all 0.2s ease;
+}
+
+.storyboard {
+ width: 100%;
+ min-height: 180px;
+ margin: 22px 0;
+ padding: 20px 22px;
+ background: rgba(255,255,255,0.06);
+ border: 2px solid rgba(107,66,38,0.55);
+ border-radius: 14px;
+ color: #dbd6d6;
+ font-family: 'Georgia', serif;
+ font-style: italic;
+ font-size: 1.05rem;
+ line-height: 1.6;
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.04), 0 6px 18px rgba(0,0,0,0.25);
+ backdrop-filter: blur(1px);
+}
+
+.explorebtn {
+ width: 180px;
+ padding: 12px 16px;
+ margin: 10px auto 20px;
+ text-align: center;
+ font-family: 'Impact', 'Arial Narrow Bold', sans-serif;
+ font-weight: 400;
+ font-style: italic;
+ cursor: pointer;
+}
+
+.explorebtn, .HB, .attack, .inventory, .story { color: #2b1508; }
+
+
+.weapon {
+ padding: 16px 0 8px;
+ display: none;
+ justify-content: center;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+
+.shield,.sword {
+ padding: 12px 16px;
+ width: min(180px, 100%);
+ text-align: center;
+ font-family: 'Impact', 'Arial Narrow Bold', sans-serif;
+ font-weight: 400;
+ font-style: italic;
+ color: #4d2f16;
+
+}
+
+#health {
+ font-weight: bold;
+}
+
+#health2 {
+ opacity: 0.9;
+}
+
diff --git a/src/updateUi.js b/src/updateUi.js
new file mode 100644
index 0000000..52566f6
--- /dev/null
+++ b/src/updateUi.js
@@ -0,0 +1,52 @@
+export function showExploreBtn(){
+ let exploreBtn = document.getElementById("explorebtn");
+ exploreBtn.style.display = "block";
+ }
+
+export function hideExploreBtn(){
+ let exploreBtn = document.getElementById("explorebtn");
+ exploreBtn.style.display = "none";
+}
+
+export function displayWeapons(){
+ let weapons = document.querySelector(".weapon");
+ weapons.style.display = "flex";
+ }
+
+ export function hideWeapons(){
+ let weapons = document.querySelector(".weapon")
+ weapons.style.display = "none";
+ }
+
+ export function ShowText(text){
+ let storyBoard = document.getElementById("storyboard");
+ storyBoard.innerHTML = text;
+ }
+
+ export function hideSword(){
+ let sword = document.querySelector(".sword");
+ sword.style.display = "none"
+ }
+
+ export function hideShield(){
+ let shield = document.querySelector(".shield");
+ shield.style.display = "none"
+ }
+
+ export function showShield(){
+ let shield = document.querySelector(".shield");
+ shield.style.display = "block"
+ }
+
+ export function showSword(){
+ let sword = document.querySelector(".sword");
+ sword.style.display = "block"
+ }
+
+ export function btnText(weapon_1,weapon_2){
+ let sword = document.querySelector(".sword");
+ let shield = document.querySelector(".shield");
+ displayWeapons();
+ sword.innerHTML = weapon_1;
+ shield.innerHTML = weapon_2;
+ }
\ No newline at end of file
diff --git a/src/weapons.js b/src/weapons.js
new file mode 100644
index 0000000..f35fc3a
--- /dev/null
+++ b/src/weapons.js
@@ -0,0 +1,23 @@
+import * as characters from "./characters.js";
+
+class Sword{
+ constructor(name,damage,accuracy){
+ this.name = name;
+ this.damage = damage;
+ this.accuracy = accuracy;
+ }
+}
+
+class Shield{
+ constructor(name,block){
+ this.name = name;
+ this.block = block;
+ }
+}
+
+export const Basic_Blade = new Sword("Basic Blade",3,3);
+export const Basic_shield = new Shield("Basic Shield",3);
+export const Slithering_Blade = new Sword("Slithering_Blade",4,5);
+export const Slithering_Shield = new Shield("Slithering Shield",4);
+export const Lightning_Blade = new Sword("Lightning_Blade",5,6);
+export const Lightning_Shield = new Shield("Lightning_Shield",6);
\ No newline at end of file
diff --git a/test.html b/test.html
deleted file mode 100644
index e7b8414..0000000
--- a/test.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
- test
-
-
-
-
-
- Whatever you do do not resize this window
-
-
-
-
-
-
\ No newline at end of file
diff --git a/tests/logic.test.js b/tests/logic.test.js
new file mode 100644
index 0000000..793e3c2
--- /dev/null
+++ b/tests/logic.test.js
@@ -0,0 +1,14 @@
+import {describe, test, it, expect } from "vitest";
+
+import { hits } from "../src/logic";
+
+describe('hits', ()=>{
+ it('Should return true when accuracy is greater than hit',()=>{
+
+ const accuracy = 5;
+
+ let result = hits(accuracy);
+
+ expect(result).toBe(true);
+ })
+})
\ No newline at end of file