Battle Engine - Alpha 6 release, downloads in first post

Ideas and games that are not yet publicly in production. This forum also contains the pre-2012 archives of the Works in Progress forum.
Message
Author
Jake
Support Hero
Posts: 3826
Joined: Sat Jun 17, 2006 7:28 pm
Contact:

Re: Battle Engine

#31 Post by Jake »

Simple movement AI done! For the following test, I have two AI enemies which have been set up with the following parameters:

Code: Select all

# The second param is the skill to use for movement.
# The optional third ('idealDistance') param is the preferred distance from opposing characters.
# The optional fourth ('hide') param tells whether or not to avoid opposition fighter LoS.
steve = MovingEnemyFighter("Steve", move, idealDistance=0, sprite=steveSprite)       # The one with the knife
jim = MovingEnemyFighter("Jim", move, idealDistance=10, hide=True, sprite=jimSprite) # The one with the sword and shield
The guy in green is the player character, who at time of screenshot sat still for two turns not doing anything. Steve has run right up next to him, 'cause he's a melee attacker and has an ideal distance of 0, so he tries to get in close; Jim is a coward with an ideal distance of A Long Way Away, and the 'hide' flag states that he tries his best to stay out of line-of-sight of player characters.

Jim is just deciding where to move to in the screenshot. The numbers over the grid squares are debug information which won't be in the release, showing the weights he's given to each of the squares he can move to - he's going to pick the one with the highest value, so he'll end up one square in from the top-left corner in the -6 square. If he didn't have the 'hide' parameter set to 'True' (the default, obviously, is 'False') then he'd have preferred the top-most square (-14 in the picture) because it's furthest away from the player fighter.
Attachments
Demonstration of AI weighting
Demonstration of AI weighting
Server error: user 'Jake' not found

blakjak
Veteran
Posts: 224
Joined: Fri Dec 21, 2007 2:36 pm
Location: France
Contact:

Re: Battle Engine

#32 Post by blakjak »

I don't understand why Jim wouldn't go to tile "-14" even if "hide" is true, unless "hide" evaluates enemy Los not by the distance between the enemy and Jim, but by predefined values ( like the "-6" ) ? In which case, my question is : what determines those values, and how come they are different than just the distance between enemy and Jim, which seems like a logical choice ?

Did I understand at least one thing correctly ? D:

Anyway, it's looking spiffy.

Jake
Support Hero
Posts: 3826
Joined: Sat Jun 17, 2006 7:28 pm
Contact:

Re: Battle Engine

#33 Post by Jake »

blakjak wrote: I don't understand why Jim wouldn't go to tile "-14" even if "hide" is true, unless "hide" evaluates enemy Los not by the distance between the enemy and Jim, but by predefined values ( like the "-6" ) ?
I possibly didn't make myself clear - 'LoS' is 'Line of Sight', it's unrelated to distance. The weights aren't pre-determined, they're calculated on the fly based on the positions of other fighters.
blakjak wrote: In which case, my question is : what determines those values, and how come they are different than just the distance between enemy and Jim, which seems like a logical choice ?
It's different than just the distance because it has to cater for multiple enemies, and because it's taking into account what's set as the 'ideal' distance, rather than just having a 'move towards enemies' or 'move away from enemies', and because it's taking into account whether or not the positions can be seen by enemies.

The algorithm to determine the weighting for a position is something like this:

Code: Select all

- set weight to 0
- for each enemy fighter
    - check the distance between the fighter and the tested position
    - find the difference between that distance and the ideal distance, and subtract it from the weight
    - if the position is actually at the ideal distance from the fighter, add 2 *
    - subtract 10 if the AI is set to 'hide' and the enemy fighter can see this position **
* This is a fairly arbitrary bonus, the intention is to avoid an AI fighter getting stuck between two 'best' positions.
** This is a serious penalty to make a 'hide' AI definitely prefer staying out of line-of-sight to being in an otherwise-ideal position. It's very likely that they'll seek out the square they can move to which the fewest enemy fighters can see.


So in the example picture, the -14 square is -14 because it's 6 squares (I'm not allowing diagonal movement in this example) from the nearest enemy but his ideal is 10 (so it gets a -6 penalty for being that far from the ideal distance), and because it's within LoS of one enemy fighter (for the remaining -10). The -6 square is only four spaces from the enemy but it's out of LoS (hiding behind the other AI fighter), so it's a preferred square for an AI set to 'hide'.
Server error: user 'Jake' not found

blakjak
Veteran
Posts: 224
Joined: Fri Dec 21, 2007 2:36 pm
Location: France
Contact:

Re: Battle Engine

#34 Post by blakjak »

I see, Los was for me related to the distance between the AI and Geoff. What I didn't know was that you had a more complex algorithm, and that Los calculation could take into account other AI fighters as visual obstacles, that's great !

Jake
Support Hero
Posts: 3826
Joined: Sat Jun 17, 2006 7:28 pm
Contact:

Re: Battle Engine

#35 Post by Jake »

blakjak wrote:I see, Los was for me related to the distance between the AI and Geoff. What I didn't know was that you had a more complex algorithm, and that Los calculation could take into account other AI fighters as visual obstacles, that's great !

It was your suggestion about having fighters protect a warlock that made me think of it - it's not so straightforward to have the fighter step in front of the warlock, but it turns out it's doable to have the warlock step behind the fighter (or, you know, a tree or a rock or something)! ;-)
Server error: user 'Jake' not found

blakjak
Veteran
Posts: 224
Joined: Fri Dec 21, 2007 2:36 pm
Location: France
Contact:

Re: Battle Engine

#36 Post by blakjak »

Oh yeah that's right ! So you did manage to code it in the end =), sweet.

I've gotta think of some other behaviours =D

User avatar
DaFool
Lemma-Class Veteran
Posts: 4171
Joined: Tue Aug 01, 2006 12:39 pm
Contact:

Re: Battle Engine

#37 Post by DaFool »

One advantage that turn-based has over realtime strategy is that one can alternate between a zoomed out macromanagement overview and an intimate micromanagement zoomed in view. While reading this article
http://www.gamasutra.com/view/news/2868 ... isions.php
I thought how Valkyria Chronicles combined both macro and micro views precisely because it was turnbased.
So my question is if it will be possible to show the full map during the unit selection phase, and a zoomed in segment during unit execution phase.

Jake
Support Hero
Posts: 3826
Joined: Sat Jun 17, 2006 7:28 pm
Contact:

Re: Battle Engine

#38 Post by Jake »

DaFool wrote: I thought how Valkyria Chronicles combined both macro and micro views precisely because it was turnbased.
To nit-pick, calling the unit-selection view in Valkyria Chronicles 'macro' is about as accurate as the word 'strategy' in 'real-time strategy' - to a wargamer, 'macro' generally means 'strategic', in the 'operational rather than tactical' sense, while Valkyria Chronicles' unit-selection is still very much the tactical map.


And honestly, I don't think it has much to do with it being turn-based; as the article itself notes, there are plenty of examples of real-time games with a tactical-overview map or the ability to zoom out and see the battlefield as a whole, I think the main reason most turn-based tactics games don't do it is because their battlefields aren't usually big enough to warrant it. UFO had a tactical map, for example. ;-)

And ultimately, mechanically-speaking VC is a pretty standard turn-based-tactics game with a nice movement/targetting system and a slightly unorthodox unit-activation mechanic, and I kind of suspect that the tactical-map view probably came about because the developers found that you couldn't differentiate characters well enough on a traditional mini-map or a zoomed-out 3D view, particularly since they still have to support SD TVs.

DaFool wrote: So my question is if it will be possible to show the full map during the unit selection phase, and a zoomed in segment during unit execution phase.
Now: No.
In the future: Hopefully.

Once the alpha is released you'll see that all graphics used by the engine are wrapped up inside a custom Displayable called BattleDisplayable, which has its own 'Show' method which calls through to renpy.show() with an appropriate Transform. One of the big reasons for this design decision is so that at some point in the future, I can have a camera scrolling around a larger battlefield simply by setting some global 'cameraX' and 'cameraY' properties and having them applied as an offset to the drawing of individual sprites. The ATL Transform allows one to set zoom and rotation as well as xpos and ypos, so I don't see any reason right now why those couldn't be added as well. (I can't think of any utility in rotating the map right now, but hey... ;-)
Server error: user 'Jake' not found

Jake
Support Hero
Posts: 3826
Joined: Sat Jun 17, 2006 7:28 pm
Contact:

Re: Battle Engine

#39 Post by Jake »

Another quick update - this lunchtime I got scenery working, so the tree in the example pictures now stands out in front of the grid and blocks movement and line of sight. In the future I hope to be able to set scenery to partially block LoS, or block LoS but not movement (curtain) or vice versa (fence), but for alpha 1 at least it'll be a relatively simple implementation.

I also forgot to mention before that for an example, I've implemented a simple elemental-magic system, so (for example) water spells will do more damage to a target with the 'fire' attribute, and less to one with 'earth'.

It reminds me of another area I'd be interested in suggestions for, though, and that's damage resolution. Attacks (at least with the example damage resolvers) come down to an 'attack' stat versus a 'defence' stat. Presently I have a fairly simple algorithm to determine damage based on attack and defence:

Code: Select all

            #calculate damage - goes up more rapidly with zero or negative def
            if (target.Stats.Defence < 1):
                defence = 2 - target.Stats.Defence
                damage = attack * defence
            else:
                damage = (attack/target.Stats.Defence)+ 0.5

            damage = int(damage * 10)
So this produces a set of damage results a bit like this:

Code: Select all

                     DEF
         0     0.5  1    1.5  2    3    4    5
       +-----+----+----+----+----+----+----+----+
    1  | 20  | 15 | 15 | 12 | 10 | 8  | 8  | 7  |
       |-----+----+----+----+----+----+----+----+
ATT 3  | 60  | 45 | 35 | 25 | 20 | 15 | 13 | 11 |
       |-----+----+----+----+----+----+----+----+
    5  | 100 | 75 | 55 | 38 | 30 | 22 | 18 | 15 |
       +-----+----+----+----+----+----+----+----+

...which has some odd discontinuities, such as between Def 0.5 and 1 or Def 3 and 4 for Att 1. Now, it's probably good enough to run a game on, but the code also isn't very elegant and it's full of arbitrary numbers, so it probably doesn't make a very good bit of example code, either. Can anyone think of, or does anyone know of, a decent f(attack,defence) => damage resolution algorithm that's simple and clean enough to make a good example without having much in the way of arbitrary numbers or special cases (e.g. for 0s)?


(The elemental-damage effects are all taken care of by modifying the attack value before it goes into this algorithm, so water vs. fire gives attack * 2, while water vs. earth gives attack * 0.5; I expect armour equipment to modify defence scores, for the most part, so I'm not - at least for the purposes of examples - interested in incorporating that kind of thing into the damage resolution directly.)
Server error: user 'Jake' not found

User avatar
DaFool
Lemma-Class Veteran
Posts: 4171
Joined: Tue Aug 01, 2006 12:39 pm
Contact:

Re: Battle Engine

#40 Post by DaFool »

I never really understood how ATK, DEF, and damage resolved in most games (same with MAG and INT). I think I'll be able to understand it better if everything were in terms of either absolute HP or a percentage thereof.

I know with most gamemakers here (Ren'Py RPG makers in particular), the damage tends to be rather miniscule (so is HP). I understand that it's purely to be able to know and test the system that it works. I'm just used to overbloated HP and damage numbers (e.g. contemporary Final Fantasies).

Also we should take note that some (most?) games will incorporate EXP and levelling up (sometimes even mid-battle), so there's a new grid to work with.

Jake
Support Hero
Posts: 3826
Joined: Sat Jun 17, 2006 7:28 pm
Contact:

Re: Battle Engine

#41 Post by Jake »

DaFool wrote:I never really understood how ATK, DEF, and damage resolved in most games (same with MAG and INT). I think I'll be able to understand it better if everything were in terms of either absolute HP or a percentage thereof.
The only ways I can think of to do a battle system which knocks off absolute percentages of HP would mean HP would be effectively a pointless stat - if an attack is going to knock off 50% of your HP all the time, it doesn't make any difference whether you have 10HP or 10,000, you're still dead in two hits!
DaFool wrote: I know with most gamemakers here (Ren'Py RPG makers in particular), the damage tends to be rather miniscule (so is HP). I understand that it's purely to be able to know and test the system that it works. I'm just used to overbloated HP and damage numbers (e.g. contemporary Final Fantasies).
To a point, larger numbers are better because it means more precision. If I get a result of 1.33333333 out of my damage calculator for a certain att/def combination, then if I just round it off I get a score of 1, meaning I lose a quarter of my damage potential. If I multiply it by 10 before rounding, I get 13, which means I only lose 2.5% of my damage potential to rounding error. Multiply it by 100, and you only lose a quarter of a percent of your damage potential to rounding. (Of course, like the stock exchange, rounding errors go up as well as down.)
(The other minor advantage to larger numbers is that it makes it more plausible to get a lucky break where your character is left with 2 or 3 hit points out of a couple of thousand, which is the kind of moment gamers will remember.)

On the other hand, it seems to me that once you've reduced your rounding error to below 1% of the average value you're talking about, there's little point in getting any bigger... the only thing that happens is that hitpoint reserves get bigger to compensate, so any enlargement of numbers after a certain point is really entirely superficial.
DaFool wrote: Also we should take note that some (most?) games will incorporate EXP and levelling up (sometimes even mid-battle), so there's a new grid to work with.
New grid? I think you possibly misunderstand the table I drew; it has Def varying left and right, and Att varying up and down, so presuming you extended it far enough in each direction you'd cover every possible combination with the same single table... I'd definitely avoid changing the formula used for different levels of character!
Server error: user 'Jake' not found

User avatar
DaFool
Lemma-Class Veteran
Posts: 4171
Joined: Tue Aug 01, 2006 12:39 pm
Contact:

Re: Battle Engine

#42 Post by DaFool »

Multiply it by 100, and you only lose a quarter of a percent of your damage potential to rounding.
Then it seems HP, ATK, and DEF in the range of 100s would be optimal (which we tend to see in most RPGs... starting numbers, anyway).

If you can make a standard table with that sort of minimal rounding error, that would probably be optimal. (Then I'd just add a x 1000 multiplier to put those rpgs with 200,000 damage to shame, just for the heck of it.)

Jake
Support Hero
Posts: 3826
Joined: Sat Jun 17, 2006 7:28 pm
Contact:

Re: Battle Engine

#43 Post by Jake »

DaFool wrote:(Then I'd just add a x 1000 multiplier to put those rpgs with 200,000 damage to shame, just for the heck of it.)
I would argue that you'd be shaming yourself by stooping to their rather superficial game, but whatever floats your boat. :3
Server error: user 'Jake' not found

User avatar
curry nochi rice
Miko-Class Veteran
Posts: 746
Joined: Sat Mar 27, 2010 3:12 am
Projects: Delicatessen, Whom to Notice, Start of Something, Love Sorcery
Organization: Circle Cosine
IRC Nick: Curry
Skype: after.curry.rice
itch: project-rothera
Contact:

Re: Battle Engine

#44 Post by curry nochi rice »

I just thought of using this for a turn-based strategy game involving units instead of individual character...

something similar to a battle plan where you move unit symbols to attack enemies.
Personal (R-13) | Now at IndieDB | Circle Cosine's itch.io
I wanna be done.

User avatar
DaFool
Lemma-Class Veteran
Posts: 4171
Joined: Tue Aug 01, 2006 12:39 pm
Contact:

Re: Battle Engine

#45 Post by DaFool »

Indeed, in fact the simplest method might even be the best. Red and blue triangles on a plain top-down map. Then during unit execution phase cue static pictures of unit in action and text dialogue showing damage inflicted.

I was just going through some isometric drawing tutorials and realized you actually have to count pixels (two pixels left/right for every pixel up/down; not really a perfect 30 degrees, just the best-looking one). Good to go through if you want some practice becoming a proficient sprite artist, but otherwise a nightmare if you really want things to stack up nicely and not look amateurish.

You can start with top-down symbolic view, then (and only then) once that milestone is achieved you can start thinking isometrically with fully animated sprites. After which if the game proves popular you can make a remake or a sequel in 3D (well that was my plan anyway), but if you think about it the core mechanics is really simple and can be done on a napkin.

Post Reply

Who is online

Users browsing this forum: No registered users