Hi, I'm really stuck trying to write decent/mantainable code for my little tilebased oldschool 2d engine.
I started trying to use the less math possible, like the majority of old 2d games did... Now apart from the stupid algorithm that I'm using(the main point here is not how to do collisions), I would like to know how can I organize lots of code that is always dependent on the same value (in this case direction.x), as you can see. At first I had 2 main branches with lots of repeated code, I tried to precompute some stuff in this example, like inFront, isNewOverlap and isNewBestEntity. This allowed me to use the same code after, without having two main branches differing only for these checks, all of this is inside a loop that checks for some tiles in front of the entity moving. But as you can imagine, later code (but also before this example) is the same, we always have checks that compare greater o less then values, or include width or not... I thought of switching to a center based coordinates system instead of top left (so that I can always do centerX + width*direction) but since I'm working with bitmap I have no real center so I tried to avoid that... and even if I had done it, I would still have to fight with all those > < checks...
So the real and only question is:
Is there a better way for handling all of these repeating code without changing the algorithms? (stuff like the example here the code is starting to grow and it's full of stuff like this)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 |
if(foundCollideEntity)
{
ASSERT(direction.x != 0.0f);
//compute direction dependent calculations:
b32 inFront = 0, isNewOverlap = 0, isNewBestEntity = 0;
b32 isOverlap = (foundCollideEntity->flags & ENTITY_FLAG_OVERLAP_W_ENTITIES);
if(direction.x > 0.0f)
{
inFront = toPixelCoord(foundCollideEntity->p.x) >= toPixelCoord(entity->p.x + entity->width-1);
isNewOverlap = isOverlap && (!*validOverlapX || foundCollideEntity->p.x < (*validOverlapX)->p.x);
isNewBestEntity = (!(*bestEntityX)) || (foundCollideEntity->p.x < (*bestEntityX)->p.x);
}
else
{
inFront = toPixelCoord(foundCollideEntity->p.x + foundCollideEntity->width-1) <=
toPixelCoord(entity->p.x);
isNewOverlap = isOverlap && (!(*validOverlapX) || (foundColliderEntity->p.x +
foundColliderEntity->width-1) >
((*validOverlapX)->p.x + (*validOverlapX)->width-1));
isNewBestEntity = (!(*bestEntityX)) || (foundCollideEntity->p.x + foundCollideEntity->width-1) >
(*bestEntityX)->p.x + (*bestEntityX)->width-1;
}
//NOTE: we now also check for the current tile and entitites can be behind the player
if(inFront) //direction dependent!!
{
if(IsEdgeToEdgeInRange(entity->p.y,
entity->p.y + entity->height-1,
foundCollideEntity->p.y,
foundCollideEntity->p.y + foundCollideEntity->height-1))
{
//TODO: HERE WE SHOULD HAVE A LIST OF OVERLAPPING ENTITIES SINCE WE CAN OVERLAP
// WITH MORE THAN ONE AT THE SAME TIME
//entity is COLLIDING
if(isNewOverlap)//direction dependent!!
(*validOverlapX) = foundCollideEntity;
else if(isNewBestEntity)//direction dependent!!
(*bestEntityX) = foundCollideEntity;
}
}
}
}
|
I don't know if this type of code is inherently like that, and then I should only stay with the previous one, with a big main branch with repeated code and accept the form of it... I hope someone can shine some light on my question!
Cheers from Italy!