A Shooting tower!

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

renegadeandy wrote: each enemy on each game loop :

call a function which will iterate over all enemies, find and update their tile positions
I'm assuming that you're already looping over all the game objects in order to move them. If so, you can just update the tiles during each object's movement, rather than in a separate loop.

If you're using an animator to move your objects, I'd recommend switching to doing movement yourself, since it gives you a much finer degree of control.

renegadeandy wrote: each tower or defencive unit scan for the tiles around it and shoot if something is near.

I say everygame loop, i suppose as you say it could be every 100ms or every 250ms.

**unsure how to make it do it less often but thats a problem which im sure can be easily sorted later**
Each time round your game loop, work out how long the previous frame took by diffing device->getTimer()->getTime() to get a difference in milliseconds. Either leave it as milliseconds, or divide it by 1000 to get a (float) time in seconds. I like to work in seconds, so I div by 1000.

Code: Select all

    u32 then = device->getTimer()->getTime();

    while(device->run())
//    if (device->isWindowActive())
    {
        SContext::Time = device->getTimer()->getTime();
        SContext::FrameDelta = (SContext::Time - then) / 1000.f;
        if(SContext::FrameDelta > 0.1f) // Limit the delta, in case I've been debugging
            SContext::FrameDelta = 0.1f;
        then = SContext::Time;
(SContext is a structure with all my globals in it).

For each tower, use a counter. Each frame, decrement it by the frame time. When it's <= 0, do your targeting, and set the counter to the delay that you want (e.g. 0.1f).

Code: Select all

    void doPointDefence(void)
    {
        TimeToNextPointDefenceTargetting -= SContext::FrameDelta;
        if(TimeToNextPointDefenceTargetting <= 0.f)
        {
            TimeToNextPointDefenceTargetting = SConstants::PointDefenceTargettingDelay;

            // ... do the targetting
        }
This is just a suggestion. There's nothing wrong with doing the targeting every frame, if it's relatively cheap. I like to use delays for most "AI" operations because it cuts down on processing, and simulates the reaction time of a human.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
renegadeandy
Posts: 122
Joined: Sun May 25, 2008 11:14 pm
Location: Scotland
Contact:

Post by renegadeandy »

Alright great your advice is definitely what I will act upon. One thing I am unsure about in terms of development is that you said :
Id recommend to switching to doing movement yourself
I dont really have the time or knowledge to be able to do this - which is why i opted for this in the first place so in that respect I suppose I would just calculate the tiles which the object is on each game loop i.e each device->run() game loop by calling a function in an object which does all the tiling updates for all the enemies, then all the radius calculations and decisions for shooting at enemies right after that etc etc etc

Does that sound good?

Thanks very much!

Andy
Last edited by renegadeandy on Wed Jul 02, 2008 11:52 pm, edited 1 time in total.
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

use this formula to calculate the distance.

let:
node1 = sentry in tower.
node2 = enemy foot soldier

Code: Select all


distance = node1->getPosition() - node2->getPosition();

if ( distance  is near ) {
    node1->shootAt(node2);
}

Image
renegadeandy
Posts: 122
Joined: Sun May 25, 2008 11:14 pm
Location: Scotland
Contact:

Post by renegadeandy »

renegadeandy wrote:Alright great your advice is definitely what I will act upon. One thing I am unsure about in terms of development is that you said :
Id recommend switching to doing movement yourself
I dont really have the time or knowledge to be able to do this - which is why i opted for this in the first place so in that respect I suppose I would just calculate the tiles which the object is on each game loop i.e each device->run() game loop by calling a function in an object which does all the tiling updates for all the enemies, then all the radius calculations and decisions for shooting at enemies right after that etc etc etc

Does that sound good?

Thanks very much!

Andy
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

dlangdev wrote:use this formula to calculate the distance.

let:
node1 = sentry in tower.
node2 = enemy foot soldier

Code: Select all


distance = node1->getPosition() - node2->getPosition();

if ( distance  is near ) {
    node1->shootAt(node2);
}

vector3df actually has a function to calculate the distance between two positions which would be better to use as it actually gives you a float value back rather than a vector. Also there's one a function that gives the squared distance back which is more efficient as it avoids the costly square root operation, so then you just have to compare the square distance against a squared threshold. So if you want your tower to have a 10 unit radius that it can 'see' objects in you just check the squared distance against 10*10 instead.
Image Image Image
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

this is probably the code fragment...

Code: Select all

core::vector3df t1 = forwardObserver->getPosition();
irr::f32 distance = t1.getDistanceFrom(enemyCombatant->getPosition());
if ( distance  < firingRange ) {
       general.saycommand('Unleash Hell!');
}
Image
renegadeandy
Posts: 122
Joined: Sun May 25, 2008 11:14 pm
Location: Scotland
Contact:

Post by renegadeandy »

what is forward observer in your example?!
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

Whatever you want it to be, in your case it's your tower.
Image Image Image
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

oh, sorry bout that.

i'll rewrite the code...

Code: Select all

core::vector3df t1 = tower->getPosition(); 
irr::f32 distance = t1.getDistanceFrom(sydney->getPosition()); 
if ( distance  < tower->getFiringRange() ) { 
       tower->fireAt(sydney);
} 
Image
renegadeandy
Posts: 122
Joined: Sun May 25, 2008 11:14 pm
Location: Scotland
Contact:

Post by renegadeandy »

Right - so after a lengthy break im back again - ready to do my tiling system to help track enemies and get towers to find them and shoot them.

So this is what I have so far:

Create a 2d array of A x B which holds tile objects, each tile object holds an array of object references currently on the tile.

So , i took my smallest units x and z values :

unit.x = 529.4375
unit.z = 883.667603

and my terrains x and z values :

terrain.x = 100000.031250
terrain.z = 101010.95312

and did terrain.x / unit.x and terrain.z / unit.z to give array[x][z]

Which seems to make an array of array[188][114].

Does this seem right logically to you guys?
Post Reply