Pregunta

I'm looking into how I should design my games in regards to management/transitioning of different "screens" as well as effect timings. I'm currently using AndEngine on Android, which doesn't have an explicit game loop, although I'm interested in hearing how these issues are dealt with both with or without a game loop.

  1. I've already written a temporary system that I'm using to handle the different "screens" in my game (splash, menu, game, options etc), which is based on "scenes" within AndEngine. I've got 3 base "scenes" which act as layers for a background, content and popups. Each Screen has onTransitionIn() and onTransitionOut() methods which are called by the ScreenManager when it's own methods (such as closePopup(), that sort of thing) are called. However, all code in the transition methods would obviously be run at once, meaning all animations, the screen status etc would be executed instantly. To overcome this problem, I used the postDelayed(runnable, delay) method in the Android Handler class. That way, I was able to change the screen status after the transition animations were completed and run one animation after another. Now the entire system is pretty much based on running delayed code via the handler. Unsurprisingly, it's crude, not particularly stable and generally amateurish.

  2. The second issue regarding "effect timings" is closely linked to my usage of the Handler class. Let's just say I want to create an effect when a user completes a task, where some animation is played and a number is increased on the screen. At the moment, the only way of having one run after the other is by using the Handler. As stated previously, this appears to me like a crude/unstable/amateurish method.

I'd really like to know how these issues are generally handled in games (both with/without an explicit loop).

¿Fue útil?

Solución

From your description, it sounds like when you want to trigger a chain of actions, you're basically firing them all off at once, each with some fixed delay. This is quite fragile - if you change the duration of one of the actions, it might no longer sync up with something that's supposed to happen after it.

A more robust approach would be to use the Observer Pattern. Each action could have an onCompleted() event (and/or various other events, depending on the nature of the action), which could be used to trigger the start of the next action.

For example, let's say that when the user presses the selects a menu item, you want this sequence of events:

  1. Play an animation of the selected item.
  2. When 1 is finished, transition the current screen off.
  3. When 2 is finished, transition the next screen on.

It sounds like you're doing something like this:

void onItemSelected(MenuItem menuItem) {
    runNow(new SelectedItemAnimationHandler(menuItem)); // Takes 500ms
    // Delay for 500ms to wait until end of selection anim.
    postDelayed(new ScreenTransitionOffHandler(currentMenu), 500); // Takes 1000ms
    // Delay for 1500ms to wait until end of transition off.
    postDelayed(new ScreenTransitionOnHandler(nextMenu), 1500);
}

You might chain the events by creating Actions (which fulfil the 'subject' role in the Observer pattern) and ActionObservers (which fulfil the 'observer' role):

void onItemSelected(MenuItem menuItem) {
    // Set up the actions
    // Actions call onCompleted() on any observers when they complete.
    SelectedItemAnimationAction sa = new SelectedItemAnimationAction(menuItem);
    ScreenTransitionOffAction stoff = new ScreenTransitionOffAction(currentMenu);
    ScreenTransitionOnAction ston = new ScreenTransitionOnAction(nextMenu);

    // Add some observers to the actions
    sah.addOnCompletedHandler(new ActionObserver() {
            public void onCompleted() {
                stoff.start();
            }
        });
    stoff.addOnCompletedHandler(new ActionObserver() {
            public void onCompleted() {
                ston.start();
            }
        });

    // Start the first action
    sa.start();
}

This way, you don't need to specify the duration of the SelectedItemAnimationHandler when you set up the ScreenTransitionOffHandler.

EDIT: Tried to make implementation of the Observer pattern clearer. EDIT 2: Changed runNow(action) to action.start()

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top