GameSalad

How to have a turret track like in tower defence games?

Twayne2Twayne2 Posts: 136Member, PRO

So I am working on a turret defence game. I have where the turret rotates to game.attribute coordinates which are the enemy's coordinates. The enemies have self health attributes and there are bullets to shoot them. I have an actor called ''turret range'' which is supposed to be the turret's range. But here are my problems:

  1. Once the enemy is out of range, and the turret stops firing, everything is good. But, once the enemy reaches another turet range of another tower, all turrets start firing. I can't edit a self.attribute from another actor, thus I am stuck.
  2. The turret aims at the enemy farthest away, even if he is out of range.
    Thanks for any help. :smile:
    Here is my file:
«1

Comments

  • Twayne2Twayne2 Posts: 136Member, PRO

    Please uninstall the file when you are done. It uses my artwork and my rules. Who knows, I might some day want to publish the game. :smile:

  • Twayne2Twayne2 Posts: 136Member, PRO

    bump

  • Twayne2Twayne2 Posts: 136Member, PRO
    edited February 6

    Anyone? Support just said, basically, just go buy a template. Please, I need help. :smile:

  • RowdyPantsRowdyPants Posts: 357Member, PRO

    @Twayne2 I tried to open your game but it came expanded in folder form and I can't get it back into .gsproj form

  • JapsterJapster Posts: 554Member, PRO

    @Twayne2 - Can't see this as I'm not at home, and my main mac is screwed atm (no loss, given I can't even publish anyway due to the touch issue, then the new issues introduced, sore point...) BUT...

    Can I assume that you're using magnitude(PX-X,PY-Y) (ish!) to cover the proximity logic for each turret? - if so, can you not just constrain the player's X/Y to game attributes, and have each turret compare it's x/y with the GAME attribute, via Magnitude? - no need to reference other turrets attribs, and tbh, there probably shouldn't be for your own sake - could get messy!

    Can't see why this wouldn't work, and it would also ensure that each turret's state is independent, based on the result of its own Magnitude result?

    Hope that helps!

    Japster

  • JapsterJapster Posts: 554Member, PRO
    edited February 7

    @Twayne2 said:
    Anyone? Support just said, basically, just go buy a template. Please, I need help. :smile:

    Nice.... I'm thinking that support are resigned to the fact that while there was a time when you'd fall over yourself to have to pick from the solutions given in here by fellow users, hey.... it's not the same around here, an' all that... :frowning:

  • Twayne2Twayne2 Posts: 136Member, PRO
    edited February 7

    I was able to open my file. Weird. Japster I am currently using an actor called turret range, as I don't know how to do that magnitude thing. I think the gamesalad guru guy has a video on that so I might have a look at that. I was just hoping that there was a solution using an actor called turret range. Also there is no ''player'', just turrets you can drop. Maybe you can provide some more detail as to your plan? I am open to suggestions lol. :smile:

  • Twayne2Twayne2 Posts: 136Member, PRO

    Thank you Japster! you gave me a great idea that works based on that sort-of. Now my only problem is that the turret doesn't shoot at enemies in range once the farthest one leaves its range. But that is relatively all right. Thanks everyone! :smile:

  • JapsterJapster Posts: 554Member, PRO
    edited February 8

    Glad it helped! - Magnitude is simple, but soooo useful!

    That last bit of info you gave me makes me think that you still have some shared data, if the furthest one causes the turret to stop - I'm assuming you have a stream of enemies moving along, a'la the usual tower defense genre?

    If you have many enemies, maybe have a table, and each enemy/target updates their row with their X,Y position when they move? (ie. DON'T constrain 100 / 200 variables, each with a unique name... :wink: )

    so

    Table Enemies:-

    Enemy X Y
    Row 1 100 106
    Row 2 100 145
    Row 3 80 100

    so, pseudocode / behaviour ran by EACH turret would be something like this:-

    Loop through table

    if Magnitude(Self.X - tablecellvalue(Enemies,1,1), Self.Y - tablecellvalue(Enemies,1,2)) < MySightRange
    (Fire away! - or add to list of possible matching targets)...

    etc...

    So your turret can simply 'loop through table', checking magnitude against the enemies' positions, targeting any / one that's in range, or building up a 'deadpool' to choose from ;) )

    This should work for EVERY turret, against every single enemy/actor independently, and only if THAT actor is in range at that point in time...

    Maybe the more savvy know an easier method of doing this, but I do love me my tables action.... :smiley:

    NOTE 1) PS - Using an additional column on this table, you could even spread / single target enemies, by having selected targets flagged in the table! - so say, Turret 1 targets Enemy 3, it sets column 3 for enemy/row 3 to TRUE, and all turrets (including this one) also check if this column is FALSE when targeting enemies (meaning they've not yet been targeted, so are fair game!), which would mean that if you wanted to shoot 1 shot at each of three enemies in range, all 3 turrets in range of the enemies would each fire 1 shot at a different enemy - simple to add the logic, just in case there was a reason you wanted to remove random shots at random targets - would probably make a harder variant, compared to targeting only the first matching enemies...

    (ie. the 1st method I mentioned has the advantage that CLOSER in-range enemies are targeted first, if you make the order the order they're set off in, and they're all the same speed - ie. 1st in-range enemy in the table would be picked, so would be attacked by everything in range first.)

    Again, I don't know much about your game, but if you want anything other than ONLY the first of any matching targets targeted until it moves out of range of a given turret, then the logic in NOTE 1 would help, or failing that, just randomly decide to attack (or not!) any matching targets you find as you're looping, using the first method, then simply stop checking for that turret's targets, once you've decided to fire at a matching in-range target.

    Hope that makes sense!

  • JapsterJapster Posts: 554Member, PRO

    PS - if you think it's helpful, you can always throw my suggestions a 'like' etc... :wink: It just helps me find motivation to post more of them! :smiley:

  • Twayne2Twayne2 Posts: 136Member, PRO
    edited February 8

    Sorry I am not good with tables, so I don't understand that post very much. But it is long and you put time and effort into it so I will give it a like. :smiley:

  • Twayne2Twayne2 Posts: 136Member, PRO

    Since there is no simple solution and I have an alright set-up this thread can be closed. :smile:

  • Twayne2Twayne2 Posts: 136Member, PRO
    edited February 8

    Thanks everyone! :)

  • JapsterJapster Posts: 554Member, PRO

    No worries, but honestly, tables are easy mate, and VERY powerful! - I'd write a quick project to show you what I mean, but my Mac is dead, and my Mini Mac needs memory (on order)....

    Thanks for the like, ha ha! :smiley:

  • ArmellineArmelline Posts: 4,585Member, PRO
    edited February 8

    Definitely no simple solutions. I've yet to see anyone make a real tower defense game with GameSalad. @Japster seems to have thought this through as far as anyone has! Getting the towers to consistently fire at the correct targets is not simple. You need to track the location of each soldier and have each turret calculate which soldier is furtherst along the path but still within range. Not simple to do! It's something I've always wanted to try but never been brave enough to make a serious attempt at!

  • JapsterJapster Posts: 554Member, PRO

    @Cutscene Entertainment said:

    Hey Twayne,
    Is this what you're looking for?


    If so, I've created a little template for you and attached it here. I would go into explanation on how it's done right here, but it's kind of in-depth so I added some notes and video for you in the download. Also, anyone else who feels they might need this can use it as well.
    Hopefully this meets your needs. I wish you luck.

    For how to add more turrets check out this video:

    @Cutscene Entertainment - Awesome mate! - will have to have a check out of your template myself once I'm up and running, as knowing you, I'm guessing you've done it an awesome way.... :smile:

  • RowdyPantsRowdyPants Posts: 357Member, PRO

    @Cutscene Entertainment said:

    Hey Twayne,
    Is this what you're looking for?


    If so, I've created a little template for you and attached it here. I would go into explanation on how it's done right here, but it's kind of in-depth so I added some notes and video for you in the download. Also, anyone else who feels they might need this can use it as well.
    Hopefully this meets your needs. I wish you luck.

    For how to add more turrets check out this video:

    @Cutscene Entertainment Above and beyond! Thanks for putting this demo and video together.

  • Cutscene EntertainmentCutscene Entertainment Posts: 110Member, PRO

    @RowdyPants said:
    Above and beyond! Thanks for putting this demo and video together.
    @Japster said:
    Awesome mate! - will have to have a check out of your template myself once I'm up and running, as knowing you, I'm guessing you've done it an awesome way.... :smile:


    Ah thanks guys so much. I'm trying to do my best to help out when I can. Hopefully this is what the original poster was trying to accomplish.

  • Twayne2Twayne2 Posts: 136Member, PRO
    edited February 10

    Sorry for the late response. I am confused how the turret knows to go to rotate to the next enemy in the line. I studied your code but couldn't really figure out how. I know there is the TT1X and TT1Y, etc., but I don't see how that works. Your video didn't explain it it just showed how to add more tower to your template. :smile:

  • Cutscene EntertainmentCutscene Entertainment Posts: 110Member, PRO

    @Twayne2 said:
    Sorry for the late response. I am confused how the turret knows to go to rotate to the next enemy in the line. I studied your code but couldn't really figure out how. I know there is the TT1X and TT1Y, etc., but I don't see how that works. Your video didn't explain it it just showed how to add more tower to your template. :smile:


    Well,
    Basically every time the controller for TT1X and TT1Y change, Gamesalad automatically records this action in a queue (or however you spell that) without you having to tell it to. When a controller is no longer valid, it goes to the next in the queue. This is automatic.

  • Twayne2Twayne2 Posts: 136Member, PRO
    edited February 12

    But how does the turret rotate to the next one in line if the enemy's coordinates are still the leading one? That's my problem. :(
    P.S. How does the system even stay working with all of the self values stacking up? Lol. :smile:

  • Cutscene EntertainmentCutscene Entertainment Posts: 110Member, PRO

    @Twayne2 said:
    But how does the turret rotate to the next one in line if the enemy's coordinates are still the leading one? That's my problem. :(
    P.S. How does the system even stay working with all of the self values stacking up? Lol. :smile:


    I know, it is in fact quite confusing in and of itself.

    I have the system set up to where once the enemy leaves the turret's FOV, it's no longer recognized as an "enemy". In the code, the enemy coordinates only apply while inside the FOV of a turret. So when it leaves, it's no longer an enemy, so the turret doesn't track it anymore. Like so:

    Basically, imagine that there's a T-shirt the enemies can wear called the "enemy shirt" which reads "I'm an enemy! Shoot me!"
    What basically happens is, the enemy is walking along, and when it comes into contact with the FOV of a turret, it puts on the shirt, alerting the turret. When it leaves the FOV, it takes the shirt back off and goes on its merry way, and the turret leaves it alone.
    Enemies of course stack up, so multiple enemies could be wearing the shirt at once in the same FOV. When one leaves, the turret automatically targets the next enemy wearing the shirt. Kinda like so:

    Automatically targeting the next actor to which certain attributes apply once another ceases to meet the same qualifications is an automatic function of the constrain attribute in GS. If you say, "lock onto enemy xy", itll find the first enemy xy and target it. When that target is no longer an enemy it'll target the next.

    How does this system stay working? Well, technically the values don't stack up. Every time an enemy leaves the FOV, it trashes its enemy values. Really there are only around four or five enemies in an FOV at a time.

    It's very hard to explain but hopefully that made SOME kind of sense. Explaining things in text form is difficult in general.

  • Twayne2Twayne2 Posts: 136Member, PRO

    I tried setting up where once the enemy collides with the turret's range, change a game attribute, such as your alert attribute, to 1. Else, change the game attribute to 0. If this game attribute is 1, constrain the enemy's position x and y to two other game attributes. Ugh, hold on.

    Here it is in rule form:
    enemy -
    rule: if enemy collides with actor ''turret range''
    do: change game attribute tracker to 1
    else: change tracker to 0.

    rule: if tracker is 1
    do: constrain position x and y
    else: should there be something here?

    This should handle when the enemy is in range or not. I actually have if x position is less than 125, etc., like you do, but I guess they are actually not needed.

    turret -
    rule: if tracker is 1
    do: shoot
    do: rotate to vector of angle blah blah XD

    Shoudn't this do it?

  • Cutscene EntertainmentCutscene Entertainment Posts: 110Member, PRO

    @Twayne2 said:
    I tried setting up where once the enemy collides with the turret's range, change a game attribute, such as your alert attribute, to 1. Else, change the game attribute to 0. If this game attribute is 1, constrain the enemy's position x and y to two other game attributes. Ugh, hold on.

    Here it is in rule form:
    enemy -
    rule: if enemy collides with actor ''turret range''
    do: change game attribute tracker to 1
    else: change tracker to 0.

    rule: if tracker is 1
    do: constrain position x and y
    else: should there be something here?

    This should handle when the enemy is in range or not. I actually have if x position is less than 125, etc., like you do, but I guess they are actually not needed.

    turret -
    rule: if tracker is 1
    do: shoot
    do: rotate to vector of angle blah blah XD

    Shoudn't this do it?


    That should work marvelously for the first turret.

    According to your description:

    @Twayne2 said:
    enemy -
    rule: if enemy collides with actor ''turret range''
    do: change game attribute tracker to 1
    else: change tracker to 0.

    So basically, whenever an enemy comes into contact with the FOV of a turret, the game announces alert status (game.tracker). The problem with this is that it's not specifying alert status for a specific turret, it's just saying to the world "Alert! Enemy! Alert!".
    That's why all the turrets wake up at once as opposed to each turret selecting their respective enemies.
    If an enemy is in the range of turret three, that shouldn't alert turret 1, 2, 4, 5, etc.

    What you have to do is set up a unique alert for every turret. Hence my attributes (game.alert1, game.alert2, game.alert3, etc.)

    ALSO:

    @Twayne2 said:
    rule: if tracker is 1
    do: constrain position x and y

    You're saying here that when the alert status is active, you want the enemy to be recognized as an enemy, in essence putting on the enemy t-shirt.
    The only problem with that is, much like the problem with your first rule, it's not specifying which turret it's the enemy of. Instead it's just saying "yo I'm an enemy".
    If an enemy is in the range of turret two, it's not an enemy of turret 1, 3, 4, 5, etc.

    So again what you have to do is set up unique enemy X Y coordinates for every turret. Hence my attributes (game.TT1X, game.TT1Y, game.TT2X, game.TT2Y, game.TT3X, game.TT3Y, etc.) Btw TT stands for "Turret Target".

    It's a pain but it's gotta be done because GS doesn't support relative recognition.
    (ex. nearest actor, left side, right side, etc.)

  • Twayne2Twayne2 Posts: 136Member, PRO

    The problem is I am trying to make a tower defence game but with however many towers that you want. (Later there will be some kind of gold system I believe.) I have been trying to come up with some system to accomplish this lol. :smile:

  • Cutscene EntertainmentCutscene Entertainment Posts: 110Member, PRO
    edited February 14

    @Twayne2 said:
    I need to be able to place however many turrets I want. How do I accomplish this?


    Alas, If you speak of a turret code generator for an infinite amount of turrets, I'm afraid that is beyond my power. The answer you seek now lies only with the GS masters themselves.

    Tread lightly, for the masters have little patience and their dedication to your problem will be delicate.
    I bid you farewell and I wish you luck.

  • Twayne2Twayne2 Posts: 136Member, PRO

    I am close I think. I have where I can put turrets, they rotate to farthest enemy in range, sort-of. Just gotta fix how they all rotate to other ranges, and maybe fix something else. Thanks for all of your help, it has been appreciated. :) Good luck!

  • HopscotchHopscotch Posts: 2,767Member, PRO
    edited February 14

    @Twayne2

    added to the good advice already given, here a couple of suggestions from me:

    Performance:

    As the number of enemies and turrets grow, the amount of checking needed will grow drastically.

    Some pointers to help with performance:

    Have a table, every enemy is represented by a row, every turret by column. Referenced by a self.ID. Reuse rows/columns as enemies die and new ones get added.

    Update the enemy positions every draw cycle.

    Let the enemies (not the turrets) check their distance to every tower and write these values to the table. This can be done for all towers in one "Change Table Value" behavior with multiple Column Value updates.

    Furthermore, only perform the distance check in one enemy per draw cycle, not all of them. this means that even for 30 enemies on screen, the range targeting is accurate to with in a second, their position info however is always precise.

    This allows for minimal code per cycle, yet quite up to date values.

    With the distance values in the table, each turret can now use a loop (with loops per cycle set to 20 or more) and the very fast TableSearch function to find the closes enemy. This way, even with a large number of enemies, on average, only a relatively small amount of rows will actually need to be processed as you block step through the table.

    Even better, work with a grid based system. Thus reduce your distance values based on the grid value, i.e. instead of an enemy being 236 pixels away, declare it as being 3 grid tiles away. Now, lets say your turret range is 4 grid tiles, you will only need to do a table search for any enemies 1 grid tile away. If any are found you are done, if not repeat for 2 grid tiles away, etc. This way you only loop a maximum times relative to your turret grid tile range, or less.

    Enemy hit detection:

    Be mindfull of how you do the hit detection on the enemies. As soon as enemies bunch up or are shot at at a shallow angle, you will run into a situation where either, the wrong, or multiple enemies get hit by a projectile. So you will have to come up with a way to handle this. Preferably as part of your early design. How you will implement this will depend on the type of special artillery you will include later (area of effect, slow effects, dots, etc.). This will probably be your hardest problem to solve.

    Closest enemies logic:

    Something else to consider early on is exactly how you want your targeting to work, or do you anticipate implementing multiple options.

    The simplest is of course "always fire at the closest enemy".

    Another method is "focused fire" on one enemy until that enemy is out of range. This is the most common and most logical in tower defense games.

    Yet another may be, target the weakest enemy.

    etc.


    As you can see, you have taken on the challenge of doing one of the hardest genres, from an optimization point of view.

    Since all the above implementations are closely related in how they dictate the coding approach, it is very difficult for anyone to give specific and useful piecemeal advice to this on the forums. :)

  • JapsterJapster Posts: 554Member, PRO

    ...and this is why I LOVE tables... :wink: ^^^

«1
Sign In or Register to comment.