1
\$\begingroup\$

I am creating a 2d mobile game where there are three levels. Each level has 20 objectives. This can increase in the future.

Examples:

Level 1
Current Objective: 2/20
Objective : Collect 1000 coins
Rewards: 100  coins.

Level 1
Current Objective: 20/20
Objective : Kill 100 aliens
Rewards: Shotgun

The question is, when a user is playing a game, how do you check if he has already completed his current objective in efficient way? This is not involving any third party listener like GameCenter, Scoreloop, etc.

I do not want to have a method with zillions of switch/if-else/or any other conditional blocks to be checked in every update call since this will affect the FPS. Some frameworks are not thread-safe. So having a separate thread is not an option either since I am going to port it to some other platforms using some other frameworks.

How do I go about it?

\$\endgroup\$
1

4 Answers 4

5
\$\begingroup\$

Premature optimization and design paralysis are evil. Don't fall into the trap of worrying about a simple check. If you're concerned, implement and profile.

I think you're under-estimating how powerful hardware can be - even the low-end hardware. An if statement comparing a simple boolean is pretty cheap and should be the least of your concerns in a game. I agree that checking for the condition every frame isn't ideal - but there a lot of difference ways you can circumvent this if you're that concerned. The check is extremely cheap and many others have went over this - but I'll try to give yet another detailed explanation. You've tagged this under Java and C++ and mentioned Android 1.5 in a comment - so presumably that is your target.

Check only when necessary. If you have an objective that is obtain a score of 10, 000 points; add a check on your setter for score or add a callback to the achievement manager, preferably to verify this. The objective manager would just be a simple hash map of enums and booleans; (I picked hash map for the fast lookup times) the callback makes a quick lookup into this table and sets it to unlocked if needed.

Optimize for the game objectives. If your game objective is "kill 5 ships", keep a counter of the alive ships left; don't query the game state directly. Evaluate the state deltas as they are completed so you don't have to do an expensive computation all at once. This is handy if your objective requires a lot of spatial probing that might be expensive. Does every yellow box need to be touching a green box? On collision, set a flag to determine this and then unset it when the object moves off. Keep the state easy to access and query.

Defer the check. If your check is more expensive than a single lookup and a few comparisons (expensive property getters, functions or lots of checks) and you really think you can't optimize the checks, then you can always defer your check. Your game likely has states that are idle or the player is not doing a whole lot. It's tough to say without knowing your game - but let me give a general gist.

We'll use Angry Birds as a quick example here to illustrate the purpose. Angry Birds probably has a lot of states in its state machine - but for simplification reasons we're going to assume just two.

The first state is when the birds are resting on the slingshot; they're idle and not doing anything and just waiting for user input. Not a lot of stuff is going and small FPS drops would go unnoticed the minute this state is transitioned to.

The second state is of course when the bird is flying through the air. After this state finishes (the bird has finished flight), the game transits back to the slingshot (state 1) and checks to see if all the pigs have seen defeat.

The idea of deferring the objective checks works exactly like Angry Birds does - you can queue up plausible objective checks that could have happened during that state and then you verify later when the load is acceptable and the end user won't notice any obvious frame drops.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you so much. This is exactly what I was looking for. I wanted to know if I was right thinking that way but never had so much faith. Thank you. \$\endgroup\$
    – Malakai
    Commented Mar 27, 2013 at 1:19
1
\$\begingroup\$

You should create an achievement system for observing the rules and performing the necessary checks

How can I set up a flexible framework for handling achievements?

\$\endgroup\$
0
\$\begingroup\$

Keep a list of achievements per level. Iterate through the list each cycle. If an achievement is done just delete it from the list (to put it another way, check is accomplished).

Don't be affraid to "if" each option. Your gameboy would be able to iterate a 1000 member list with 60 fps (hypothetically). You won't feel an FPS drop.

There are ways to go without ifs using some simple mathematical formulas but it's 2013. We don't need hacks like that. It will make your code more obscure.

\$\endgroup\$
5
  • \$\begingroup\$ I know it's 2013 and I know there are still 1.5 Android devices that people use. \$\endgroup\$
    – Malakai
    Commented Mar 26, 2013 at 13:35
  • \$\begingroup\$ It doesn't matter. 1.5 devices are more than enough. You need to iterate. The cost is low. \$\endgroup\$
    – AB.
    Commented Mar 26, 2013 at 15:17
  • \$\begingroup\$ It DOES matter. I have been testing my game on LG Optimus GT540. It runs on Android 1.6. One more calculation matters. You can run a nice particle effect on it. You can rotate a 3d model on it. But a game is not made just to display a cool particle effect, or cool animated hud layer, or a cool flying hero with a gun. A game is composed of all these and many more. So, yes it matters. \$\endgroup\$
    – Malakai
    Commented Mar 26, 2013 at 15:44
  • \$\begingroup\$ How about you profile your code first instead of preaching the nonsence of exorbitant cost of 20 ifs (branch misses of course) ? \$\endgroup\$
    – AB.
    Commented Mar 26, 2013 at 22:12
  • \$\begingroup\$ You should not assume that the person who asks a question is less intelligent/knowledgeable than you are. This thing only happens to average programmers who think they are "good". Look at the answer of Vaughan Hilts. This is how you help. \$\endgroup\$
    – Malakai
    Commented Mar 27, 2013 at 1:21
0
\$\begingroup\$

Just check at every event instead of every frame call. For example, if you have an objective of gathering 200 coins, check this one only when you get a coin. If you have a score achievement, check it only when the score changes.
Checking those things only when relevant will keep your overhead mininum.

To avoid the big if/switch structure you can make a specialized class to manage those achievements/objectives and have an exclusive function for each single achievement.

\$\endgroup\$
2
  • \$\begingroup\$ Essentially same answer as mine, but according to WebApp this is not efficient enough for him. \$\endgroup\$ Commented Mar 26, 2013 at 14:34
  • 1
    \$\begingroup\$ Well, I can't think of any possible way more efficient than checking once, and only once, each time an event occurs. Barring some convoluted hack that will tottaly hinder his intended portability, he will have to do this. \$\endgroup\$
    – petervaz
    Commented Mar 26, 2013 at 16:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .