-
Notifications
You must be signed in to change notification settings - Fork 7
Multimedia
This article deals with input and output systems, their connection to the main program and the game loop. In particular, we will explore:
- Cameras and views
- Scrolling
- Animation
A common pattern in interactive applications is that the same entity that consumes or presents output also produces input. This may obviously true for players: they are the ultimate consumers and producers. With this abstraction in mind AI-controlled players can also been as pairs of consumer/producer: they take the game state, "show" it (to an intelligent agent/function), and produce a set of actions pertaining to some of the players.
In the game programming literature, this abstaction is known as a view. Other names for it are reactive value 1.
Consuming the output and producing a new input may not be synchronous actions. Network players, for instance, can be abstracted as views: the game state (or a game update) is sent via the network, and input actions are transmited back to the server. The player may be receiving updates every few miliseconds (if latency is low) while only firing a few times per second, max.
Using views also helps abstract from polling vs callbacks, rendering asynchronously, having multiple cameras for different players, and even using widget systems.
Example of a view in a monadic game. Example of views in Arrowized FRP. Example of views in Keera Hails.
Games often present scenes that do not fit on the screen. Mario Bros. is such a game. Counter strike is such a game. Any racing game is also of this kind.
In arcade 2D-based games, one can easily simulate this effect by moving all other elements (oponents, background, etc), when the player "moves" forward. The player moving forward, then, is just an illusion. But, as your logic and physics become more complex, and you add more than one player, this workaround becomes harder to implement.
While elements are shown in screen coordinates, the internal processing function should work with game, or world coordinates.
What's actually going on in these games is that you have a perspective, a point of view, a camera pointed to the game world that only shows you a part of it, from a specific angle. What's more is that camera is a portal also for the input: what looks like middle of the screen in screen coordinates may not represent the center of the world.
It's easy to see that, given a function f
that transforms game world
coordinates into screen coordinates, we have:
gameForUser = capScene screenSize $ transformState f gameState
inputFromUser = transformInput f<sup>-1</sup> screenInput
IN 3D... Game Engine Architecture
In 2D... Whatever
PLACE FOR ANOTHER EXAMPLE
Heads-on displays are a general name for those information panels shown on top of the game with additional information.
PLACE FOR AN IMAGE
What's interesting about them is that:
- They can be enabled or disabled.
- They may be shown or not depending on the game state.
- They may be interactive (handle input apart from presenting output).
The last point is perhaps the most crucial one: while it is easy to display something in one area of the screen, we also need to:
- Transform screen coordinates into coordinates local for the displayed elements.
- Translate raw input events into more meaningful event descriptions.
For example, given an input event (eg. mouse click at position (x,y)), we need to determine wether it lies on the game area or a panel, and then translate the screen coordinates into local coordinates for that element. If it's the game area, all we need is to apply the inverse camera function. If the panel, we may just need to rebase them based on the position of the panel on the screen.
The general transformation is as follows:
PLACE FOR THE MATRIX
What we are describing here is true both for HUDs and any other permanent or temporary on-screen element that does not use the game camera as the main game area.
PLACE FOR AN EXAMPLE
Note that, after the transformation of the event coordinates, we still need to transform the low-level input event (click, etc.) into an declarative depiction of what happened (fire).
You can see this intermediate layer as a simple widget system, and may even consider creating an abstraction for containers and alignments that facilitates adapting to different screen sizes and screen rotations during gameplay. I recommend that you keep it as simple as you can, and as abstract as you can.
PLACE FOR AN EXAMPLE OF CONTAINERS
PLACE FOR AN EXAMPLE OF ALIGNMENT
As we just saw in the chapter about cameras, many games present a portal to a world larger than it fits on the screen. Backgrounds can lighten an otherwise dull screen, but what really changes game appearance are moving backgrounds and a perception of depth.
First, we will explore backgrounds without depth (static and moving). Then we will explore backgrounds with depth (parallax). In the next section we will explore depth in a more general way (even in 2D games, often termed 2.5 as opposed to full 3D).
Implementing static backgrounds could not be more trivial. A static, uninteractive background can be presented both as an adhoc layer in the render (see first example) or integrated as one more visual element. What's important in the second case is that, unlike other visual elements, a static background is not affected by the game camera, but it is affected by transformations that have to do with laying different elements out on the screen.
A PICTURE IS WORTH A THOUSAND WORDS
PLACE FOR AN EXAMPLE
In some cases, the game world is just slightly larger than the screen, but still limited in size. The background is therefore also larger than the screen, but finite. Presenting this kind of world is relatively simple, and it only requires that we crop part of it to the size of the screen. We can generalise this approach easily by using transformation/camera matrices applied to background coordinates.
What's important in this case is to make sure that players can never move out of the world boundaries, or there will be screen areas with no background.
PLACE FOR AN EXAMPLE
Some games gave very large or even unlimited world sizes. In such cases, backgrounds tend to be designed so that each side matches the opposite perfectly, like in a rolling paper.
PLACE FOR AN ANIMATION
This was a common trick in animation, and you can see it often in older TV series:
PLACE FOR AN ANIMATION
There are several ways of implementing this. One way is to crop the background in two, and present one part and then the other:
PLACE FOR AN EXAMPLE
Depending on the underlying framework, you may get away without cropping: you can also paint the world twice, and then paint the rest of the scene relative to its position with respect to the background.
While I personally tend to favour the first approach, whether cropping or painting twice is performance-wise pretty much depends on the platform and the underlying graphics layer (some do not let you paint out of screen area, others easily facilitate rebasing the scene relative to a background).
Games can achieve a more appealing sense of perception by adding depth. Even if the action takes place in 2D, a common effect is to add several background elements moving at different speeds as characters move along the world (so as to make it look like some elements, the ones moving faster, are closer than others, moving slower).
PLACE FOR AN IMAGE
While this may seem like a relatively new trick because of its common presence on the web nowadays, there are old games around there that used this effect already:
PLACE FOR AN IMAGE
Implementing parallax, so as long as the background layers are all presented behind all the game action, is just as trivial as presenting one background, but having one camera transformation matrix for each background.
PLACE FOR AN EXAMPLE
Even 2D games can achieve a sense of depth by introducing layers. Layers can be presented without any modification to make them look closer, or with a camera transformation.
PLACE FOR TWO IMAGES
Implementing these kinds of transformations is relatively trivial. First, your game elements need to have a third dimension. Unlike the x and y dimensions, which may have fine precision approximating the continuous, the z dimension can easily be a integer if all you want is to layer your scene. Different layers can then be presented to users one by one.
Layering your scene is actually a form of 3D with an integer z coordinate, and as such it introduces some of the casuistics of 3D:
-
If I click on the game area, which element of which layer am I trying to interact with?
-
If interactive layers are presented using parallax effects, how do I adapt the input?
-
If interactive layers are presented using parallax effects, how does that affect the physics?
TO BE COMPLETED
TO BE COMPLETED. Readers will mainly be refered to books and other material.
- Keera Hails http://github.com/keerastudios/keera-hails