• No se han encontrado resultados

SUCESIÓN DE FIBONACC

In document AQUÍ (página 32-67)

After all the groundwork we’ve done, we can finally talk about how to actually implement the game itself. For that, let’s identify what tasks have to be performed by our game:

The game is split up into different screens that each perform the same tasks: evaluating user input, applying the input to the state of the screen, and rendering the scene. Some screens might not need any user input, but transition to another screen after some time has passed (e.g., a splash screen).

The screens need to be managed somehow (e.g., we need to keep track of the current screen and have a way to transition to a new screen, which boils down to destroying the old screen and setting the new screen as the current screen).

The game needs to grant the screens access to the different modules (for graphics, audio, input, etc.) so they can load resources, fetch user input, play sounds, render to the framebuffer, and so on.

As our games will be in real time (that means things will be moving and updating constantly), we have to make the current screen update its state and render itself as often as possible. We’d normally do that inside a loop called the main loop. The loop will terminate when the user quits the game. A single iteration of this loop is called a frame. The number of frames per second (FPS) that we can compute is called the frame rate.

Speaking of time, we also need to keep track of the time span that has passed since our last frame. This is used for frame-independent movement, which we’ll discuss in a minute.

The game needs to keep track of the window state (e.g., whether it got paused or resumed), and inform the current screen of these events.

The game framework will deal with setting up the window and creating the UI component we render to and receive input from.

Let’s boil this down to some pseudocode, ignoring the window management events like pause and resume for a moment:

createWindowAndUIComponent(); Input input = new Input();

Graphics graphics = new Graphics(); Audio audio = new Audio();

Screen currentScreen = new MainMenu(); Float lastFrameTime = currentTime();

CHAPTER 3: Game Development 101

95

while( !userQuit() ) {

float deltaTime = currentTime() – lastFrameTime; lastFrameTime = currentTime();

currentScreen.updateState(input, deltaTime); currentScreen.present(graphics, audio, deltaTime); }

cleanupResources();

We start off by creating our game’s window and the UI component we render to and receive input from. Next we instantiate all our modules necessary to do the low-level work. We instantiate our starting screen and make it the current screen, and record the current time. Then we enter the main loop, which will terminate if the user indicates that he wants to quit the game.

Within the game loop, we calculate the so-called delta time. This is the time that has passed since the beginning of the last frame. We then record the time of the beginning of the current frame. The delta time and the current time are usually given in seconds. For the screen, the delta time indicates how much time has passed since it was last updated—information that is needed if we want to do frame-independent movement (which we’ll come back to in a minute).

Finally, we simply update the current screen’s state and present it to the user. The update depends on the delta time as well as the input state, hence we provide those to the screen. The presentation consists of rendering the screen’s state to the framebuffer, as well as playing back any audio the screen’s state demands (e.g., due to a shot that got fired in the last update). The presentation method might also need to know how much time has passed since it was last invoked.

When the main loop is terminated, we can clean up and release all resources and close the window.

And that is how virtually every game works at a high level. Process the user input, update the state, present the state to the user, and repeat ad infinitum (or until the user is fed up with our game).

UI applications on modern operating systems do not usually work in real time. They work with an event-based paradigm, where the operating system informs the application of input events, as well as when to render itself. This is achieved by callbacks that the application registers with the operating system on startup; these are then responsible for processing received event notifications. All this happens in the so-called UI thread—the main thread of a UI application. It is generally a good idea to return from the callbacks as fast as possible, so we would not want to implement our main loop in one of these. Instead, we host our game’s main loop in a separate thread that we’ll span when our game is firing up. This means that we have to take some precautions when we want to receive UI thread events, such as input events or window events. But those are details we’ll deal with later on when we implement our game framework for Android. Just remember that we need to synchronize the UI thread and the game’s main loop thread at certain points.

In document AQUÍ (página 32-67)

Documento similar