• Advertisement
Sign in to follow this  

Refactoring if-conditions for player turn code

This topic is 1315 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello,

 

I've got some code for a 2d game that orients an NPCs graphic towards the direction he is walking to. There are 4 directions (down, left, right, up), that have the values (0, 1, 2, 3) respectively (so 3 - direction will yield the other direction on that axis). It is possible for the NPC to walk straight, diagonally, and unevenly-diagonally (2 pixel on the x-axis, 1 on the y-axis, hope you know what I'm talking about). Now the code for mapping this movement to the direction is rather clumsy, just a big mess of if-statements:

unsigned int DirectionFromMove(const math::Vector2& vMove)
{
	if(vDir.x > 0)
	{
		if(vDir.y > 0)
		{
			if(vDir.x > vDir.y)
				return 2;
			else
				return 0;
		}
		else if(vDir.y < 0)
		{
			if(vDir.x > abs(vDir.y))
				return 2;
			else
				return 3;
		}
		else
			return 2;
	}
	else if(vDir.x < 0)
	{
		if(vDir.y > 0)
		{
			if(abs(vDir.x) > vDir.y)
				return 1;
			else
				return 0;
		}
		else if(vDir.y < 0)
		{
			if(vDir.x < vDir.y)
				return 1;
			else
				return 3;
		}
		else
			return 1;
	}
	else
	{
		if(vDir.y > 0)
			return 3;
		else if(vDir.y < 0)
			return 0;
	}
}

I thought about it for a while, but didn't find any better way myself. I'm really curious, since in "production"-code I always end up with stuff like this. Is there some clever solution here to get rid of all the ifs?

Share this post


Link to post
Share on other sites
Advertisement


I hope this works... gone testing...

 

Yep, this does indeed work, thanks a lot, thats a whole lot easier. Except that I somehow got up and down mixed up, at least its easier to fix in your version :D So the general advice for such monstrous if-statements would be "look for an easier algorithmn", or is there some recommandation in case there is no easier algorithmn scheme?

Share this post


Link to post
Share on other sites


Yep, this does indeed work, thanks a lot, thats a whole lot easier. Except that I somehow got up and down mixed up, at least its easier to fix in your version So the general advice for such monstrous if-statements would be "look for an easier algorithmn", or is there some recommandation in case there is no easier algorithmn scheme?

 

I started by drawing a crude diagram and looking for a mathematical solution. Sometimes it's easier to visualize that way.

Share this post


Link to post
Share on other sites

I want to add something to my last post.

 

If you have a function that returns 4 distinct values but there are some code paths that return the same value this is a very good indicator that the function can be refactored into a simpler solution.

 

When doing calculations in vector space I'd always recommended to scribble up a diagram except for the simplest of cases.

Share this post


Link to post
Share on other sites
unsigned int DirectionFromMove(const math::Vector2& vMove)
{
    return (vDir.x < vDir.y) + 2*(vDir.x > -vDir.y);
}

Also untested...

 

Assuming that works you can be even more fancy if you want and do

 

That's something like what I usually go with in cases like this. If you can split the distinctions into ranges within a binary number it becomes easier to see. In this case you're only dealing with a pair of binary states, so it's really the simplest case.

 

This sort of touches on the field of "discrete mathematics". You may want to poke around for a cheap book on the subject if this kind of 'puzzle' interests you. Usually when your intuition is telling you that something can be simplified there's a 'clever' solution in there somewhere.

Share this post


Link to post
Share on other sites

~snip~

 

To be honest, when I see long nested if-trees I mentally replace the whole thing with a picture of spongebob jumping up and down. I get why it's not great to do it all on one line around JPs, but something like:

int result = 0;
if(vDir.x < vDir.y)  {result += 0x01;}
if(vDir.x > -vDir.y) {result += 0x02;}
return result;

Is much preferred for me. It's actually a lot more to do with visual efficiency rather than performance efficiency. I can look at those three lines and sort out what's going on in a few moments, but I'm simply not interested in browsing through that whole if-tree to see what details are where.

 

This is kind of a poor example of what I mean, since this really is the simplest use case for this and it could easily go either way, but when you get to something where you're crapping out ordinals based on 14 different conditions, it can be a lot easier to sort out a one-page bit-field rather than a five page if-tree.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement