
- •Credits
- •Foreword
- •About the Authors
- •About the Reviewers
- •www.PacktPub.com
- •Table of Contents
- •Preface
- •Introducing SFML
- •Downloading and installation
- •A minimal example
- •A few notes on C++
- •Developing the first game
- •The Game class
- •Game loops and frames
- •Input over several frames
- •Vector algebra
- •Frame-independent movement
- •Fixed time steps
- •Other techniques related to frame rates
- •Displaying sprites on the screen
- •File paths and working directories
- •Real-time rendering
- •Adapting the code
- •Summary
- •Defining resources
- •Resources in SFML
- •Textures
- •Images
- •Fonts
- •Shaders
- •Sound buffers
- •Music
- •A typical use case
- •Graphics
- •Audio
- •Acquiring, releasing, and accessing resources
- •An automated approach
- •Finding an appropriate container
- •Loading from files
- •Accessing the textures
- •Error handling
- •Boolean return values
- •Throwing exceptions
- •Assertions
- •Generalizing the approach
- •Compatibility with sf::Music
- •A special case – sf::Shader
- •Summary
- •Entities
- •Aircraft
- •Alternative entity designs
- •Rendering the scene
- •Relative coordinates
- •SFML and transforms
- •Scene graphs
- •Scene nodes
- •Node insertion and removal
- •Making scene nodes drawable
- •Drawing entities
- •Connecting entities with resources
- •Aligning the origin
- •Scene layers
- •Updating the scene
- •One step back – absolute transforms
- •The view
- •Viewport
- •View optimizations
- •Resolution and aspect ratio
- •View scrolling
- •Zoom and rotation
- •Landscape rendering
- •SpriteNode
- •Landscape texture
- •Texture repeating
- •Composing our world
- •World initialization
- •Loading the textures
- •Building the scene
- •Update and draw
- •Integrating the Game class
- •Summary
- •Polling events
- •Window events
- •Joystick events
- •Keyboard events
- •Mouse events
- •Getting the input state in real time
- •Events and real-time input – when to use which
- •Delta movement from the mouse
- •Playing nice with your application neighborhood
- •A command-based communication system
- •Introducing commands
- •Receiver categories
- •Command execution
- •Command queues
- •Handling player input
- •Commands in a nutshell
- •Implementing the game logic
- •A general-purpose communication mechanism
- •Customizing key bindings
- •Why a player is not an entity
- •Summary
- •Defining a state
- •The state stack
- •Adding states to StateStack
- •Handling updates, input, and drawing
- •Input
- •Update
- •Draw
- •Delayed pop/push operations
- •The state context
- •Integrating the stack in the Application class
- •Navigating between states
- •Creating the game state
- •The title screen
- •Main menu
- •Pausing the game
- •The loading screen – sample
- •Progress bar
- •ParallelTask
- •Thread
- •Concurrency
- •Task implementation
- •Summary
- •The GUI hierarchy, the Java way
- •Updating the menu
- •The promised key bindings
- •Summary
- •Equipping the entities
- •Introducing hitpoints
- •Storing entity attributes in data tables
- •Displaying text
- •Creating enemies
- •Movement patterns
- •Spawning enemies
- •Adding projectiles
- •Firing bullets and missiles
- •Homing missiles
- •Picking up some goodies
- •Collision detection and response
- •Finding the collision pairs
- •Reacting to collisions
- •An outlook on optimizations
- •An interacting world
- •Cleaning everything up
- •Out of view, out of the world
- •The final update
- •Victory and defeat
- •Summary
- •Defining texture atlases
- •Adapting the game code
- •Low-level rendering
- •OpenGL and graphics cards
- •Understanding render targets
- •Texture mapping
- •Vertex arrays
- •Particle systems
- •Particles and particle types
- •Particle nodes
- •Emitter nodes
- •Affectors
- •Embedding particles in the world
- •Animated sprites
- •The Eagle has rolled!
- •Post effects and shaders
- •Fullscreen post effects
- •Shaders
- •The bloom effect
- •Summary
- •Music themes
- •Loading and playing
- •Use case – In-game themes
- •Sound effects
- •Loading, inserting, and playing
- •Removing sounds
- •Use case – GUI sounds
- •Sounds in 3D space
- •The listener
- •Attenuation factor and minimum distance
- •Positioning the listener
- •Playing spatial sounds
- •Use case – In-game sound effects
- •Summary
- •Playing multiplayer games
- •Interacting with sockets
- •Socket selectors
- •Custom protocols
- •Data transport
- •Network architectures
- •Peer-to-peer
- •Client-server architecture
- •Authoritative servers
- •Creating the structure for multiplayer
- •Working with the Server
- •Server thread
- •Server loop
- •Peers and aircraft
- •Hot Seat
- •Accepting new clients
- •Handling disconnections
- •Incoming packets
- •Studying our protocol
- •Understanding the ticks and updates
- •Synchronization issues
- •Taking a peek in the other end – the client
- •Client packets
- •Transmitting game actions via network nodes
- •The new pause state
- •Settings
- •The new Player class
- •Latency
- •Latency versus bandwidth
- •View scrolling compensation
- •Aircraft interpolation
- •Cheating prevention
- •Summary
- •Index

Company Atop the Clouds – Co-op Multiplayer
Playing multiplayer games
We've seen multiplayer games since computer games emerged—decades ago. We are used to calling friends and family to play games with us, sometimes in a
co-operative mode with common goals and other times for a competitive experience. The point is that playing with someone else is usually lots of fun!
There was a time when the Internet barely existed, or simply put, people's connections were too slow to actually have a good online experience. By then, it was very usual for games to have a local multiplayer mode. This allowed a big trend for split screen and other types of local multiplayer gameplay. Local Area Network (LAN) multiplayer was also implemented as a way to make the experience more cooperative to players, and as a result, you could actually cooperate or fight with your friends over a cable or wireless network. Unfortunately, as time passed and the Internet became more powerful, the local multiplayer modes became less and less used, and actual online multiplayer modes started to be the dish of the day. Either mode is not extinguished or anything close to that, but the game market seems to mark a tendency for online games.
For the purpose of this book, and to cover the networking field of programming, we will be not be focusing on local modes, but rather will implement a fullynetworked concept. However, fear not! We will show you a concept that game developers use a lot these days which allows you to actually have local co-op on top of a networked architecture!
Interacting with sockets
First of all, in order to go deeper in to network programming, we need to understand how computers communicate with each other. This is the technological base that everyone should know before trying to do anything with networking.
This topic is not simple by itself, but it can be approached more easily without the need to understand the deeper concepts, with the help of SFML's socket classes.
A socket is essentially a gateway for data. You can visualize it as a link between two applications. These applications are virtual, in the sense, they only matter in the network, but are not necessarily different application processes, because you can use sockets to connect an application to itself, as we do in this chapter. These sockets are the base of all networked programs; therefore, they are extremely important. As sockets are a rather complicated concept, SFML provides classes to manage them.
There are the following two main ways of communicating between multiple machines:
[ 236 ]
www.it-ebooks.info

Chapter 10
TCP
Transmission Control Protocol (TCP) is a network convention for transferring data between computers. This means that any operating system or platform that is connected to the Internet and therefore uses the Internet Protocol (IP), which TCP is
built on top of, is able to communicate in a uniform way. This is why in a networked application, we don't care who we are "talking" to, as long as the remote peer can "speak" TCP/IP, communication is possible.
For example, when you use your Internet browser, some websites will be hosted in Linux machines while others will be in Windows. Because they all use TCP/IP, it is not relevant what the operating system is, the website will be transferred to our browser and we will be able to visualize it just the same.
SFML provides two cross-platform classes for using TCP sockets: sf::TcpSocket and sf::TcpListener, which are exactly what we will use to achieve an online gameplay in this chapter. The sf::TcpSocket class initiates TCP connections, while the sf::TcpListener class listens on a certain port for an incoming connection.
Please note that TCP/IP is a high-level protocol in your operating system. When you use it, many things are being managed by the OS, which takes some weight out of your back.
The TCP protocol comes with the following features by default:
•Packet ordering: It will ensure packet ordering so you can assume that your data will arrive to the destination in the same order you sent it.
•Packet restructuring: It also provides packet restructuring facilities, completely built in. This means that if a packet is too
big, it will be split into smaller ones to make the network transfer possible while still arriving at the destination in a seamless way.
•Reliability: It is another strong aspect of this protocol. It will ensure every that packet gets to the destination, without
exceptions. If one packet fails to arrive, the protocol just stalls and is assumed to have lost its connection. However, before a packet is assumed to be impossible to transfer, it is re-sent many times in an attempt to eventually deliver it successfully.
[ 237 ]
www.it-ebooks.info

Company Atop the Clouds – Co-op Multiplayer
In order to exchange data between computers, this protocol demands that a connection or a tunnel is made first. This means that before sending or receiving data, both machines must "shake hands" and create a tunnel of information between them. This is done when one of them enters a listening state on a specific port, using sf::TcpListener, and the other uses sf::TcpSocket to connect to that port. Once that connection is successfully established, data is free to roam!
A network port is an integer number, normally ranging from 0 to
65535, which defines a "gateway" in your network where data and connections can pass through to your application's sockets. You are free to pick what port(s) your game will use for communication as long as you do the following:
• Be careful not to pick reserved ports by your operating system.
• Avoid picking ports that are commonly used by other programs, which will cause a conflict. For example, port 80 is used very often by web servers, remote desktop apps, and others. As a general rule, avoid using ports below 1024.
•Make sure both the client and the server know the same port so communication can happen.
Besides the obligation to establish a connection in order to communicate, this protocol offers advantages such as, ordered arrival of data and reliable data sending.
The first means that the order in which you send your bytes to the remote peer matters because they will get there in the same order! The latter means that the data is guaranteed to arrive at the destination. This is very good for many uses, even essential, but unfortunately, it adds an extra overhead to the network performance that some real-time games cannot cope with. Imagine you send packet A, B, and C, in order. Let's say your Internet connection isn't in its best shape and packet B keeps getting lost before arriving at the remote peer. This means that A will get to the destination, but B and C won't until B is sent successfully.
That said, we can conclude that this protocol is very adequate for file transfers and other reliable data transfers, as well as for smaller games which are less hungry for network performance. But it may be too slow for some real-time action games, which have higher speed requirements.
UDP
User Datagram Protocol (UDP) is another often used tool for network programming. Communicating data to another computer means simply pushing an array of bytes to the network, so it is very similar to TCP/IP in this matter; however, UDP has a very different set of rules.
[ 238 ]
www.it-ebooks.info

Chapter 10
The first important thing about this protocol is to know that it is connectionless. You can't establish a tunnel of reliable data. You just take your data and send it somewhere and it either gets there or not, and you are not notified of it.
This may seem strange at first. You may think "Why would I want to send data that may not even get there?" and it is normal to be suspicious about the utility of such a network protocol at first, but you'll understand how powerful it can become if made right.
The strong aspect about this protocol is that data is sent fast and there is no overhead on ensuring packet ordering or arrival. So, people usually implement a custom protocol on top of UDP that allows sending some data reliably, by sending data continuously until a confirmation of arrival is received, while other data is sent unreliably.
Another important key difference of UDP and TCP is that UDP will not split a packet into smaller parts when it exceeds the maximum limit of data size; you have to take care of that manually. While in TCP you can neglect such things, in UDP, it's important to keep packets small and efficient.
To use such sockets, SFML provides sf::UdpSocket. You just need to create an object of this type, bind to a port with the sf::UdpSocket::bind() function, and then either send data through it or check if anything was received using the
sf::UdpSocket::send() and sf::UdpSocket::receive() functions respectively.
We won't be covering UDP sockets in the chapter, but the SFML documentation and tutorials on www.sfml-dev.org should provide what you need in order to understand them in detail.
Socket selectors
Another facility that SFML provides is the sf::SocketSelector class. This one is not used in the book's game, but it is very useful and will make your life easier if you choose to use it.
This class will act as an observer for your sockets. It will hold pointers to every socket you choose to register in it. Then, you may simply call
sf::SocketSelector::wait() and it will return when one or more of the sockets receive some data. Once this happens, you handle the data somehow and call the function again. This will ensure you always are notified of packets and handle them in a simple and centralized manner.
You can call sf::SocketSelector::add() for any type of socket and listener: sf::TcpListener, sf::TcpSocket, or sf::UdpSocket.
[ 239 ]
www.it-ebooks.info