Deleting sprites (How would You do it #5?)

43 posts

Flag Post

Let’s say we have a BattleField and Soldier movie clips (or derived from movie clip or other display object). BattleField contains a bunch of soldiers (as children). Rough truth is that soldiers sometimes die and after dying they should get removed from the BattleField.

So the (double) question is: Who should
1. detect the death of the soldier (run collision detection with bullets, check if he is out of screen, check if he starved to death or blown himself, etc.);
2. call the removeChild() function/method.

So how would you do it? Do some magic with parent reference? Event listener? Do everything in battleField? Anything else? Or maybe organize everything in some other way?

 
Flag Post

Your Game logic class should detect the death of a soldier. Kinda. Your game logic class should iterate over the soliders, which manage themselves. However you handle your collisions, health, etc will determine which class effectively detects the death.

Your soldier should remove itself from the screen, along with any cleanup.

 
Flag Post

Whatever is in charge of the game logic (the controller, say) should remove the soldier… when the soldier says it’s time.

So if the controller determines that a bullet hits the soldier, it removes the bullet and calls the beenhit() function of the soldier, so the soldier knows he’s been hit. If the soldier determines that being hit by a bullet is reason enough to die, he interrupts whatever he was doing and starts his death animation.

Time passes…

When the soldier has finished his death animation, he dispatches an event to say he’s ready to leave. The controller catches the event, and removes the soldier. the controller is also in charge of determining how the sudden absence of the now dead soldier will affect the world. Sadly, someone’s score will likely increase as a consequence of this tragic event.

 
Flag Post

Sounds like you read through this thread and want to know who was “right.” (Answer: I was, obviously. :P)

 
Flag Post

I have entity classes manage the process of taking damage and realising that they’re dead. That can also involve removing their view. But the game engine then iterates over the entities and removes any that are marked as for removal. It just seems cleaner to not mix entities managing themselves and managing the list of entities.

 
Flag Post

From a performance perspective, managing all of it in one place would be better.

 
Flag Post
Originally posted by BigJM:

From a performance perspective, managing all of it in one place would be better.

I did that once. 2,184 lines of code in 1 file. Incredibly hard to find anything. I will never go back. RIP Tribulation.

 
Flag Post

A better IDE would help for that. In most cases, the performance benefits would be negligible.

From an OOP perspective, objects are supposed to be as independent as possible (ie encapsulated and decoupled). Therefore, an individual soldier shouldn’t know anything about the battlefield he is in. Take that as you want.

 
Flag Post

Every enemy class I have iterates though all of the player bullets on the field and if it collides with one it calls the Die() function. Within that function it calls the Parent.RemoveEnemy() function. So while the enemy itself detects and deals with collision and tells itself to die when it hits 0 health, the EnemyManager class is the one that actually removes the enemy from the list of enemies (since EnemyList is private).

Note that when I say “parent” I am referring to the class that handles the class, not the class that this class inherits from. Enemy parent is EnemyManager. Enemy parent class is GameObject.

So…

1) Each enemy class does it
2) Parent function through parent class.

 
Flag Post

1) Soldier (in my case Monster) tracks itself and has an interface about saying dead or not, is it time to clean it up or not.
2) Battlefield keeps track of when to add or remove monsters, and other objects that could be on screen.

 
Flag Post
Originally posted by Bobikas:

Let’s say we have a BattleField and Soldier movie clips (or derived from movie clip or other display object). BattleField contains a bunch of soldiers (as children). Rough truth is that soldiers sometimes die and after dying they should get removed from the BattleField.

So the (double) question is: Who should
1. detect the death of the soldier (run collision detection with bullets, check if he is out of screen, check if he starved to death or blown himself, etc.);
2. call the removeChild() function/method.

So how would you do it? Do some magic with parent reference? Event listener? Do everything in battleField? Anything else? Or maybe organize everything in some other way?

Tough question as there exist a ton of different philosophies on this topic. If you want a maintainable and flexible framework for your game which also can be used for future and even drastically different games, then you should look into agile programming.

Many have mentioned that you should have one central class named GameLogic and that’s especially true for agile programming. The job of GameLogic class is to handle all of the calculations in the game, so if you want something changed/added you go to that class. The advantage is that as soon as you have duplicated code you simply create a new function for this code and call it where there codes is needed, so you in the future only have to edit one place in the code when making alterations/extensions/bug-fixes (the code also becomes easier to read as the function name explains what that code bit does).
In sharp contrast to UnknownGuardian’s suggestion, the soldier/unit classes do not contain logic in agile programming (they do not perform the detach), their only job is to function as data containers with get and set functions for alteration of said data. Let’s say you have 3 or more different unit types which all have to detach the same way, that’s the code duplicated 3 times, but what if you during optimization of the code decide not to detach the units but instead just make them invisible for fast “re-attachment” instead of creating new units? In agile programming you would only have to make the change one place in the code (in the GameLogic class).
True, you could just make all the units extend the same super class, but what if some units only are used once and should be detached instead of made invisible for later use? The units would have to extend the detach super class but at the same time also extend another super class which hold code they still have in common with units which only are made invisible, it would be a proper mess and is the only reason why AS3, Java and C# do not allow for extension of more than one class.

Back to agile programming and the GameLogic class, when you change the detach code for units to instead make them invisible, you do not delete this code, but instead use the strategy pattern; you create an interface called DetachStrategy and then move the old detach code to a class which implements this interface and also write the new make invisible code in a class which implements the interface. This way you can in future games switch between the two methods based on your needs.

For the problem with some units using the old detach strategy one just use the state pattern. The state pattern is simply a class which extends the same strategy interface, looks on the unit’s type and then decides which of the two detach strategies should be used.

These places where the strategy pattern is used are called variability points, you should not waste time on planning them before coding but just add them as needed, it will save you many design headaches and your framework will gradually become more flexible while remaining highly maintainable.

Following the golden rule of low coupling and high cohesion, it’s important that the GameLogic class only handles game logic, things like graphics-rendering should be handled by a different class, communication through a clearly defined facade pattern (an interface with functions which only exchange immutable data), preventing a criss cross of “connections”/references and confusion about where values are being manipulated (will save hours on debugging, especially when the framework grow large). The same with the game menu and game controls, the GameLogic class should remain independent so you easily can switch control type(in game even) and menu system.

Hmm post got longer than planned and it has gotten rather late, so I won’t read it through before submitting, feel free to ask if there’s something which doesn’t make sense. :)

 
Flag Post

I’ve been doing it the Octabech way, I think, ever since a conversation with…..someone or other….on this forum. Main.as handles user input, logic.as calculates everything, rend.as draws everything…..anything else is just an object holding data. I shall start telling people I’m an ‘agile programmer’. a follower of the Snowbird Agile Manifesto.

 
Flag Post

Here’s what I do. Not sure if it’s best practice, but:

1) I give each soldier a boolean flag called “terminate” that is set to true when they move off screen permanently or are killed irrevocably. With a few special exceptions, the soldier/other ingame displayobject detects what constitutes death (0 hp, moving offscreen, etc) and flags itself accordingly.

2) The main game framehandler cycles through each soldier on every frame for movement/shooting/behavior, collision detection, etc. If “terminate” is found to be true, then removeChild is called, that soldier is purged from the array, and he ceases to be.

Example: Let’s say we have an enemy soldier and player bullet (or any two objects that could be considered hostile to one another). The main framehandler checks for collisions and, if true, has the soldier apply damage to the bullet and the bullet applies damage to the soldier. If either reach 0 hp, their terminate flag gets set to true. The main framehandler then checks this flag and, if true, throws them into the meatgrinder.

 
Flag Post
Originally posted by EndlessSporadic:

Every enemy class I have iterates though all of the player bullets on the field and if it collides with one it calls the Die() function. Within that function it calls the Parent.RemoveEnemy() function.

This method presumes enemies are objects on the display list. If you’re blitting instead, which you likely should be if you care about performance, then sadly you have to go through the Event system or inform the soldiers of the existence of the battlefield in some way. The second option is inelegant and breaks encapsulation.

Originally posted by EndlessSporadic:

Note that when I say “parent” I am referring to the class that handles the class, not the class that this class inherits from. Enemy parent is EnemyManager. Enemy parent class is GameObject.

The Class a given Class inherits from is called its superclass in AS3. ‘parent’ refers to the instance having ‘this’ instance as a child. Only DisplayObjects (well, instances of subclasses of DisplayObject) can be children, therefore only they can have a parent.

 
Flag Post
Originally posted by Ace_Blue:

[…] or inform the soldiers of the existence of the battlefield in some way. The second option is inelegant and breaks encapsulation.

It seems reasonable to me. How else are soldiers supposed to find enemies to shoot, or find their way around obstacles?

 
Flag Post

My game would have a soldier class, which extends my actor class. New soldiers get added to the actors array, and every frame I loop through all the actors and call the eachframe function. Each soldier class declares its own movieclip, and adds itself to the screen when necessary (parent is a parameter in the constructor).

1. Each soldier would detect their own expiry. They would have a public gotHit function, but working out how many hit points the soldier has left and if they should still be alive happens in the eachframe function.
2. Removing the movieclip is done by the ugly but functional clip.parent.removeChild(clip). Actors can also set a cleanup flag (public boolean property), which will cause them to be removed from the actors array when I call the checkDeceasedActors function in my main code.

 
Flag Post
Originally posted by player_03:

It seems reasonable to me. How else are soldiers supposed to find enemies to shoot, or find their way around obstacles?

In either instance, they don’t. As far as an enemy is concerned, it exists in a vacuum. There is no map, no other enemy instance, no bullet. There is just ‘this’, in an otherwise empty Universe. And, once in a while, a function that gets called to play this animation or that, or manipulate internal variables. And another once in a while, this dispatches an event into the ether because it seemed important to do it somehow, even though this doesn’t know why. The controller knows about all the enemies, and the battlefield. It can query the battlefield with such questions as “Can this enemy here see the player?” It can also query the AI module with questions such as “Assuming this enemy could see the player this far away, would the enemy shoot?”

Reciprocally, it would ask the AI “What should this enemy do?” and call the battleground’s pathfinder to ask “this enemy wants to go there, what should its next move be?” Which is a lie, because the enemy doesn’t really want to go anywhere, it’s the AI that wants to move it. But the pathfinder doesn’t really need to know that. It doesn’t know the AI even exists anyway.

And then to the soldier, all the controller ever says is: “Dude, you’re moving to the right”, or “Dude you’re shooting”, or “Dude, you’re hit.” And the soldier does what the soldier should: what he’s told, just going through the motion, without any concern for the big picture.

Edit: \/ I know you’re being facetious, but encapsulation isn’t an illusion, because the controller is not omniscient. Neither is it omnipotent. I does not, for instance, know how many HP a given soldier has. That’s a private (forgive the pun!) variable which the soldier isn’t sharing with the outside world. And the controller cannot tell an enemy to die, unless that has been explicitly made part of its prerogatives. No, the controller is just as much of a cog in the machine as any other Class. The omniscient, omnipotent puppeteer pulling all those strings is the programmer. Not that I have a God complex or anything…

 
Flag Post

That was very existentialist, Ace, very existentialist. I like how you included a bit of epistemology in your discussion. What I find insightful is that, to you, the existence of the Controller was never in doubt. If I were to follow your arguments to their conclusion, it seems that everything is ultimately part of the Controller. Encapsulation is an illusion.

Ok, enough derailing BS from me. We now bring you back to the original topic. :P

 
Flag Post
Originally posted by Elyzius:

That was very existentialist, Ace, very existentialist. I like how you included a bit of epistemology in your discussion. What I find insightful is that, to you, the existence of the Controller was never in doubt. If I were to follow your arguments to their conclusion, it seems that everything is ultimately part of the Controller. Encapsulation is an illusion.

Ok, enough derailing BS from me. We now bring you back to the original topic. :P

Not derailing BS at all, your question is valid. :) There are different perspectives of how Objects should be seen, the most common but slowly dying view is the model centric where objects should copy the real world, for instance a car object encapsulates all the info about a car or sub-objects like Engine, Door, Tire and so forth.
Ace however is using the responsibility centric perspective, which means he doesn’t group after what real world object the code belongs to but what its job is, in the case with the GameLogic it encapsulates the job of handling movement and collision of all types of units. The reason for using the responsibility centric perspective is that a car can have more purposes than simple transport, for example the car’s roof shares the same responsibility as an umbrella, to keep people dry, but where should that code be written, in the car or in the umbrella object? It would generate a mess if the model centric view was to be followed, so instead the code for the “keep dry” responsibility is encapsulated into its own object which then call the car/umbrella objects which only contain their own variables.

 
Flag Post
Originally posted by Ace_Blue:

As far as an enemy is concerned, it exists in a vacuum. There is no map, no other enemy instance, no bullet. There is just ‘this’, in an otherwise empty Universe.

Ok, let’s break this down.

A soldier should store the following information, because storing it anywhere else would violate encapsulation:

• Position
• Health
• Current state (shooting, reloading, patrolling, following a target, etc.)
• Inventory (weapon type, amount of ammo, health packs left, etc.)

Maybe some of that would be encapsulated within (say) a Gun object, but in that case the soldier would store a reference to said Gun, and the soldier could call functions on the gun as necessary.

But other than that, it seems pretty reasonable, don’t you think?


So what is a “controller” doing telling the soldier what animation to play? The soldier knows what state it’s in. The animation to play depends on what state it’s in. Why would you force a middleman into the middle of what ought to be a simple, encapsulated function?

And, for that matter, what is this “controller” doing determining the soldier’s AI? Is there an imperial mandate that all soldiers use the same AI? What if you wanted to make a sniper with its own separate AI?

You’ve gone and hard-coded assumptions like “this soldier only even considers attacking the player” or “this soldier can only detect the player via line-of-sight” into something out of that soldier’s control. What about player-friendly NPCs? What about soldiers who can hear the player’s gun go off, or soldiers who can remember that the player exists even after the player ducks behind a stack of crates?

The soldiers ought to store a reference to their own AI module. That way, nothing outside the soldier object dictates what AI the soldier uses, and you can even switch around AIs without re-writing outside code. (This is a principle called “encapsulation,” in case you want to look it up.)

But, you’re going to protest, the AI isn’t going to work encapsulated within the soldier like that! The AI can’t make good decisions, or for that matter any decisions, without some input about the outside world!

And you’re right about that. You just aren’t right that soldiers shouldn’t have information about the outside world. Do real-world armies to employ blind soldiers only? No? So why would you simulate them like that?

Sure, it’s a bad idea to reveal the inner workings of the battlefield class. But there’s no reason not to provide (at the very least) callback functions along the lines of “getUnitsVisibleFrom(x, y)” and “findPath(startX, startY, endX, endY).” Or make an interface with those functions, and pass an instance of that to the soldiers.

Encapsulation shouldn’t mean handicapping yourself.

 
Flag Post

I guess OctaBech hit the nail on the head with the object-centric and responsibility centric perspectives. If I’m understanding you right, player_03, you advocate each type of soldier having its own AI (or possibly each soldier implementing its own version of the AI interface), while I would prefer a single AI handling each class of soldier individually.

In the spirit of the How Would You Do It series, and having described how I would at length, I’m just going to stop hogging the thread and let others speak. (Also, I am aware of that thread. I wanted nothing to do with it then, and I still don’t.)

 
Flag Post

Soldiers of the same type would be allowed to store a reference to the same “AI” instance, if appropriate.

 
Flag Post

@Player_03

Encapsulation doesn’t handicap you, you are just seeing it from the wrong perspective, you try to see it from every single unit as if they are independent thinking beings, but that either creates a lot of duplicated code or a whole lot of cross references, both breaking the rules of high cohesion and low coupling. It’s not a problem as long as it’s a small code base and you are the only programmer, but it simply doesn’t work in big projects or if you want to reuse/modify the code base.

Try instead to think of it as one of those role playing games like heroes quest. The unit cards contain information, the figurines represent the movie clips and the game master is the GameLogic class which each turn/frame-even reads the cards, throw the dices and move the figurines on the board. Now you have the difference responsibilities clearly defined and can call them in an logical order. :)

 
Flag Post

Despite the right and wrong answers to this question, I still find that I’ll end up doing it whichever method is most convenient at the time.

The example uses soldiers that die needing to be removed from the battlefield. While fairly strait forward, not all projects are so well…defined when they get started.

Case and point, I made a tower defense game in Unity, and to my horror it ran like garbage on the iPad. One of the hangups I discovered, was the Destroy() command: every time one of the creeps was destroyed (AS3 equivalent: removeChild() ) there was noticeable lag from the garbage collector.

So I had each of the “soldiers” “remove” themselves from the stage by setting their position to a negative value on death (in this case on the Y axis, so they were below the game board and hidden from the camera—absolute position and direction are irrelevant, so long as they are placed where the camera would never see them). Then when the wave was completely done (win/loss, didn’t matter) which was determined in the main game logic, the main game would then iterate over all the enemies and destroy them all at once.

Voila, the garbage collection lag was moved to a point in time where it would go unnoticed.

 
Flag Post
Originally posted by OctaBech:

[…] you try to see it from every single unit as if they are independent thinking beings, but that either creates a lot of duplicated code or a whole lot of cross references […]

I’ve implemented it that way, and no, it doesn’t. Why would it?