It is currently Wed Jun 19, 2019 3:42 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Thu Nov 15, 2018 5:26 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1875
In my current game, the amount of energy that a character loses shall be determined by certain attributes:

The hero has an attack value.
The hero has a defense value.
The hero has current life energy.

The opponent has an attack value.
The oponent has current life energy.
(Since the same opponent type always has the same initial values, a defense value isn't necessary here. A higher defense is simply realized by giving him more initial energy.)


When the hero gets hit by an opponent, the hero's energy loss is calculated by the opponent's attack value and the hero's defense value.

When the hero attacks an opponent, the opponent's energy loss is calculated by the hero's attack value.


Now, what is the best formula to calculate the energy loss per hit?

I've found some formulas:

damage = attack * attack / (attack + defense)

damage = attack / (100 / (100 + defense)

However, they use arbitrary multiplication and division, which is not really ideal for NES games since it eats up too much CPU time.

So, is there any good formula that can be calculated in a fast way and that has no drawbacks?
What did action adventures on the NES or Game Boy use here?


Since my game uses screen-by-screen scrolling like in "Zelda" and since weapons and items are equipped in a menu, I could maybe do an alternate approach:

I could use one of the above formulas to store the current potential hero damage and opponent damage values into the opponents' properties.
During a screen transition, the game stops for a moment anyway, so the calculation doesn't need to be ultra fast here.
Same when I equip items in a menu: I could just update each opponent's properties there.
This way, the game would simply use this one pre-calculated value to subtract from the energy and doesn't need to do any complicated calculations during live gameplay.

However, if I decide to make it possible that a new opponent enters the screen during gameplay, this could require a calculation of this forumla during live gameplay.

In the moment, new opponents cannot enter the screen, but I'm not sure if this will stay like this. Maybe bosses can spawn smaller henchmen.

One situation where new "characters" entering the screen is definitely already the case is when the opponent shoots a weapon.

And opponents and weapons have no direct relation:
An opponent has an array of movement patterns. And one step in one of those patterns might be "shoot this and that weapon".
Therefore, I cannot store a weapon damage value in an opponent's properties since the opponent definition doesn't even know directly if the opponent can shoot arrows or fireballs. Everything is independent from each other:
Certain opponent properties points to a collection of movement patterns. And any pattern can have any "spawn weapon xyz" as a command.


Another likely situation that might require calculation during live gameplay: If the hero is influenced by a temporary status value (like "cursed" or whatever those RPGs use) where, for example, his defense goes down for 20 seconds.


So, what would you suggest here? And how did old games do it?

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Thu Nov 15, 2018 5:46 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7500
Location: Canada
DRW wrote:
However, they use arbitrary multiplication and division, which is not really ideal for NES games since it eats up too much CPU time.

Unless you expect to have to resolve 20 attack damages in the same frame, the slowness of division shouldn't really be a problem here.


Top
 Profile  
 
PostPosted: Thu Nov 15, 2018 6:10 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1875
Not by itself, but the game logic does a whole bunch of other stuff as well which all adds up.

For example, this calculation:
damage = attack / (100 / (100 + defense));
where all variables are global zeropage variables of type unsigned char, requires 11 scanlines worth of CPU time. (I measured it by enabling and disabling $2001 mid-frame.)

This one:
damage = attack * attack / (attack + defense);
requires nine scanlines, so it's only slightly better.

Such values are unacceptable.
I'm aiming more for something in the range of one or two, at most three scanlines.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Thu Nov 15, 2018 7:50 pm 
Offline
User avatar

Joined: Wed Sep 07, 2005 9:55 am
Posts: 366
Location: Phoenix, AZ
Are you set on calculating these things at run-time? If not, you could use look up tables.

And IIRC, the original Zelda just right shifted enemy attack values based on which ring upgrade you had. Essentially n, n/2, or n/4.

_________________
. That's just like, your opinion, man .


Top
 Profile  
 
PostPosted: Thu Nov 15, 2018 8:00 pm 
Offline
User avatar

Joined: Sat Jan 09, 2016 9:21 pm
Posts: 614
Location: Central Illinois, USA
Quote:
Now, what is the best formula to calculate the energy loss per hit?


It's hard to answer the question of BEST without really knowing your goals, but I've often just used the much simpler and obvious method:

Code:
max(1, (attack - defense))


It has obvious disadvantages, but the advantage is that it's simple to calculate and simple to undestand.

Quote:
What did action adventures on the NES or Game Boy use here?

Zelda was mentioned already.
I'm pretty sure Crystalis used just
Code:
max(0,(attack-defense))
. (which is why you could get enemies you couldn't damage, or that couldn't damage you)
No idea what other games used.

_________________
My games: http://www.bitethechili.com


Top
 Profile  
 
PostPosted: Thu Nov 15, 2018 8:05 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1875
never-obsolete wrote:
Are you set on calculating these things at run-time? If not, you could use look up tables.

Lookup tables would be fine, but how should I do this?

Let's say you attack an opponent:
You have an attack value that is native to the hero. (I'm not yet sure whether this is a fixed value or one that increases during the game.)
Your weapon has its own attack value.
But you can also equip items that increase your attack value. (Either by adding "+ n" to the current value or by doing stuff like "NewValue = BaseValue * 2".)
Furthermore, time-based live statuses may increase or decrease the value, like when an opponent can make you weak for 20 seconds or when you can temporarily boost your status with magic.

So, it's a bit difficult to do a lookup table here.
Same with being attacked by the opponent: You have to calculate the opponent's attack value in combination with your defense value. However, your defense value is calculated based on several items and statuses.

never-obsolete wrote:
And IIRC, the original Zelda just right shifted enemy attack values based on which ring upgrade you had. Essentially n, n/2, or n/4.

Yeah, that was was really simple. But as you see, my game setup is a bit more complicated and more in line with actual RPGs, only that it's still an action game and not turn-based.

gauauu wrote:
It's hard to answer the question of BEST without really knowing your goals

What do you mean with goals?

gauauu wrote:
but I've often just used the much simpler and obvious method:

Code:
max(1, (attack - defense))

Was this commonly used? Because it looks very simple.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Thu Nov 15, 2018 8:16 pm 
Offline

Joined: Sun Mar 27, 2016 7:56 pm
Posts: 216
gauauu wrote:
It's hard to answer the question of BEST without really knowing your goals, but I've often just used the much simpler and obvious method:

max(1, (attack - defense))

Even Breath of the Wild goes for something this simple, for enemies attacking Link:

damage = max(1, base attack + max(0, weapon attack - defense))

Damage is in units of quarter-hearts, so if Link has 20 hearts, he has 80 HP.

Base attack depends on the enemy type and rank (e.g. for Bokoblins, it's 0 for red, 4 for blue, 8 for black, and 24 for silver). The effect of base attack is that attacks always do at least a set amount of damage, so no matter how stacked up on armor you are, a Silver Bokoblin will always do at least 24 damage (6 hearts) per hit, for example.

The reverse, where Link attacks enemies, is about as simple as it could possibly get:

damage = weapon attack

Enemies don't have defense at all, so they compensate with huge amounts of HP. For instance, as an extreme case, Gold Lynels, the strongest enemies in the game, have 7000 HP, the equivalent of 1750 hearts. (Luckily, the game doesn't actually tell you the correspondence between hearts and enemy HP, or it'd feel a little ridiculous.)

This does leave out a few combat mechanics (elemental damage, blocking, buffs, spin attacks, etc.), but as you can see, even a modern game can get by with simple formulas like these.


Last edited by Nicole on Thu Nov 15, 2018 10:35 pm, edited 2 times in total.

Top
 Profile  
 
PostPosted: Thu Nov 15, 2018 8:52 pm 
Offline
User avatar

Joined: Sat Jan 09, 2016 9:21 pm
Posts: 614
Location: Central Illinois, USA
DRW wrote:
What do you mean with goals?

I mean, like how you want your game balance to work. How impactful you want armor to be. Whether you're ok with the character just taking 1 damage. Whatever technique you pick will require planning armor values, enemy attack values, and player health values to achieve the balance and character progression that you want your game to have. So suggestions like mine (or what zelda does) will create a much different game than your formula. So the question comes down to: what reduces complexity but still keeps the goals you have for your game?

Quote:
Code:
max(1, (attack - defense))

Was this commonly used? Because it looks very simple.


No idea how commonly used it was. I've used it in 2 action-adventures, and I gave the example of Crystalis. But I haven't studied enough other games to know what's common.

_________________
My games: http://www.bitethechili.com


Top
 Profile  
 
PostPosted: Thu Nov 15, 2018 10:41 pm 
Offline

Joined: Tue Feb 07, 2017 2:03 am
Posts: 718
either use "hit points" which is what I would think most things would do.

or use 128 percentiles. i.e don't /100 * 100 but /128 * 128, you will need to "up" your values by say 1/5 but a lot faster and its the relative scales of what you are doing that is important not the actual raw values.


Top
 Profile  
 
PostPosted: Thu Nov 15, 2018 11:18 pm 
Offline
User avatar

Joined: Wed Sep 07, 2005 9:55 am
Posts: 366
Location: Phoenix, AZ
Quote:
Let's say you attack an opponent:
You have an attack value that is native to the hero. (I'm not yet sure whether this is a fixed value or one that increases during the game.)
Your weapon has its own attack value.
But you can also equip items that increase your attack value. (Either by adding "+ n" to the current value or by doing stuff like "NewValue = BaseValue * 2".)
Furthermore, time-based live statuses may increase or decrease the value, like when an opponent can make you weak for 20 seconds or when you can temporarily boost your status with magic.

So, it's a bit difficult to do a lookup table here.
Same with being attacked by the opponent: You have to calculate the opponent's attack value in combination with your defense value. However, your defense value is calculated based on several items and statuses.


From what it sounds like you plan to do, the attack/defense values will only involve some adds and possibly some shifts. These aren't very costly in terms of cpu cycles and the results can be cached until something changes. I was looking more at the damage formulas you gave as somewhere you could use the look up tables because there were only two inputs, the operations never change, and are costly.

With the proper look up table this:

Code:
damage = attack / (100 / (100 + defense));


would be reduced to this:

Code:
         ldy attack_val
         lda dmg_ptrlo, Y
         sta __ptr
         lda dmg_ptrhi, Y
         sta __ptr + 1
         
         ldy defense_val
         lda (__ptr), Y
         ; A now holds your damage value


Now you have to look at what the possible ranges are for attack and defense, because the table will get huge fast.

_________________
. That's just like, your opinion, man .


Top
 Profile  
 
PostPosted: Fri Nov 16, 2018 4:07 am 
Offline

Joined: Mon May 30, 2011 9:01 pm
Posts: 215
Fire Emblem uses max(0,(strength + weapon - defense))


Top
 Profile  
 
PostPosted: Fri Nov 16, 2018 8:14 am 
Offline
User avatar

Joined: Thu Sep 15, 2016 6:29 am
Posts: 896
Location: Denmark (PAL)
How you want to calculate damage really depends on the design of your game. Like, do you want a higher damage or defense rating to be a nice "added bonus", or do you want it to be central to fighting an enemy?

For example, the Dragon Quest games usually have a treshold for when you can actually do solid damage to certain enemies with high defense, and it's not like twice the defense just means you do half the damage. These games thoroughly reward (and occasionally require) using spells to boost your attack or reduce the enemy's defense. And it gives a more immediately noticeable feedback from leveling up your stats.
However, for most pure action games this approach won't work as well, as you want the player to be able to win by using skill, rather than just relying on stats. (unless we count something like the old Ys games as "action")


Top
 Profile  
 
PostPosted: Fri Nov 16, 2018 9:41 am 
Offline

Joined: Tue Aug 28, 2018 8:54 am
Posts: 143
Location: Edmonton, Canada
You can also roll to calculate your attack based on the skill and defense. It will be longer than max check, but faster than /100 division.

You have weapon
Base damage: 5
Weapon (or character) skill: 80 out of 100

Enemy
Defense: 30 out of 100

Chance to attack: 80 (Skill) - 30 (Defence) = 50

Code:
if (rand(100) < 50)
    damage = 5;
else
    damage = 0;


Now you can double your damage if you have critical chance.
Code:
if (rand(10) == 9) // assuming roll(10) gives 0-9 range
   damage = damage << 1;


These numbers are purely arbitrary, balance depends on what you want.


Top
 Profile  
 
PostPosted: Fri Nov 16, 2018 9:44 pm 
Offline

Joined: Tue Feb 07, 2017 2:03 am
Posts: 718
This is basically how D&D works..

Roll for Attack, I got a 12
Roll for Defense, they got a 8

I did 4 damage.


Top
 Profile  
 
PostPosted: Sat Nov 17, 2018 2:39 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7717
Location: Chexbres, VD, Switzerland
I'm no expert, but a random guess is that most NES-era games did it based on simple additions and substractions, possibly shifts. This makes it hard to get the balance right; for instance in Fire Emblem games (any game in the series) it's easy to be overpowered or underpowered, and this is part of the game; if you have the wrong character with wrong weapons it's not rare that you'do 0 damage per attack, and vice versa, if your character is overpowered it's not rare a weak enemy can do 0 damage per attack; and both sides can easily one-hit KO eachother.

More conventional RPGs such as Final Fantasy or Dragon Quest might use more advanced formulas, but those doesn't seem to have been developed before the SNES era. If this is inspiring for you, there is on GameFaqs:
Damage Formula FAQ for Final Fantasy III
Mechanics Guide for Chrono Trigger
Battle Mechanics FAQ and Enemy Mechanics FAQ for Final Fantasy VII

Whether those FAQs are accurate or not, and how did they figure the internal mechanics out, I do not know.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group