I'm using Box2D and Cocos2D for iOS.
From time to time, the game freezes and it is caused by an infinite loop on b2World::SolveTOI.
for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next)
{
// Invalidate TOI
c->m_flags &= ~(b2Contact::e_toiFlag | b2Contact::e_islandFlag);
c->m_toiCount = 0;
c->m_toi = 1.0f;
}
I have a game where a "hero" has to collect coins. Coins are bodies, and through the contact listener I'm adding bodies in an array in order to destroy them later when the array is full (count = 2).
Here is how I add bodies to the array:
+ (void) addBodyToDestroy:(b2Body *)body {
[toDestroyArray addObject:[NSValue valueWithPointer:body]];
}
And here is how I destroy them:
+ (void) destroyAllBodies {
b2World *world = [InGame getWorld];
for (NSValue *bodyValue in toDestroyArray)
{
b2Body *body;
body = (b2Body*)[bodyValue pointerValue];
world->DestroyBody(body);
body = NULL;
}
[toDestroyArray removeAllObjects];
}
What I find very weird is that it doesn't freeze every time, just sometimes, and I can't get to know what seemes to block...
Solution :
The body was added more than once into the array to be destroyed, so when the array was full, it was destroyed more than once, which caused the infinite loop.
b2Contact of the contact manager is linked list data.
So, for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next)
means start from m_contactList and loop until c->next meets NULL
I don't know how your contact listener works, but you have to pay attention to the timing of the world step, collision check and destroy.
Because, the contact listener is called each time when there's a contact while world is stepping. So if your contact listener is designed to store contact data, then you have to process all the contact data between world step and destroy.
(If you don't, there might be dangling pointers of the destroyed body in contact data)
If you want to destroy coins when they fill the array, you'd better check the array if there is same object.
for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next) is quite an unusual for loop, at least from my experience. I can clearly explain what it does, and maybe this will help you.
This is how a for loop works:
for( /*code called at beginning, usually to create a counting variable*/;/*code that is checked for a boolean value every loop. True means loop again, false means stop. Usually this is checking the value of the counting variable.*/;/*code that is called at the end of each loop. Usually this is advancing the counting variable*/) {
//Code inside the loop that does stuff many times
}
So for this loop:
The loop starts. a new b2Contact pointer named c is created and is assigned to the value of the m_contactList property of m_contactManager.
The loop checks the value of c and determines a value of either true or false. In this case, since c appears to be an instance of an object, it probably is checking whether c is nil or not.
At the end of each loop, c is set to point to the m_next member of c. This is quite strange as c is no longer m_contactList but something contained by m_contactList. Then again this could be perfectly normal. You should know what your code does.
Related
sometimes it may happen that MC_MoveAbsolute is called with the same current position of the axis, in this case the "done" or "busy" states cannot be used to manage the end of the function because the function must not perform any movement.
I'm a newbie to these types of controls, the examples I've studied always use a state machine like this:
1: MC_MoveAbsolute .exec: = true;
if MC_MoveAbsolute .busy then // never goes high if AxisActPos = MC_MoveAbsolute.position;
MC_MoveAbsolute .exec: = false;
nextStep: = 2;
end_if
2:
if MC_MoveAbsolute.done then
// do something
what is the best way to handle these situations?
I normally don't use the busy bit.
1: MC_MoveAbsolute .exec: = true;
nextStep: = 2;
2: if MC_MoveAbsolute.done then
MC_MoveAbsolute .exec: = false;
// do something
end_if
The nature of the case structure is that when the step is incremented, the new code won't be executed until the next program scan. So, presuming that you are executing your MC_MoveAbsolute function block on every scan outside of the case, the done bit will be set appropriately (depending on whether motion was needed or not) before it is checked in step 2 of the case.
Documentation (https://docs.unity3d.com/2019.2/Documentation/ScriptReference/RaycastCommand.html) says:
If maxHits is larger than the actual number of results for the command
the result buffer will contain some invalid results which did not hit
anything. The first invalid result is identified by the collider being
null. The second and later invalid results are not written to by the
raycast command so their colliders are not guaranteed to be null. When
iterating over the results the loop should stop when the first invalid
result is found.
Soo, having
new RaycastCommand(from, direction, 4);
How can i distinguish if i had no hits vs when result is invalid? Both cases have hit.collider == null.
If collides with multiple elements, rather than returning the nearest colliding one, it will return nothing??
RaycastHit is a struct type thus itself can never be null. So as the docs says
The first invalid result is identified by the collider being null.
NOTE: The order of the (optional) parameters in the constructor if not explicitly named is
new RaycastCommand(Vector3 from, Vector3 direction, float distance, int layerMask, int maxHits);
and their default values are
distance = float.MaxValue
layerMask = -5
maxHits = 1
Again in words: The default value for maxHits is 1!
Unfortunately this is not visible in the docs but your IDE should reveal that.
Knowing this now you can see that your current example
new RaycastCommand(from, direction, 4);
actually says: The maximum distance of the ray is 4 but still allows only 1 single hit!
If you rather wanted to have 4 possible hits you have to call it as
new RaycastCommand(from, direction, maxHits: 4);
now if you call it like this a buffer with exactly 4 RaycastHit entries will be created, no matter how many objects are hit or if any at all.
Then nothing was hit at all if
results[0].collider == null
and since unfortunately
The second and later invalid results are not written to by the raycast command so their colliders are not guaranteed to be null.
you would have to filter them e.g. like
var validResults = new List<RaycastHit>();
foreach(var r in results)
{
if(r.collider == null) break;
validResults.Add(r);
}
Then you could further also sort them to "nearest first" using Linq like e.g.
using System.Linq;
...
var orderedResults = validResults.OrderBy(r=>r.distance).ToList();
// Which is basically a shorthand for something like the following
// not sure though how Linq does it internally, I hope it does something more efficient ^^
var orderedResults = new List<RaycastHit>();
foreach(var r in validResults)
{
for(int i = 0; i < orderedResults.Count; i ++)
{
if(orderedResults[i].distance <= r.distance)
{
orderesResult.Insert(i + 1, r);
break;
}
}
}
Say ...
you have about 20 Thing
very often, you do a complex calculation running through a loop of say 1000 items. The end result is a varying number around 20 each time
you don't know how many there will be until you run through the whole loop
you then want to quickly (and of course elegantly!) access the result set in many places
for performance reasons you don't want to just make a new array each time. note that unfortunately there's a differing amount so you can't just reuse the same array trivially.
What about ...
var thingsBacking = [Thing](repeating: Thing(), count: 100) // hard limit!
var things: ArraySlice<Thing> = []
func fatCalculation() {
var pin: Int = 0
// happily, no need to clean-out thingsBacking
for c in .. some huge loop {
... only some of the items (roughly 20 say) become the result
x = .. one of the result items
thingsBacking[pin] = Thing(... x, y, z )
pin += 1
}
// and then, magic of slices ...
things = thingsBacking[0..<pin]
(Then, you can do this anywhere... for t in things { .. } )
What I am wondering, is there a way you can call to an ArraySlice<Thing> to do that in one step - to "append to" an ArraySlice and avoid having to bother setting the length at the end?
So, something like this ..
things = ... set it to zero length
things.quasiAppend(x)
things.quasiAppend(x2)
things.quasiAppend(x3)
With no further effort, things now has a length of three and indeed the three items are already in the backing array.
I'm particularly interested in performance here (unusually!)
Another approach,
var thingsBacking = [Thing?](repeating: Thing(), count: 100) // hard limit!
and just set the first one after your data to nil as an end-marker. Again, you don't have to waste time zeroing. But the end marker is a nuisance.
Is there a more better way to solve this particular type of array-performance problem?
Based on MartinR's comments, it would seem that for the problem
the data points are incoming and
you don't know how many there will be until the last one (always less than a limit) and
you're having to redo the whole thing at high Hz
It would seem to be best to just:
(1) set up the array
var ra = [Thing](repeating: Thing(), count: 100) // hard limit!
(2) at the start of each run,
.removeAll(keepingCapacity: true)
(3) just go ahead and .append each one.
(4) you don't have to especially mark the end or set a length once finished.
It seems it will indeed then use the same array backing. And it of course "increases the length" as it were each time you append - and you can iterate happily at any time.
Slices - get lost!
I'm working on a game in Lua, and so far I have everything working with everything in one document. However, to better organize everything, I've decided to expand it into modules, and while I figure I could probably get it working more or less the same, I figure now might be an opportunity to make things a little more clear and elegant.
One example is enemies and enemy movement. I have an array called enemyTable, and here is the code in Update that moves each enemy:
for i, bat in ipairs(enemyTable) do
if bat.velocity < 1.1 * player.maxSpeed * pxPerMeter then
bat.velocity = bat.velocity + 1.1 * player.maxSpeed * pxPerMeter * globalDelta / 10
end
tempX,tempY = math.normalize(player.x - bat.x,player.y - bat.y)
bat.vectorX = (1 - .2) * bat.vectorX + (.2) * tempX
bat.vectorY = (1 - .2) * bat.vectorY + (.2) * tempY
bat.x = bat.x + (bat.velocity*bat.vectorX - player.velocity.x) * globalDelta
bat.y = bat.y + bat.velocity * bat.vectorY * globalDelta
if bat.x < 0 then
table.remove(enemyTable,i)
elseif bat.x > windowWidth then
table.remove(enemyTable,i)
end
end
This code does everything I want it to, but now I want to move it into a module called enemy.lua. My original plan was to create a function enemy.Move() inside enemy.lua that would do this exact thing, then return the updated enemyTable. Then the code inside main.lua would be something like:
enemyTable = enemy.Move(enemyTable)
What I'd prefer is something like:
enemyTable.Move()
...but I'm not sure if there's any way to do that in Lua? Does anyone have any suggestions for how to accomplish this?
Sounds like you just want the metatable of enemyTable to be the enemy module table. Lua 5.1 reference manual entry for metatables
Something like this.
enemy.lua
local enemy = {}
function enemy:move()
for _, bat in ipairs(self) do
....
end
end
return enemy
main.lua
local enemy = require("enemy")
enemyTable = setmetatable({}, {__index = enemy})
table.insert(enemyTable, enemy.new())
table.insert(enemyTable, enemy.new())
table.insert(enemyTable, enemy.new())
enemyTable:move()
Of course you can do it. For what I can see, your Move function processes the table you pass it as an argument and returns another table, in a functional programming fashion, leaving the first table immutate. You just have to set your Move function so that it knows it has to operate on your enemy table instead of creating a new table. So in your module write:
local enemy = {}
-- insert whatever enemy you want in the enemy table
function enemy.Move()
for _, bat in ipairs(enemy) do
--operate on each value of the enemy table
end
--note that this function doesn't have to return anything: not a new enemy table, at least
end
return enemy
And in your love.load function you can call
enemyTable = require "enemymodule"
Then you just have to call enemyTable.Move()
Apologies if the question is poorly phrased, I'll do my best.
If I have a sequence of values with times as an Observable[(U,T)] where U is a value and T is a time-like type (or anything difference-able I suppose), how could I write an operator which is an auto-reset one-touch barrier, which is silent when abs(u_n - u_reset) < barrier, but spits out t_n - t_reset if the barrier is touched, at which point it also resets u_reset = u_n.
That is to say, the first value this operator receives becomes the baseline, and it emits nothing. Henceforth it monitors the values of the stream, and as soon as one of them is beyond the baseline value (above or below), it emits the elapsed time (measured by the timestamps of the events), and resets the baseline. These times then will be processed to form a high-frequency estimate of the volatility.
For reference, I am trying to write a volatility estimator outlined in http://www.amazon.com/Volatility-Trading-CD-ROM-Wiley/dp/0470181990 , where rather than measuring the standard deviation (deviations at regular homogeneous times), you repeatedly measure the time taken to breach a barrier for some fixed barrier amount.
Specifically, could this be written using existing operators? I'm a bit stuck on how the state would be reset, though maybe I need to make two nested operators, one which is one-shot and another which keeps creating that one-shot... I know it could be done by writing one by hand, but then I need to write my own publisher etc etc.
Thanks!
I don't fully understand the algorithm and your variables in the example, but you can use flatMap with some heap-state and return empty() or just() as needed:
int[] var1 = { 0 };
source.flatMap(v -> {
var1[0] += v;
if ((var1[0] & 1) == 0) {
return Observable.just(v);
}
return Observable.empty();
});
If you need a per-sequence state because of multiple consumers, you can defer the whole thing:
Observable.defer(() -> {
int[] var1 = { 0 };
return source.flatMap(v -> {
var1[0] += v;
if ((var1[0] & 1) == 0) {
return Observable.just(v);
}
return Observable.empty();
});
}).subscribe(...);