x`#### Popcorn Hacks: Develop a basic combat system that allows characters to engage in battles with enemies. This will help you practice using functions, conditionals, and basic game mechanics in JavaScript.


Popcorn Hack Part 1 - 1: Using initializeData Function
  1. Add speed to the initializeData(data = null) function and give it a default value.
  2. Add seed to the HTML output.
  3. Add speed to the JSON data.
  4. Test calling initializeData with no argument, and then using a data JSON object as an argument.
Popcorn Hack Part 1 - 2: Adding IJKL Key Conditions in handleKeyDown
  1. Add a case statement for each of the IJKL keys in the handleKeyDown({ keyCode }) switch statement.
  2. Send the key code for each IJKL key to the gameObject.handleKeyDown method.
  3. Use console.log() to output gameObject.

Popcorn Hack 2: Creating a Simple Attack System
  1. Add a boolean variable named canAttack, and set it to false.
  2. Use an if statement to check if the player can attack.
  3. If canAttack is false, output “Can’t attack.”
  4. Use Math.random() to determine if the player is allowed to attack. (Tip: Use ChatGPT for help with Math.random() if needed!)
  5. This will pick a random number to decide if the attack can happen.
  6. Use console.log() for all outputs.

Popcorn Hack 3: Level Requirement Check
  1. Use the ternary operator to create an output if the player meets the level requirements.
  2. If not, output a message telling the player they are under-leveled.
  3. Use console.log() to print your output.
%%javascript
    //Popcorn Hack 1-1
    function initializeData(data = null) {
        let speed = 5;
        if(data){
            speed = data.SPEED;
        }
        return speed;
    }
   let data = {
        SPEED: 15,
    }
    console.log(initializeData())
    console.log(initializeData(data));
<IPython.core.display.Javascript object>

THIS VIDEO GIVES INSTRUCTIONS TO PLAY MY GAME. IF YOU DON’T WANT TO WATCH JUST OPEN THE CONSOLE TO PAST EVERYTHING IN MY CODE EXCEPT FOR THE %%javascript. THIS GAMR WORKS IN LITERALLY ANY CONSOLE, NOT JUST JUPYTER NOTEBOOK.

%%HTML
<video width="320" height="240" controls>
  <source src="./video.mp4" type="video/mp4">
</video>
%%js
    //prompt doesn't work in jupyter notebook btw
    const MAXLEVELDIF = 1.1;
    class Character{
        constructor(name, health, strength, speed, level){
            this.name = name;
            this.health = health;
            this.strength = strength;
            this.speed = speed;
            this.level = level;
        }
        //popcorn hack 1-2
        move(event){
            switch(event.key){
                case 'up': case 'i':
                    console.log(`${this.name} moved up.`);
                    break;
                case 'left': case 'j':
                    console.log(`${this.name} moved left.`);
                    break;
                case 'down': case 'k':
                    console.log(`${this.name} moved down.`);
                    break;
                case 'right': case 'l':
                    console.log(`${this.name} moved right.`);
                    break;  
                default:
                    console.log(`Invalid direction.`);
            }
        }
        attack(enemy){
                const damage = Math.floor(Math.random() * this.strength);
                enemy.health -= damage;
                console.log(`${this.name} attacked ${enemy.name} and caused ${damage} damage.`);
        }
        isUnderLeveled(enemy){
            if(this.level * MAXLEVELDIF < enemy.level){
                //Popcorn hack 2-3
                return this.level < enemy.level ? true : false;
            }
        }
        train(){
            this.level++;
            this.strength *= 1.1;
            this.speed *= 1.1;
            console.log(`${this.name} has trained and is now level ${this.level}. Strength increased to ${this.strength} and speed increased to ${this.speed}.`);
        }
        fight(enemy){
            if(!this.isUnderLeveled(enemy)){
                while(this.health > 0 && enemy.health > 0){
                    if(Math.random() * enemy.speed > Math.random() * this.speed){
                        console.log(`${enemy.name} attacks first this turn!`);
                        enemy.attack(this); 
                        if(this.health <= 0){
                            console.log(`${this.name} has been defeated!`);
                            break;
                        }
                        this.attack(enemy);
                        if(enemy.health <= 0){
                            console.log(`${enemy.name} has been defeated!`);
                            break;
                        }
                    }
                    else{
                        console.log(`${this.name} attacks first!`);
                        this.attack(enemy);
                        if(enemy.health <= 0){
                            console.log(`${enemy.name} has been defeated!`);
                            break;
                        }
                        enemy.attack(this);
                        if(this.health <= 0){
                            console.log(`${this.name} has been defeated!`);
                            break;
                        }
                    }
                }
            }
            else {
                return 'You are under-leveled for this enemy.';
            }
        }
    }
    class Necromancer extends Character{
        constructor(name, health, strength, speed, level, mana){
            super(name, health, strength, speed, level);
            this.mana = mana;
        }
        attack(enemy){
            if(this.health > 0){
                if(this.mana >= 10){
                    const damage = Math.floor(Math.random() * this.strength * 2);
                    enemy.health -= damage;
                    this.mana -= 10;
                    console.log(`${this.name} casts a spell on ${enemy.name} and causes ${damage} damage. Mana remaining: ${this.mana}`);
                }
                else{
                    super.attack(enemy);
                    this.mana += Math.random()*15;
                }
            }
            else{
                console.log('Why are you attacking me? I AM DEADDD')
                return;
            }
        }
        
    }
    class Warrior extends Character{
        constructor(name, health, strength, speed, level, endurance){
            super(name, health, strength, speed, level);
            this.endurance = endurance;
        }
        attack(enemy){
            if(this.health > 0){
                if(this.endurance >= 10){
                    const damage = Math.floor(Math.random() * this.strength * 1.5);
                    enemy.health -= damage;
                    this.endurance -= 5;
                    console.log(`${this.name} charges at ${enemy.name} and causes ${damage} damage. Endurance remaining: ${this.endurance}`);
                }
                else{
                    super.attack(enemy);
                    this.endurance += Math.random()*20;
                }
            }
            else{
                console.log('Why are you attacking me? I AM DEADDD')
                return;
            }
        }
    }
    let enemy = new Necromancer('Lucius', 2500, 15, 30, 5, 100);
    let protagonist = new Warrior('Santhosh', 100, 20, 25, 1, 100);
    function resetGame(){
        enemy = new Necromancer('Lucius', 2500, 15, 30, 15, 100);
        protagonist = new Warrior('Santhosh', 200, 20, 25, 1, 100);
        console.log('Hello! Welcome to this short game that I might use as an example for data abstraction. Your goat is to defeat the enemy by using protagonist.fight(enemy). But you are to weak! Spam protagonist.train() to level up!!!')
    }
    resetGame();
    // Key down thingy 
    document.addEventListener('keydown', (event) => {
        const direction = player.handleKeyDown(event);
        if (direction) {
            player.move(direction);
        }
    });
<IPython.core.display.Javascript object>

Homework:

Objectives


Option 1: Create a simple combat system.

  • Allow characters to fight enemies.
  • Use basic functions and conditionals in JavaScript.
  • Focus on making it easy to understand how battles work.


Option 2: Make a dialogue system for your NPC (Non-Player Character).

  • Use the prompt() function to ask the player for a response (choose a number from 1 to 4).
  • This dialogue should appear when the player gets close to the NPC and presses a button.

</span>

Additional Tips:

  • For Option 1:
    • Start by writing down what the characters and enemies will be. Create simple names and attributes (like health).
    • Use console.log() to print out what's happening at each step. This will help you understand the flow of your code.
    • Look for example code online to see how others have created combat systems. Don't be afraid to borrow ideas!
  • For Option 2:
    • Plan out the dialogue options before you start coding. Write them down in a list.
    • Use comments in your code to remind yourself what each part does. For example, // Ask the player for a response.
    • Test your code frequently. After writing a few lines, run it to see if it works before adding more.