Wednesday, April 30, 2014

Creature Attacks

The creatures in the game include a goblin, a snake, a wizard, and a dragon. The creature attacks are all located in a single function, and the attack initiated depends on the level you are on. The attacks happen   on a clock schedule.

void creatureAttack()
{
  float miss;
  float hit;
  
  passedAttackTime = millis() - savedAttackTime;
  
  if (passedAttackTime > totalAttackTime)
  …

Let's look at the goblin attack on level 1:

if (level == 1)
  {
   enemySound = minim.loadFile("SWORD.wav");
   miss = random(1,10);
   if (miss < 7)
   { 
     hit = random(5,15);
     damage = round(hit);
     hp -= damage;
     fill(255,0,0,40);
     stroke(255,0,0,40);
     rect(0,0,width,height);
     if (!attaText)
     {
      attaText = !attaText; 
     }
  }
  else
  {
     fill(255,0,0,10);
     stroke(255,0,0,10);

     rect(0,0,width,height);
     if (!missText)
     {
      missText = !missText; 
     }
  }
 }

The goblin attacks with an axe, so a 'sword' sound effect is used to represent a goblin attack. Then, a random number determines whether the goblin actually hits or misses the player. The goblin thus has a 30% chance of missing.

If the goblin hits you, a random number is generated between 5 and 15.

The round command will round the number to an integer, so you can't lose 7.33423521 HP. The damage then be deducted from the player HP.

Finally, a transparent red light will fill the screen, to represent the hit, and a boolean is set to display text in a later function. If the goblin misses, the red light is even more transparent, and a different boolean is set.

Now, let's look at the snake attack.

 else if (level == 2)
 {
   miss = random(1,10);
    enemySound = minim.loadFile("SNAKE.wav");
   if (miss < 9)
  { 
     hit = random(8,25);
     damage = round(hit);
     hp -= damage * playerResistanceP;
     fill(255,0,0,40);
     stroke(255,0,0,40);

     rect(0,0,width,height);
     if (!attaText)
     {
      attaText = !attaText; 
     }
  }


It looks identical to the goblin attack, just with different variables (more damage, less chance of missing). However, notice that hp is deducted by damage * playerResistanceP, so if a poison shield is generated (setting your wand to cast poison), it cuts the blow into half of the generated damage.

Tuesday, April 29, 2014

Credits

CREDITS:

Code-

Adam Lastowka
http://www.openprocessing.org/sketch/58970

Konkuk University
Department of Dynamic Media
http://www.openprocessing.org/sketch/144900

Graphics-

gorchakov.artem
"Gloomy Forest"
https://www.flickr.com/photos/ghor/8394379683/

E-Zara
"Desert Sand Sand Dunes"
http://pixabay.com/en/desert-sand-sand-dunes-143124/

Eric E Castro
"John Muir Glacier"
http://commons.wikimedia.org/wiki/File:John_Muir_Glacier.jpg

Photochrom Print
"Neuschwanstein Castle LOC print rotated.jpg"
http://en.wikipedia.org/wiki/File:Neuschwanstein_Castle_LOC_print_rotated.jpg

W-Dueck
"Moonless Night"

"Kalamitsi Beach, Ionian Sea, Lefkada Island, Greece"

Creatures:

evilestmark
"Goblin"
http://openclipart.org/image/800px/svg_to_png/65551/goblin.png

dakadi
"Dragon"
http://openclipart.org/image/800px/svg_to_png/141691/dd.png

nizips
"Magician"
http://openclipart.org/image/800px/svg_to_png/29503/magician.png

sirrob
"Rattlesnake"
http://openclipart.org/image/800px/svg_to_png/170138/Rattlesnake.png

Music-

"The Descent", "Crusade", "All That", "Truth of the Legends" by Kevin MacLeod
incompetech.com

Sound Effects

Erdie
"Sword04"
http://www.freesound.org/people/Erdie/sounds/27858/

Jamius
"Snake Attack, Verbal Pulse"
http://www.freesound.org/people/Jamius/sounds/41531

Julien Matthey
"JM FX Fireball"
http://www.freesound.org/people/Julien%20Matthey/sounds/105016/

Qubodup
"Poison Spell Magic"
http://www.freesound.org/people/qubodup/sounds/219566/

RICHERlandTV
"Magic"
http://www.freesound.org/people/RICHERlandTV/sounds/216089/

RobinHood76
"Dragon's Breath"
http://www.freesound.org/people/Robinhood76/sounds/66642

Timbre
"Another Magic Wand Spell Tinkle"
https://www.freesound.org/people/Timbre/sounds/221683/

Urupin
"Fast Freezing Ice"
http://www.freesound.org/people/urupin/sounds/192415/

Zixem
"Mystic 2"
https://www.freesound.org/people/Zixem/sounds/69506/








Using Magic

The bulk of the gameplay involves the player casting magic spells on opponents. The wand cannot move more than 1/3rd of the screen from the bottom. Additionally, the wand can be pointing to the northwest, north, or northeast. First, the player will select the spell to use:

void keyPressed()
{
  
  if (key == CODED)
  {
    if ((keyCode == LEFT) && (wandX < 35))
    {
      wandX += 35; 
      
    }
    else if ((keyCode == RIGHT) && (wandX > -35))
    {
      wandX -= 35; 
    }
    
  }
  else if (key == 'f')
    {
     type = 1; 
     userSound = minim.loadFile("FIRE.wav");
     magicEffect = color(255,0,0);
     magicEffect2 = color(255,100,0);
                playerResistanceM = 1;
          playerResistanceI = 1;
                          playerResistanceP = 1;

    }
   else if (key == 'i')
   {

    type = 2;
         userSound = minim.loadFile("ICE.wav");
         magicEffect = color(0,0,255);
         magicEffect2 = color(0,200,255);
                    playerResistanceM = 1;
          playerResistanceI = 0.5;
                          playerResistanceP = 1;


   }
   else if  (key == 'm')
   {
          userSound = minim.loadFile("MAGIC.wav");

     type = 3;
          magicEffect = color(155,0,155);
          magicEffect2 = color(255,0,0);
          playerResistanceM = 0.5;
          playerResistanceI = 1;
                playerResistanceP = 1;




   }
    else if (key == 'p')
    {
          userSound = minim.loadFile("ICE.wav");    //Right now, the poison file doesn't work, substituting ice sound.

      type = 4; 
      magicEffect = color(0,155,0);
      magicEffect2 = color(0,255,100);
      playerResistanceI = 1;
      playerResistanceM = 1;
      playerResistanceP = 0.5;



    }
    else if (key == 's')
    {
      type = 5;
           userSound = minim.loadFile("SWORD.wav");
      playerResistanceM = 1;
          playerResistanceI = 1;
                          playerResistanceP = 1;


      magicEffect = color(200);
    }
    else if (key == 'h')
    {
     type = 6; 
     userSound = minim.loadFile("HEAL.wav");
     magicEffect = color(255,255,0);
     magicEffect2 = color(255,255,100);
           playerResistanceM = 1;
          playerResistanceI = 1;
                          playerResistanceP = 1;

    }
    else if (key == 'c')
    {
     type = 7;
          userSound = minim.loadFile("RECHARGE.wav");

     magicEffect = color(0,255,155);
     magicEffect2 = color(0,255,255); 
           playerResistanceM = 1;
          playerResistanceI = 1;
                          playerResistanceP = 1;

      
    }
    {
    }
    
}

When the appropriate key is pressed, the user sound effect and spell color. If the player types 's' for the sword, the wand is redrawn to look like a sword. Likewise, the arrow keys move the wand direction.

When the player clicks (to use the wand), the program will check:



1. Player SP (to make sure the player has enough spell points)
2. What spell (to know what to use)



//Mouse Pressed

void mousePressed()
{  
  if (!cast)
  {
    if (type == 5)
    {
         cast = !cast;
         
        if (level == 1)
       {     
        if (goblin.swing())
        {
          goblin.impact(); 
        }
       }
       
       else if (level == 2)
       {
        if (snake.swing())
        {
          snake.impact(); 
        }
         
       }
       else if (level == 3)
       {
        if (wizard.swing())
        {
          wizard.impact(); 
        }
         
       }
      else if (level == 4)
       {
        if (dragon.swing())
        {
          dragon.impact(); 
        }
         
       }
    }
    else
    {
    
    if (!checkSP())
    {
      if (!low)
      {
          low = !low;
          if (attaText)
          {
            attaText = !attaText;
          }
          if (missText)
          {
           missText = !missText; 
          }
      }
    }
    else
    {
      if (low)
      {
        low = !low;
      }
   cast = !cast; 
   if (type == 1)
   {
        sp -= 10; 
   }
   else if (type == 2)
   {
        sp -= 10; 
   }
   else if (type == 3)
   {
        sp -= 20; 
   }
   else if (type == 4)
   {
        sp -= 5; 
   }
   else if (type == 6)
   {
     sp -= 15;
   }


If the wand is a catcher, it does nothing if clicked.

   else if (type == 7)
   {
    cast = !cast; 
   }
    }

  }
  }
}

Meanwhile, a boolean variable will check whether the mouse has been clicked. If so, it will cast the spell and reset the variable.If you are using a healing spell, the for loop is ignored and simply uses an ellipse emitting from the wand.

if (cast)
  {
     userSound.rewind();  //sound effect, see (Sound & music)
     userSound.play();
    if (type == 6)
    {
      if (hp < maxHP)
      {
      hp += 25;
      }
      if (hp > maxHP)
      {
       hp = maxHP; 
      }
      
      fill(magicEffect, 70);
      stroke(magicEffect,70);
      ellipse(castPosX,castPosY,150,150);
      cast = !cast;
    }
   else 
   {

   if (sparks <= 15) 
   {
     magic.add(new Magic(castPosX,castPosY,wandX));
   }

A for loop will then check to see if any of the magic effects hit the creature.  The design is adapted from Park Hyebin, Konkuk University. 

   for (int i = magic.size()-1; i >= 0; i--)        //Adapted from circle motion by Park Hyebin, Konkuk University - http://www.openprocessing.org/sketch/144900
    {

       Magic m = (Magic) magic.get(i);
       m.move(); 
       m.display();
       if ((level == 1) && (goblin.hit(m)))
       {
         goblin.impact();
         magic.remove(i);
         sparks++;
       }
       else if ((level == 2) && (snake.hit(m)))
       {
         snake.impact();
         magic.remove(i);
         sparks++;
       }
       else if ((level == 3) && (wizard.hit(m)))
       {
         wizard.impact();
         magic.remove(i);
         sparks++;
       }
     else if ((level == 4) && (dragon.hit(m)))
       {
         dragon.impact();
         magic.remove(i);
         sparks++;
       }
       if (m.finished())
       {
          magic.remove(i); 
          sparks++;
        }

If the creature is defeated, the for loop is ended (so the next creature can be created).

      if (defeated)
       {
        i = magic.size()-1;

        defeated = !defeated; 
       }


Monday, April 28, 2014

Game Rules

Battle of Magic: Game Rules

Objective: Defeat four creatures (goblin, snake, wizard, ice dragon)

To cast a spell, simply click on the mouse. The spell will cast if you have enough SP. The wand can only be moved in the bottom third of the screen. Use the left/right arrow keys to change directions of the wand.

PLAYER SPELLS:

Fire: Type 'f' on the keyboard to switch to the spell. The fire spell releases red pellets. Each pellet that hits a creature will do between 2 and 8 damage to the creature, before resistances. It costs 10 Spell Points.

Ice: Type 'i' on the keyboard to switch to the spell. The ice spell releases blue  pellets. Each pellet that hits a creature will do between 1 and 10 damage to the creature, before resistances. It costs 10 Spell Points. (Obviously, the difference here is it can do more damage than fire, but it can also do less.)

Magic: Type 'm' on the keyboard to switch to the spell. The general magic spell releases purple pellets. Each pellet that hits a creature will do between 5 and 25 damage to the creature, before resistances. It costs 20 spell points - the more powerful, the more draining.

Poison: Type 'p' on the keyboard to switch to the spell. The poison spell releases green pellets. Each pellet that hits a creature will do between 1 and 5 damage to the creature, before resistances. It costs 5 spell points.

Healing: Type 'h' on the keyboard to switch to the spell. The healing spell releases a yellow light, and will heal the player for 25 points. It costs 15 spell points.


Other Uses:

Sword -  Type 's' on the keyboard to switch to the spell. The sword can be used by clicking directly on the creature. It does between 1 and 8 damages to the creature, before resistances. The advantages of the sword are that, unlike the wand, it can be moved anywhere on the screen and costs no SP to use. Obviously, the disadvantage of the sword are that (1) cumulatively, there are more resistances to the sword, and (2), creatures can parry a blow.

Catcher - Small energy triangles will fall from the sky throughout the game. These can restore spell points, if you switch your wand to catcher mode and catch some (5 SP for each triangle).

(10 SP is returned to the player every several seconds)


CREATURES:

Level 1 - Goblin: The goblin is the easiest creature to defeat. He has 1500 HP, attacks with a melee weapon, and can do between 5 to 15 damage. The goblin has 20% armor, and no resistances otherwise.

Level 2 - Snake: The snake has 2000 HP and bites, doing between 8 to 25 damage. The snake is immune to poison, has a 50% resistance to fire, and a 20% resistance to ice.

Level 3 - Wizard: The wizard has 2500 HP and uses magic to attack. He is immune to magic, and resists fire and ice by 50%.

Level 4 - Ice Dragon: The most powerful creature of all, the Ice Dragon boasts 3000 HP and immunity to ice. Additionally, the ice dragon resists fire by 25%, magic by 65%, poison by 50%, and has an armor level of 70%

Note that, if you set your wand to the creature's immunity, while you can't attack, it reduces the player's blow by 50%.


Level Ascension

The game involves fighting four different creatures. Each creature is on a different 'level'. The 'level' is a global variable that increments when the variable 'creatureHP' falls to 0 (creatureHP is also a global variable, which is set to the creature's HP at the beginning of each level).


Depending on which 'level' the player is on, the program will know what to display, how effective your magic is, and how much damage the creature can blow to you.

Each level has a unique landscape. The same "level" variable is also used for victory/defeat screens.

The level code looks like:

void level()
{
  if (level == 0)
  {
     background(dark);
     fill(255,0,0);
     text("Alas... you have died by the cruel forces of the world.",width/2,height/2 - 50);
     text("You have chosen the ways of the Good Guys.",width/2,height/2); 
     text("Oh well. Maybe your battle can still be won.",width/2,height/2 + 50); 
  }
  else if (level == 1)
  {
   background(forest);
   if (!begin1)
   {
     goblin = new Creature(width/2,height/2,5,0,1,1,1,1,0.8,25);
     begin1 = !begin1;
   }
  }
   else if (level == 2)
   {
    background(desert);
   if (!begin2)
  {
     snake = new Creature(width/2,height/2,3,1,0.5,0.8,1,0,1,0);
     begin2 = !begin2;
  }
   }
  else if (level == 3)
  {
    background(castle);
    if (!begin3)
   {
     totalAttackTime = 8000;
    wizard = new Creature(width/2,height/2,5,5,0.5,0.5,0,1,1,0);
    begin3 = !begin3;
   } 
  }
  else if (level == 4)
  {
    background(glacier);
        if (!begin3)
   {
    dragon = new Creature(width/2,height/2,6,8,0.75,0,0.35,0.5,0.3,0);
    begin3 = !begin3;
   } 
  }
  else
  {
    background(beach);
    fill(0,255,0);
     text("CONGRATULATIONS!",width/2,height/2 - 50);
     text("Through skill and perserverance, you defeated Fantasy Villains, Inc.",width/2,height/2); 
     text("May you rise to become one of the greatest wizards of all time.",width/2,height/2 + 50); 
  }
  
}

About Battle of Magic

Battle of Magic is a short fantasy game, developed for INFO I-310 Multimedia Arts and Technology, a class offered at Indiana University South Bend in the Spring of 2014, taught by Professor Eric Souther.

The objective in Battle of Magic is to defeat four creatures - a goblin, a snake, a wizard, and an ice dragon. You have an arsenal of spells to use to fight the monsters (fire, ice, magic, poison, as well as a sword). You have a number of hit points and spell points.

The game features artwork from openclipart.net and other public work available under the Creative Commons license.

The game features different aspects, and each one will be discussed as to how it was programmed.