How to mark instance for deletion in XNA/Monogame - xna

In my tower defense game I am making when my enemies die, well I want them to die right? So, I need to delete them. I am coming over from C++ where you can just delete instances of a class with delete MyInstance;, but that doesn't work in C#. I know that there is a garbage collector in C# that deletes things for you, but, how do you mark an instance for deletion? Thank YOU!!!

My recommendation would be to not delete them. While you have a garbage collector to help out, not using it can often be your best choice from a performance point of view.
Think of the maximum number of enemies you could potentially have.
Create a circular buffer of Enemy objects: essentially an array of Enemy objects and a last pointer.
Add an "IsActive" flag to each Enemy.
When you want to create a new enemy, walk forward through the circular buffer from the last pointer until you find an Enemy that has its IsActive flag set to false. Set the last pointer to that enemy, make that enemy into the type that you care about, and set its IsActive flag to true.
When the enemy dies, set its IsActive flag to false.
In your Update and Draw loops, you just iterate through the buffer and either act on or draw each Enemy that has IsActive set to true.

You can explicitly set an object to null, that will mark it for garbage collection.
Enemy e = new Enemy();
// do stuff with enemy
// Set to null
e = null;

Related

GKGoal Avoid Boundary Obstacles

I am seeming to have difficulty keeping my sprite nodes inside a map boundary that I have set up in the following way:
I have an SKNode *enemy that moves around an SKScene by goals and behaviors courtesy of GameplayKit from iOS 9. Currently the node wanders, and avoids obstacles that are defined GKPolygonObstacle objects. I have my bitmask set up so that any obstacle is deemd category wall, which the node is told to collide with (AKA disallow passing through).
In my didBeginContact:(SKPhysicsContact *)contact I am handling these collisions. All is working exactly as planned and there are no issues when manually moving this enemy.
However, the problem begins when I have the enemy wander around the scene through an SKGoal *wanderGoal set up as
// Low --> 0.5 Lowest --> 0.25
enemy.wanderGoal = [GKGoal goalToWander:low];
[enemy.agent.behavior setWeight:lowest forGoal:enemy.wanderGoal];
// Add obstacles to avoid for each of the inner map nodes
// that act as impassible areas for the enemy to pass through.
NSArray *obstacles = [SKNode obstaclesFromNodePhysicsBodies:innerMapArray];
/** This goal does not change --> enemies will ALWAYS
avoid the obstacles in the level map. This should always
be set to the highest priority of the enemy goals
*/
enemy.avoidGoal = [GKGoal goalToAvoidObstacles:obstacles maxPredictionTime:10];
// Highest --> 250
[enemy.agent.behavior setWeight:highest forGoal:enemy.avoidGoal];
The enemy moves randomly as expected, and seems to avoid the obstacles most of the time...yet on the occasion the enemy does in fact pass through the map barrier. Let me expand on this:
The map barrier is essentially a rectangle, and I have set up 2 nodes that act as a shell that represent the left half and the right half of this shape. These nodes have a thickness of 100 points so they are not simply CGPath refs but rather shapes. They act as these two brackets act: [] (my halves are flush touching at the middle).
My question is such:
How can I prevent the enemy from passing through these obstacles with using either physics with the bitmask categories, or by the goal behavior? (Or both together)
I understand that while a GKGoal is a suggested behavior it does not guarantee this goal to be reached (but it can be ~95% sure it wont happen as Apple's AgentsCatalog shows). But, what I don't understand is why the enemy does not simply "slide" along the edge of the boundary as the goal tells it to (try to) "pass" through such boundary.
This "sliding" behavior does happen when I manually move the enemy around the scene, and as I attempt to move it passed a boundary deemed an obstacle, it slides towards the direction that I am having it move (just as any video game does that has map boundaries).
SO
If someone can help me prevent this from happening / explain how to approach preventing the enemy from ever passing through these (supposedly) "impassible" areas, I would be most appreciative.
FYI: If you are unclear with what I am describing / how I have created any objects, please ask and I will provide more info to help.

How to determine when bodies in display stop moving in lua

I have some bodies moving in display using physics. I want to determine when bodies stop moving so as to call a function to take an action.
I tried a function like so:
function ball:stopMove ()
if condition then
print("Game Over!!!")
end
end
This do not get invoked. how can I do this correctly?
You can here to see how to implement your own callbacks. Basically you can create a proxy table that acts as a filter, screening for certain actions and acting on those.
If you don't want to do that, assuming you created a physics body, the function you are looking for is object:getLinearVelocity. If the object's x and y velocity are zero, the body has stopped moving. You would, of course, need to check for this every update.
Alternatively, you can calculate this yourself if you aren't using a physics body. All you need to do is keep track of the object's last x and y positions, and if the values are the same, the object has not moved since the lasted update.
I am not aware of any movement related events. So I guess you have to frequently poll the objects velocity for being zero.

Does the usePreciseCollisionDetection property work when the physics body does not have a collisionBitMask

I do not want my physics bodies to collide when they come in contact, but I want to use the
physicsBody?.usesPreciseCollisionDetection = true so that it detects contacts between the two bodies more accurately. So if I set
physicsBody?.collisionBitMask = PhysicsCategory.None //Assume that PhysicsCategory is an Enum and .None means that the bit mask is set to 0 or nothing
physicsBody?.usesPreciseCollisionDetection = true
Will the usesPreciseCollisionDetection still be valid? And if not, how to I implement more precise contact testing?
Thanks
you usually need usesPreciseCollisionDetection to make sure that a fast moving object isnt passing through a set of tiles or other physics objects that are pressed together. if youre just using the physics object as a sensor (just to test for collisions) then you probably dont need to use that. I would guess that it works either way since the documentation doesnt say otherwise, but i dont think theres any way to know for sure..
EDIT: It does matter.. if you want to detect fast moving objects set usesPreciseCollisionDetection to true. You need it whether you have a collisionbitmask set or not. Thanks Whirlwind!

Why are didBeginContact called multiple times?

In an iOS game that uses Sprite Kit along with the contact detection in Sprite Kit's build-in physics engine, I decrease the Hero's number lives by one each time he gets in contact with an enemy. This is done from the didBeginContact method.
However, it seems like that method is not just called once, when the contact begins, but called continuously as long as the Hero and the enemy overlaps: when I set a breakpoint in that method, I can see, that it is the exact same physics body instances that exist as contact.bodyA and contact.bodyB. The result is, that the Hero will lose multiple lives, even though he only passes one single enemy.
If the Hero meets the same enemy again later, he should get one more live subtracted, and therefore I cannot just maintain a seenEnemies hash set to deal with the problem above.
The question is now: how would you make sure that only one live is subtracted for each Hero/enemy contact?
The reason why the didBeginContact is being fired multiple times is because you have multiple contact points happening on concave shapes.
If you look at the picture below, you will see I have 2 sprites, a black star and a red rectangle. When the black star hits the red rectangle, it hits it on multiple points, circled in blue. Sprite Kit will then do a call for each line intersection, so that the developer can use the contactPoint variable for each of these contacts.
I had the same problem (score increasing multiple times for a single enemy destroyed and multiple life points being lost for a single instance of damage.) A user on the Apple forums thinks that it's a bug in [SKPhysicsBody bodyWithTexture:size:] but I don't believe that's the case, because it was happening with other constructors too.
First off, the categoryBitMask and contactTestBitMask are very important, obviously. Take a look at Apple's SpriteKit Physics Collisions sample code:
// Contacts are often a double dispatch problem; the effect you want is based on the type of both bodies in the contact. This sample this in a brute force way, by checking the types of each. A more complicated example might use methods on objects to perform the type checking.
// The contacts can appear in either order, and so normally you'd need to check
each against the other. In this example, the category types are well ordered, so
the code swaps the two bodies if they are out of order. This allows the code
to only test collisions once.
What I did to solve it was setting a flag after handling each condition. In my case, I was testing whether bodyA.node.parent was nil in didBeginContact, because I called removeFromParent() on the missile/enemy nodes to destroy them.
I think you should expect the event to fire multiple times and your code in there has to make sure it's processed only once.
I figured out easy solution:
Just change either body's categoryBitMask value to 0 or non-used value right after it detected contact.
For example:
if (firstBody.categoryBitMask == padCategory && secondBody.categoryBitMask == colorBallCategory) {
secondBody.categoryBitMask = 0;
// DO OTHER THING HERE
}
I came across the same issue. In my case the didBeginContact() was called many times (I counted up to 5 times) for one contact of a bullet with the enemy. As the bullet is a simple circle format, I agree with #SFX that it cannot be a bug just in Texture-Bodies. The tests have shown that there was no call to update() between the didBeginContact() calls. So the solution is simple (Swift):
var updatesCalled = 0
...
internal update() {
updatesCalled ++
}
...
internal func didBeginContact(contact: SKPhysicsContact) {
NSLog("didBeginContact: (\(contact.contactPoint.x), \(contact.contactPoint.y)), \(updatesCalled)")
if(updatesCalled == 0) {return} // No real change since last call
updatesCalled = 0
... your code here ...
}
I tried didEndContact() but that was not called at all. I didn't investigate further into this.
BTW: I just switched from Android, and I'm impressed by the easiness and stability of this System :-)
Here is an option that makes the player invulnerable after being hit for a set time:
A. Create a variable that makes the player invulnerable to losing a life after being hit for a few seconds.
Create a global Boolean variable called isInvuln (set to FALSE) and an NSTimeInterval called invulnTime.
In the method that handles the player and enemy making contact, check to see if isInvuln is False before taking a life. (if isInvuln is true ... do nothing)
If isInvuln is false, take a life then set isInvuln to true.
if(self.isInvuln == FALSE){
self.player.lives-=1;
self.isInvuln = True;}
Add to your updateWithCurrentTime:
if(self.isInvuln==True){
self.invulnTime += timeSinceLast;}
if (self.invulnTime > 3) {
self.isInvuln = FALSE:}
self.invulnTime= 0;
This will make it so that when an enemy and player collide, the player loses a life and becomes invulnerable 3 seconds. After that 3 seconds, the player can take damage again. If the enemy contacts the player within the 3 invulnerable seconds, the contact method does nothing. Hope this helps spark ideas to tackle your problem.
In my experience, didEndContact & didBeginContact are both called multiple times while the objects overlap. This is also happening in SceneKit using iOS 9, so I have to assume it's an intended behavior.

How to make a specific object defy gravity? (SpriteKit / Objective-C)

I'm working on a piece of code, and I want there to be gravity in the view but I want specific projectiles to defy gravity and fly across the screen. I know to get rid of the gravity on the whole view its just:
self.physicsWorld.gravity = CGVectorMake(0, 0);
But as stated I want gravity on the scene.
So I'm wondering if there is a way to take the gravity off one specific item? (i.e. the SKSpriteNode _debris item in my case)
By setting the physicsBody to not be affected by gravity.
E.g.
myNoGravityObject.physicsBody.affectedByGravity = NO;
See the documentation of SKPhysicsBody.
If you don't want a node to interact with physics calculations at all, but still want it to have a physicsBody (i.e. to make it begin to interact with things later on, or to check for collisions with other nodes), you can set
node.physicsBody.dynamic = NO;
This will cause the node to ignore gravity, as well as collisions, impulses, and the like. If you are setting up the contact delegate, note that at least one node in any given contact must be dynamic for the contact delegate to be notified of the event.

Resources