I'm developing a turn based RPG in java for android phones and I'm currently trying to figure out how to handle attacks that have extra variables beyond damage. For example, I would like to have fire attacks do an extra 10% damage when the target has a burn effect. I'm a bit unsure how to go about doing this in an efficient way and one that allows for future additions to my status/attack system.
So here are my thoughts on how I can do this:
A series of if/else statements or switch's
switch (status) {
case burned:
if (type == fire) {
damage = damage * 1.1;
}
break;
case frozen:
if (type == ice) {
damage = damage * 2;
}
break;
}
I could also use nested switches if I have many possible results for each status.
Use an two dimensional array with the x
values being statuses and the y
values being attacks or types. When you check the [x][y]
it returns a numerical value for the change that will occur in attack.
Burned Frozen
Fire [1.1] [1]
Ice [1] [2]
While both of these seem fine for now, I'm unsure if it will work for the future. Right now, I can certainly use combinations that change the damage amount, but what about attacks that have non-numerical effects where I can't simply return a value and multiply my damage by that value?
Would it be possible to generate some sort of code that represents a situation like:
burned = 1 in first position, frozen = 2 fire attack = f in 2nd position, ice = i damage mod is in the 3rd position
so a fire attack on a burned enemy would be 1-f-1.1
.
You should try to use polymorphism.
Create an interface that represents attacks, and let it declare a single method:
public interface Attack {
double doAttack(double baseDamage);
}
Then create classes that implement this interface:
public class FireAttack implements Attack {
double doAttack(double baseDamage){
return 1.1 * baseDamage;
}
}
public class IceAttack implements Attack {
double doAttack(double baseDamage){
return 2 * baseDamage;
}
}
Then instead of using switch statements in your code, do something like this:
public class Player {
private Attack mAttack;
// Somewhere in your code, you setup something like
void setFireWeapon(){
mAttack = new FireAttack();
}
// This is where the attack is taken care of
double inflictDamage() {
return mAttack.doAttack();
}
}
What this allows you to do is to implement any new type of attack you may wish in the future, and simply assign Attack mAttack
with this new implementation of interface Attack
. This is a trivial exemple, you could do some stuff much more powerfull than baseDamage * aDouble
if you wish.
There are many ways you could implement states like frozen. First you could use the same pattern I explained above.
On top of having a Attack mAttack
member, you could also add similar logic with a HealthStatus mHealthStatus
or whatever name you prefer. Then the call to inflictDamage()
would redirect the mAttack
object to the mHealthStatus
object.
Then the HealthStatus
class would again be an interface,
public interface HealthStatus {
double considerAttack(Attack anAttack);
}
which would have implementations of various states:
public class NormalStatus implements HealthStatus{
double considerAttack(Attack anAttack){
return anAttack.doAttack(); // No change here
}
}
public class FrozenStatus implements HealthStatus{
double considerAttack(Attack anAttack){
return 0; // Can't attack when froxen
}
}
public class BurnedStatus implements HealthStatus{
double considerAttack(Attack anAttack){
return anAttack.doAttack() * 2.0; // Get berserk when on fire!
}
}
You could also use the other patterns. I recommend you look at Design Patterns, which solve problems like the one you are facing.
Just to name a few.