Difference between revisions of "Complete roguelike tutorial using C++ and libtcod - part 9: spells and ranged combat"

From RogueBasin
Jump to navigation Jump to search
Line 10: Line 10:


This dreadful spell will deal 20 damage to the closest monster, up to a distance of 5 tiles. So the first thing we need is some helper functions to get the closest monster within a range.
This dreadful spell will deal 20 damage to the closest monster, up to a distance of 5 tiles. So the first thing we need is some helper functions to get the closest monster within a range.
===Some helpers===
The easiest is a function to get the distance from an actor to a specific tile of the map :
Actor.hpp
float getDistance(int cx, int cy) const;
Actor.cpp
float Actor::getDistance(int cx, int cy) const {
    int dx=x-cx;
    int dy=y-cy;
    return sqrtf(dx*dx+dy*dy);
}
Well that was a small warmup. Don't forget to include math.h for the sqrtf function. Now let's do something manlier.
Engine.hpp
Actor *getClosestMonster(int x, int y, float range) const;
This function returns the closest monster from position x,y within range. If range is 0, it's considered infinite. If no monster is found within range, it returns NULL.
Engine.cpp
Actor *Engine::getClosestMonster(int x, int y, float range) const {
    Actor *closest=NULL;
    float bestDistance=1E6f;
First we declare some variable. closest is the closest monster found so far. bestDistance is the distance for the closest monster found so far. We initialize it with a value higher than any possible value (1E6 == 1000000) so that the first monster in the range will be a candidate. So let's iterate over the actors list and check alive monsters :
for (Actor **iterator=actors.begin();
    iterator != actors.end(); iterator++) {
    Actor *actor=*iterator;
    if ( actor != player && actor->destructible
        && !actor->destructible->isDead() ) {
Now let's check if the guy is within range and closer than what we found so far.
            float distance=actor->getDistance(x,y);
            if ( distance < bestDistance && ( distance <= range || range == 0.0f ) ) {
                bestDistance=distance;
                closest=actor;
            }
        }
    }
    return closest;
}




[[Category:Developing]]
[[Category:Developing]]

Revision as of 12:04, 16 October 2015

Complete roguelike tutorial using C++ and libtcod
-originally written by Jice
Text in this tutorial was released under the Creative Commons Attribution-ShareAlike 3.0 Unported and the GNU Free Documentation License (unversioned, with no invariant sections, front-cover texts, or back-cover texts) on 2015-09-21.


In this article, we'll start to add diversity to the gameplay by adding three new spells :

  • lightning bolt : deals damages to the closest enemy
  • fireball : powerful area effect spell
  • confusion : turns the selected enemy into a randomly wandering zombie for a few turns

The scroll of lightning bolt

This dreadful spell will deal 20 damage to the closest monster, up to a distance of 5 tiles. So the first thing we need is some helper functions to get the closest monster within a range.

Some helpers

The easiest is a function to get the distance from an actor to a specific tile of the map :

Actor.hpp

float getDistance(int cx, int cy) const;

Actor.cpp

float Actor::getDistance(int cx, int cy) const {
   int dx=x-cx;
   int dy=y-cy;
   return sqrtf(dx*dx+dy*dy);
}

Well that was a small warmup. Don't forget to include math.h for the sqrtf function. Now let's do something manlier.

Engine.hpp

Actor *getClosestMonster(int x, int y, float range) const;

This function returns the closest monster from position x,y within range. If range is 0, it's considered infinite. If no monster is found within range, it returns NULL.

Engine.cpp

Actor *Engine::getClosestMonster(int x, int y, float range) const {
   Actor *closest=NULL;
   float bestDistance=1E6f;

First we declare some variable. closest is the closest monster found so far. bestDistance is the distance for the closest monster found so far. We initialize it with a value higher than any possible value (1E6 == 1000000) so that the first monster in the range will be a candidate. So let's iterate over the actors list and check alive monsters :

for (Actor **iterator=actors.begin();
   iterator != actors.end(); iterator++) {
   Actor *actor=*iterator;
   if ( actor != player && actor->destructible 
       && !actor->destructible->isDead() ) {
Now let's check if the guy is within range and closer than what we found so far.
           float distance=actor->getDistance(x,y);
           if ( distance < bestDistance && ( distance <= range || range == 0.0f ) ) {
               bestDistance=distance;
               closest=actor;
           }
       }
   }
   return closest;
}