Updating Attributes

specialist_3specialist_3 Member Posts: 121
edited November -1 in Working with GS (Mac)
Hi All,

I have ran into a problem with my shooter game. I have a gun which shoots different types of bullets. Different enemies need different bullets to be killed. Suppose there is a werewolf and he can only be killed by a silver bullet. Gold bullet won't work on him. My gun fires when I press space. I can choose different bullets by pressing 1,2,3 etc. When I fire a silver bullet and it collides with the enemy actor, I do an attribute comparison (RULE check) and if 1 = 1, the enemy and bullet are destroyed. If it is not equal the bullet simply passes through. I have a global attribute called Bullet.Type (1,2,3 etc) This is where the challenge starts....

Suppose,
Bullet.Type
Bronze bullet = 1
Silver bullet = 2
Gold bullet = 3

When I fire a gold bullet and then fire a silver bullet (1 trailing the other), when the gold bullet hits the werewolf, the actors die. This is because when the silver bullet (second fire) is shot, it changes the attribute of the gold bullet (at present 3) to silver = 2. How do I ensure that each bullet has its own bullet.type value such that fired bullets retain their bullet.type value.

Vice versa, when a silver bullet is fired and then followed by a gold bullet, the silver bullet does not kill the werewolf because now this time round, the bullet.type global attribute has changed to 3.

I know this has probably got to do with playing around with Constrain Attributes vs Change Attributes behavior but I am not able to get them to work properly. Or is there some other efficient way to sort this out? Can anyone guide me through this please?

Cheers!!

Comments

  • firemaplegamesfiremaplegames Member Posts: 3,211
    Since you can fire multiple bullets at once, you will need to change the logic around a bit...

    The first part you have is correct. Use a global integer attribute to spawn the correct bullet type.

    For the second part, I would do something like this:

    Create three separate bullet Actors (or however many you have)

    On the Home Screen, make a new Tag called "Bullet", and drag these bullet actors into that tag.

    In the Werewolf Actor, have the Rules set up something like this:

    Rule
    When all conditions are valid:
    Actor receives event overlaps or collides with Actor with tag Bullet
    -----Rule
    -----When all conditions are valid:
    -----Actor receives event overlaps or collides with Actor of type Silver_Bullet
    ----------Play Sound "werewolf_death.ogg"
    ----------Destroy

    Hope this helps!
    Joe
  • specialist_3specialist_3 Member Posts: 121
    Hi Joe,

    Thanks for your reply. The tag logic you have advised would definitely work if I were comparing different bullet actors (or tags) with the various enemies I have. But I actually have 9 different bullets. To reduce dependency on too many actors (to increase code efficiency - I hope), I am just having 1 bullet actor and not 9. This bullet actor's image and the global bullet.type attribute changes when I change the bullet.

    So this is where I am stuck. Can I just have 1 bullet actor (which changes images and corresponding bullet.type value) and still simulate different bullets? Please advise.
  • firemaplegamesfiremaplegames Member Posts: 3,211
    Ok, in that case, create an integer Attribute in the Bullet actor, called something like "myType".

    Put a Change Attribute loose at the top of the behaviors for the bullet, like this:

    Change Attribute
    self.myType = game.bulletType

    That SHOULD set the "myType" of each bullet when they are spawned.
  • specialist_3specialist_3 Member Posts: 121
    Hi,

    I understand that Change Attribute happens only once unlike Constrain Attribute which keeps constantly updating.

    I did that. Still what happens is that because game.bulletType is common to all the bullets being spawned, the moment the first bullet is followed by another and then another, it gets updated with the latest bullet.type attribute.

    But let me try it again and see if it works. I might have made some logic mistake especially with many attributes and variables running around.
  • specialist_3specialist_3 Member Posts: 121
    Hi Joe,

    Nope it doesn't work. It is just as I explained. Unlike real coding where we can store the individual attributes in either class instances, arrays or pointers and allow individual actors to interact directly with one another, GS only allows interaction through global attributes. Therefore, when we modify the global attribute and then link it with actors, all of them get affected equally.

    I really hope I am wrong in my understanding here because I really don't want to resolve this with multiple actors of the same type. I have a dozen different bullets with a dozen different villains not to mention different guns. Imagine the sheer number of actors that need to interact here.
  • firemaplegamesfiremaplegames Member Posts: 3,211
    One bullet should work fine.

    There are three types of Attributes in GameSalad:

    Global Attributes
    Actor attributes
    Scene Attributes

    GameSalad uses the Prototype/Instance model, Attributes you place in the Prototype are in all of the Instances of that Prototype.

    Instances CAN both listen to, and set, any attribute of ANY other Instance in the Scene. An Instance can also listen to and set (most of) the Scene Attributes, such as the Scene's Camera data. Prototypes CANNOT. You will need to click the padlock of an Instance to access the Scene Attributes.

    Change Attribute only fires once.
    Constrain Attribute constantly fires.

    So you should have a global Attribute (integer) called bulletType. When you press the spacebar, and spawn a bullet, the bullet prototype should have an integer attribute as well, called something like "myType".

    At the time of firing, set the myType of the bullet to the global bulletType. Use a change attribute behavior. myType will only be set once - it will not keep updating as the global bulletType changes. If you wanted to always have it updating, you would use Constrain Attribute.

    So in the bullet Prototype in the Library, create an integer Attribute called myType. And put a Change Attribute at the top of the list with Change Attribute: self.myType To game.bulletType.

    Again, that SHOULD work. Each bullet instance should have their own "myType" when they get fired. It shouldn't change as the global bulletType changes.

    The Prototype/Instance model is sort of a dumbed-down version of Class/Instance model. It pretty much works the same way.

    You still don't have access in GameSalad to Arrays (hopefully they will implement them soon!) or pointers, but this system can do pretty much everything else.

    If you are still having trouble, please let us know!
    Joe
  • specialist_3specialist_3 Member Posts: 121
    Hi Joe,

    I tried what you said. Now this is the outcome...

    I have 3 actors in total for now.
    Gun, Bullet, and Enemy

    In the Gun Actor,

    I have a behavior which checks for Keyboard input,
    if 1 is pressed, then gun color changes to bronze,
    if 2, silver,
    if 3, gold
    The gun has a Self.Mycolor attribute which is set to either 1,2, or 3

    When I press space (shoot)
    I assign the Turret's color (self.mycolor) to global bullet.color attribute using change attribute.
    I then spawn the bullet (under Turret Actor)

    In the Bullet Actor,

    Under a Rule, at self.time = 0 (meaning when bullet's time is at 0), I initialize its self.bulletcolor to global bullet.color using change attribute.

    Using a different rule, I test the self attribute against 1,2, or 3 to change the color/image of the bullet accordingly. Under this rule, I also change another attribute called game.collision.bullet to self.bulletcolor. This collision.bullet global variable is simply another variable to pass and compare with the enemy actor when they collide.

    The Enemy receives the game.collision.bullet variable and assigns to its own bullet.color attribute. This is then checked to see if 1 = 1 or 2 = 2 or 3 = 3. If so, the enemy is killed.

    However, the problem I have mentioned before seems to persist. What I have done is to create different display labels to test the values being passed around. I find that while the global variables seem to update correctly most of the time, the value (number) on the bullets are not. The first time I fire without changing bullet, the numbers show correctly, meaning number 1 is displayed on bronze bullet as it travels. But when I change gun to different color, say silver (which is 2), 5 bullets display 2 on them but the 6th bullet displays a 1 or vice versa. Basically, the bullet values are not getting updated correctly.

    Example, first time game loads and I fire bronze...
    it goes 1 1 1 1 1 1 1 1 1 etc
    after I change gun, it goes 1 1 1 2 2 1 1 2 1 1 1 1 2 2 2 etc or 2 2 1 1 1 etc

    Also if I fire a bronze bullet on a silver target, the target does not die. But if I fire a bronze bullet and immediately change gun and fire a silver bullet, when the bronze bullet touches the target, it dies.

    Are you able to follow what I am saying here?

    I really appreciate your time and help. Thanks.
  • firemaplegamesfiremaplegames Member Posts: 3,211
    I understand what you're going for...

    Under this rule, I also change another attribute called game.collision.bullet to self.bulletcolor. This collision.bullet global variable is simply another variable to pass and compare with the enemy actor when they collide.

    I think that is where you are getting tripped up...
    That global attribute is going to keep changing every time you fire a new bullet.

    Like you said though, it isn't easy for Instances to "talk" to one another. You CAN do it, but it is more for when the instances are manually placed in the Scene, not when they are spawned.

    Unfortunately, the way GameSalad works, you are probably going to need a different Actor for each bullet, and a different Actor for each Enemy type.

    It certainly is tedious, but it will work.

    In my games, I am loading and saving around 200 Attributes, and some of my Rule sets are 300 Rules long! Without for loops and concatenation, things get ridiculous real fast!

    This tediousness is countered by the absolute speed of getting your app running on a device. Knocking out an iPhone game in days or weeks is pretty amazing.

    But yes, I feel your pain!

    Hopefully as they keep working on the software, it will keep getting better!
  • specialist_3specialist_3 Member Posts: 121
    Hi Joe,

    Having multiple actors for bullets and enemies would certainly make things straightforward though tedious. Infact, I sort of have a prototype version which does that. My concern is the amount of resource that is going to be used. What is the maximum number of actors I can have at a particular frame or scene without slowing down the iphone or ipad? I have seen a couple of threads where members were discussing about avoiding frequent spawning and destroying as they would hog the computing resource. But so long as each actor spawned is destroyed without leaving any leak, it should not be a problem right?

    As you may have guessed, this is a tower defense game I am trying to build. So imagine, different bullets, different enemies, number of each bullet fired and number of each enemy spawned, plus miscellaneous actors.

    Thanks.
  • firemaplegamesfiremaplegames Member Posts: 3,211
    "straightforward though tedious" is how one could describe working with GameSalad! Also a lot of fun, but things can get rough sometimes...

    A Tower Defense game is a mighty challenge in GameSalad.
    JGary made one a few months ago.

    Not easy! All without Arrays, for loops, or proper functions.

    The other thing to watch out for is the use of Constrain Attributes. They are real resource hogs,
    especially on older devices. You should test your game with the GS Viewer as soon as possible.
    That will show you the RAM usage as well as the FPS on the device.

    In a typical tower defense game, the creeps would have health bars above them. In GS, you would create that with a Constrain Attribute ( to keep the health bar Constrained above the creep) But more than a few Constrains will kill the frame rate.

    You'll also need Constrains to constantly get the distance between the towers and the creeps.

    You will definitely need to be creative to pull it off!
  • specialist_3specialist_3 Member Posts: 121
    Haha, actually I am already feeling the challenge. So far the only constrain I have used is to check for checking the angle of the bullets flying. I constrain it with the angle of rotation of the gun.

    I am now facing a new challenge...pathfinding. The creeps have to find their way to the end point through the maze. The maze I have now is basically a background image. Imagine a maze which spirals inwards (rectangularly..not circle). For now, I am hardcoding the various points (edges of the maze) the creeps move towards each nav point. Upon reaching it, they move towards the next point and so on till they reach the destination. So its something like, left to right, then top to bottom, then right to left and so on. So each nav point is hardcoded in the "Move To" behavior. Rules will check if the creep has reached it and if so where do they move to next.

    Do you think there is a more efficient way of doing this?
  • firemaplegamesfiremaplegames Member Posts: 3,211
    It's either that or placing invisible triggers over the background image and changing their direction when the creeps collide with them.

    6 of one, 1/2 dozen of the other...
  • specialist_3specialist_3 Member Posts: 121
    I didn't quite get what you meant by 6 of one, 1/2 dozen of the other...
  • firemaplegamesfiremaplegames Member Posts: 3,211
    Sorry. It means "same thing either way".
  • specialist_3specialist_3 Member Posts: 121
    Hey Joe,

    I got my game to work. I only have one set of enemies and one set of bullet but seems to be working fine. I am using the hardcoded navigation points for pathfinding for now.

    One hiccup though...I am trying to set a rule that when there are no creeps left, player life is more than 0, I display "you finished level 1". Number of player lives and no creeps left is initialized to 10 and 50 respectively.

    Each time the creep reaches the destination, player life is reduced by 1. Creeps.Left is also reduced by 1.

    Each time, a creep is killed, creeps.left is reduced again by 1.

    But I notice that every time the number of creeps on screen is reduced to last 4, the game displays "you cleared level 1", which is weird. Is there a logic error in my game?
  • firemaplegamesfiremaplegames Member Posts: 3,211
    It's hard to tell without seeing the code, but it's definitely a logic bug somewhere...

    Just to confirm, in that Rule that checks all the conditions, that it is indeed set to "All" and not "Any"?

    You seem like a competent programmer, so I am sure something is just being overlooked...
  • specialist_3specialist_3 Member Posts: 121
    Hi Joe,

    Its set to "All" only. I have been playing around with the logic a bit, but it keeps displaying level is finished when there are still 4 creeps remaining. Need to create display labels now to debug this. I will update you soon.

    Well not really competent. Did some C programming during college but not since. I am actually enjoying GS. I got my basic tower defense already up in 2 days plus 1 with all the artwork. It would have taken a week if I were manually coding everything.
  • specialist_3specialist_3 Member Posts: 121
    I found the problem. God I love Display Text. It has actually got to do with my Timer behavior. Here's the problem...

    I am basically trying to spawn my creeps (global attribute MAX: 50) at certain intervals. In this case,

    After 5 seconds into Game.Time (Game.Time >= 5),

    Every 10 seconds,
    For 2 seconds,
    Every 0.2 seconds, spawn a creep

    So what happens is for every creep stream, 9 creeps are spawned. Because of this logic, the total creeps spawned overflows to 54 instead of the maximum 50 I have set. Despite the Rule which checks numOfCreeps <= 50, then timer spawn, why does it overflow to 54?

    I also noted that if the interval per creep is 0.2 seconds then in 2 seconds should there not be 10 creeps instead of 9?
  • specialist_3specialist_3 Member Posts: 121
    Ok I sorted out the first issue. It had to do with my Loop rule. Initially the timers were inside the Loop checking for <=50. I moved it inside the Timers instead and changed <= to simply <.

    However, I still don't get the second part..why 9 creeps and not 10 are spawned.
  • firemaplegamesfiremaplegames Member Posts: 3,211
    0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0

    You're right, that should be 10, maybe that final one is getting chopped off?
    The Timer isn't perfectly accurate, there might be some slippage, so maybe by the time it gets to the last one, the 2 seconds are already up...

    A better way, instead of relying on a Timer, would be to use an integer as a "creep count" and increase it every time you spawn. That should lock it down a little better.

    So:

    In the spawning Actor, create a new integer attribute called 'creepCount'

    And set the Rules like this:

    Timer Every 10 seconds
    -----Change Attribute: self.creepCount To: 0
    -----Rule
    -----When all conditions are valid:
    -----self.creepCount < 10
    ----------Timer Every 0.2 seconds
    ---------------spawn a creep
    ---------------Change Attribute: self.creepCount To: self.creepCount + 1

    I believe that should do it.

    Again, if you plan on releasing this to the App Store, you should really test it on a device asap. On older devices, Timers and spawning can cause hiccups. You barely have any RAM to work with. And every time you spawn something it adds to the RAM. (which is why some people, instead of spawning/destroying, just move the Actors offscreen and reuse them....)

    Using the Preview built into GameSalad is a little deceptive as you have all the RAM of the computer behind it. Plus the processor is much better. It's great for testing logic, but not performance.

    What you're describing should work fine on an iPhone4, Ipad, and even 3GS, but older iPhones like the 3G and older iPod Touches will struggle...

    Just a word of caution...
  • specialist_3specialist_3 Member Posts: 121
    I got you. I have to cater to older device to reach out to a wider audience. I have an itouch which I bought last year, so that should be considered an older device making it ideal for testing. Let me work on the reusing actors bit.
  • specialist_3specialist_3 Member Posts: 121
    Hey Joe,

    I got the GS Viewer after much effort. I tested my basic game on my iTouch. You are right...spawning does slow the frame rate quite a bit. It starts off @ 60fps and each time a creep is spawned, the fps drops and by the time all the creeps are in, its fluctuating at around 25-30 and that is without any of my bullets flying around which if spawned will slow down drastically.

    Only step I have taken thus far is to reduce the image sizes which has helped a little and also reduce the total number of creeps spawned to 36 instead of 50. I did go through a couple of other forums which also mention the same thing about moving actors offscreen and onscreen. But I am unable to form the logic in my head. I have built my game based on spawn/destroy logic and am stuck on how to modify it. Do I have to pre-spawn or drag in 36 creeps and put them off screen and keep rotating them?
  • firemaplegamesfiremaplegames Member Posts: 3,211
    Correct.

    Either pre-spawn then at the beginning of the level, or place them there manually.
    When they die, or reach the target, move them back to the beginning.

    Straightforward and tedious!
  • specialist_3specialist_3 Member Posts: 121
    Haha ok. Hate to imagine how games in the 80s and 90s were made and they didn't have GS back then. Alrite, I will try both methods and see which is more efficient.
Sign In or Register to comment.