1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
|
<xml>
<head>
<title>ClanLib Tutorial: Basics</title>
</head>
<body>
<a href="introduction.html"><img src="Images/prev.gif"></a>
<a href="index.html"><img src="Images/toc.gif"></a>
<a href="design.html"><img src="Images/next.gif"></a>
<h3>THIS TUTORIAL IS OUTDATED, PLEASE DO NOT USE!</h3>
<h1>Basics</h1>
<h2>Introduction</h2>
This chapter will describe what you need to know before starting
with this tutorial. Furthermore it will define some terms which will be used
by this tutorial, some random notes about gamecoding and other stuff I'd like
to share.
<ul>
<li> <a href="#programming">Programming</a><br>
Things you need to know about coding in C/C++, threads and timers.
<li> <a href="#2dgraphics">2D Graphics</a><br>
Basic stuff about programming graphics.
<li> <a href="#sound">Sound</a><br>
What you need to know about sound and music in games.
<li> <a href="#network">Network</a><br>
Some stuff about using networksupport in games.
</ul>
<a name="programming"></a>
<h2> Programming using ClanLib </h2>
<a name="programming_oop"></a>
<h3> Object Oriented Programming </h3>
ClanLib is written in C++. It uses the object modelling pretty extensive so
good knowledge of C++ and object oriented programming is assumed in this
tutorial.
<a name="programming_multitasking"></a>
<h3> Threads, timers and other misc stuff </h3>
In a game you probably want things to happen simultaniously. You need to
play sound, show graphics, move the various monsters, cars and/or players
around all at the same time. So you need a way to divide your cpu-ticks between
these objects.<br>
The most simple way is to give each object a function called
<code>act()</code> or something similar. In this function each object can
do its stuff. When the function is done, the next object's
<code>act()</code> is called.
<br> Another, more sophisticated way, is using threads. A thread is a
(part of a) programm which can be started, suspended and stopped. You can
have more than one thread in a programm and these can (appear to be)
running simultaniously. The operating system activates a thread, runs it
for a while, suspends it, and runs the next. All the multitasking is done
by the operating system (and that's what it is supposed to do). ClanLib
has support for threads.
<p>
Your game will probably be running on lot's of different machines. You
need to make sure that the speed of the computer doesn't influence the
gameplay in your game. Your framerate (the number of screen-redraws) must
be as high as possible but the speed with which monsters attack shouldn't
be higher on a faster cpu. You'll need to time the reactiontime of these
objects. In case you're using the <code>act()</code> style of coding, you'll
need to do a timestamp check for each function that should be timed. If you're
using threads, you can let it sleep for a while.
<p>
Actually, there are a few basic algorithmes being used here. There was some
discussion on the ClanLib mailinglist on this topic. I'll discuss two
algorithmes here, both using ClanLib code. The code should be pretty
self-explainatory. If you don't understand some ClanLib functions, see the
referencemanual.<br> For games that do not need a realistic frame/second
rate, such as RPG's, a simple scheme could be used:
<pre><code>
unsigned long time_stamp;
const unsigned lont game_delay = 20; // 50 frames/second
while( game_is_running )
{
time_stamp = CL_System::get_time();
for( int i=0; i<n_objects; i++ )
object[i]->act();
for( i=0; i<n_objects; i++ )
objects[i]->draw();
while( CL_System::get_time()-time_stamp<game_delay ) CL_System::keep_alive();
}
</code></pre>
This code obviously has a few major advantages: first of all, on a fast
computer, most of the time is spend in the wait-loop. This, ofcourse is a
waste of cpu-time, instead you could have had a higher fps (which ofcourse at a
certain level doesn't make a difference anymore, but that aside).
Furthermore, all objects move at the same speed. Ok, they can move at
different pixels/frame rates but that's it. The following code improves a
lot:
<pre><code>
class Object
{
const unsigned long delay = 25; // delay == 25 millisecond ~= 40 fps
unsigned long time_stamp;
boolean may_act( unsigned long time )
{
if( time - time_stamp < delay )
return false;
time_stamp = time;
}
void act()
{
if( may_act(CL_System::get_time()) )
{
if( direction==right )
x += 2;
...
// do something more usefull here
}
}
}
</code></pre>
Each object has a certain minimal delay. It will only "act" when the
delay-time has passed since its last act(). If your computer is fast enough,
that is, can do more frames/second than you fastest object needs, this will
work fine. If you run this on a slower computer, this algorithm can be
unfair to objects. Some objects will run at their framerate, others will
skip some frames. For RPG's this is fine, so what that some character runs a
little faster sometimes than another. Also, RPG's mostly use a fixed-pixel
movement. By this I mean that a monster or hero always steps two pixels
aside between frames, never more or less.
<p>
For first person games, and some other cathegories, you will not use a
fixed-pixel movement. Rather, you'll calculate how many pixels a character
has moved in the delay between two act()'s. For this you could adapt the
above to the following algorithm:
<pre><code>
class Object
{
unsigned long time_stamp;
int pixels_per_second = 12; // move this characters at 12 pixels/second
void act()
{
float frames_per_second = 1/(CL_System::get_time() - time_stamp);
time_stamp = CL_System::get_time();
if( direction==right )
x += pixels_per_second / frames_per_second;
}
}
</code></pre>
Here the framerate is calculated and, depending on the framerate the
movement is determined. This last algortithm has another advantage. By
giving a speed in pixels/second it is possible to run this game over a
network. On every computer the characters will move at the same speed (that
is, pixel/second speed, not framerate) thus implementing a more fair game
towards slower computers. The seconds also allows you to do this, but, if a
computer cannot maintain the optimal framerate (some characters will move at
a slower fps than wished for) than this is not the same as on a faster
computer.
<a name="2dgraphics"></a>
<h2> 2D Graphics </h2>
<a name="2dgraphics_terms"></a>
<h3> Terms </h3>
Here are some terms which will be used in this tutorial.
<ul>
<li> Surface: a platform dependant representation of a (collection of) picture(s) which can directly be plotted to the screen
<li> Display: the actual screen
<li> Palette: a list of color-definitions
<li> Image: a platform independant representation of a picture
<li> Sprite: a range of pictures which describe a single object and can
be viewed in some predefined order, or (to make it worse)
a specific picture in such a range.
(for example: pictures showing a monster walking, jumping and attacking)
<li> Movie: a range of pictures which is shown chronologically
<li> Frame: a single picture out of a range of pictures which make up a movie
<li> Clipping: showing only a portion of a surface
<li> Blitting: drawing a surface on a display
</ul>
<a name="2dgraphics_aboutcolors"></a>
<h3> About colors </h3>
An image is made out of pixels. Each pixel need to have its color described
in a certain way. There are two possible ways to do this:<br><br>
<i>true-color</i>:<br>
Each pixel describes its own color. Most of the time this is done by
specifying three values: a red, a green and a blue component of its color,
pretty much the same way a monitor or tv works. The number of bits per
pixel (bpp) determines how many colors are possible. For example,
16bit is a commenly used size. Here are 6 bits used for red and 5 bits for
green and blue, although other ways are possible (5-5-5, 5-6-5, 5-5-6).<br>
<i>palette-based</i>: <br>
Each pixel refers to an index of a palette. The palette itself holds the
color-information. For example: color 1 can be red, and color 2 black.
The bits per pixel define the number of different colors that can be shown
on the display. How many colors actually are possible relies on the
way the colorinformation is stored in the palette. The palette thus makes a
'selection' out of the possible colors.<br>
A common mode in which
this is used is 8 bits per pixel. This means 2^8 (=256) different colors are
possible to be shown at the same time on the display. The way colors
are described in the palette probably allows for much more, but they cannot
be accessed due to the size of the palette. <br>
<br>
Both methods have advantages and disadvantages. True-color needs a lot of
memory, each pixel needs to provide its own colorinformation. Palette-based
displays are low on memory but have a big disadvantage: the number of
different colors is limited. Therefore, displaying images having more colors
than the palette allows will result in quality-loss. An advantage of
palette-based displays is that you can alter an image without actually
drawing a pixel. Just by changing the palette you can do fading or other
graphical effects at a possibly higher speed than with true-color displays.
True-color has its own advantages. Mixing colors for example is much easier
with true-color. You do not have to search for the resulting color in the
palette (if there is one) but can directly use it.
<a name="2dgraphics_animation"></a>
<h3> Animation </h3>
A movie or animation is shown by quickly showing pictures sequentially.
Each image in an animationsequence is called a frame. The number of
frames shown per second is called the framerate.
A movie can be shown using different pictures for each frame, or by
using a startpicture, and then for each frame calculating the differences.
This way, less data is needed for showing a picture.<br>
A sprite is a collection of pictures which show an object. Each picture
in this collection is also called a sprite. For example,
a Pacman has a few different pictures: going up/down/left/right with his
mouth open or closed. Each picture has its own index in a sprite. This way
Pacman can be animated by showing several pictures out of this sprite in
the correct order.
<a name="2dgraphics_transparency"></a>
<h3> Transparency, opacity, pixelmask's and colorkeying</h3>
Pictures are mostly stored in rectangles. This is much easier to implement
and fast to use. Only, in games you probably want to work with monsters,
walking over your screen, and they are not rectangles. So if you try
drawing them over your beautiful background, you need some way to indicate
which pixels are to be drawn and which are transparent, or you stop using
rectangles for pictures. The latter is not commonly used because it is
hard to implement, and takes up a lot of CPU-time. <br>
So, we need a way to indicate transparent pixels. There are several ways
to do this. In a palette-based image you simple pick a color out of the
palette and indicate it as the background-color. In most cases this is the
first color (0). An image-drawing function only has to check for each pixel
if it is the background color and then decide if the pixel is to be drawn.
<br>
For true-color images this is not an elegant option. If you would want to use the
same technique, you can't use that specific color in your picture. This is
not a problem with palette-based images because you simple can define the
same color twice in your palette, one to use as background color, and the
other to be shown in the picture.
Some program's still use it though, so they can use pictureformat's
which do not support transparancy. That's why you sometimes see wierd
purple background's when looking at images containing sprites. You
should then call a blitter (a drawingfunction) with an additional
argument which indicates the color which should be regarded as
transparent. This is called color-keying. This term is also used to describe
an other technique. When you blit a picture on top of another, and you only
want pixels with a certain color to be changed, you can also specify a
target colorkey. In the first case (source colorkeying), you specify in the
image-being-drawn what the transparency is, in the second case (target color-keying) what
pixels may be replaced in the existing image.
There is an other technique
which uses a second image. This image contains a number for each pixel,
indicating wether the pixel is background or not. For multi-layered games
this can be further extended to indicate on which layer this pixel belongs.
However, you can do something more with such a masquerading image. Instead
of indicating on which layer the pixel belongs, you could indicate the
'transparancy' level of that pixel. This way you can make pixels look
solid (not changed when mapped over another image), transparent (completely
replaced by the background), or semi-transparent (mixed with the
background). This technique is called alpha-channeling. A pixel with its
alpha component at 0% (a 'solid' pixel) is called opaque.
<a name="2dgraphics_buffering"></a>
<h3> Buffering </h3>
A monitor builds its display going from the top-line of the screen to the
bottom-line, scanning from left to right, reading the data from a buffer.
If the image that this buffer is holding is altered while it is being
displayed, some noise can be seen
on the screen. To prevent this from occurring the image should be changed in
the time the monitor needs to go from the bottom-right to the upperleft
corner. This time is pretty short so most programs use a technique called
double-buffering. A seperate piece of memory is used to do all drawing to.
When all drawing is ready, this memory is copied to the videocard and only
then it is shown on the screen. This way, only complete images will be shown
and the game-engine doesn't have to worry wether the monitor is busy with a
retrace or not. <br>
Often, a game has a backgroundimage which doesn't have to be altered often.
One could put this image in another buffer. Everytime the program needs to
redraw the image, one could simple copy the background-buffer into the
second buffer. All drawing occurs on this second buffer. After that it's
is copied
to the 3rd buffer, from which the actual image on the screen is drawn.
This is called
triple-buffering. This idea can ofcourse be extended to several more layers.
<a name="2dgraphics_buffering"></a>
<h3> Abbreviations </h3>
To indicate a certain pixelformat an abbreviation like RGB555 or RGBA6565
may be used. The characters "r", "g", "b" and "a" stand respectively
for "red", "green", "blue" and "alpha". The digits indicate the number of
bits reserved for the field. So, RGB656 is a 15-bit per pixel mode, with
6 bits for red, 5 for green, 6 for blue. It has no alpha-channel.
<a name="sound"></a>
<h2> Sound </h2>
<a name="sound_terms"></a>
<h3> Terms </h3>
Here I'll define some terms which will be used during this tutorial.
<ul>
<li> Sample: a sound
<li> Static sound: a sound which is complete at all times and does not
change. For example: A soundeffect.
<li> Stream: a sound which is dynamic. This
means that it does not have to be complete at the moment it
is recorded or played, but can be changed or generated realtime.
For example: a microphone-in or music.
<li> Envelope: a soundproperty like volume, panning or frequency.
</ul>
<a name="sound_static_stream"></a>
<h3> Static sounds and streams </h3>
The definitions of static sounds and streams may need some more explanation.
A static sound is a sound that is prerecorded. For example
the sound that the horn of a car makes is prerecorded and played out
when it is needed. A stream on the other hand is dynamic, it is
generated at runtime. An example of this would be the sound that the
engine of a car makes. It is dependant on the speed of the car and
therefore generated at runtime.
<h3> Panning </h3>
Panning is moving a sound from one audio-channel to another. This is
ofcourse only useful if you have a stereo soundcard.
<a name="network"></a>
<h2> Network </h2>
ClanLib supports network games. So, before we get into the details about how
ClanLib supports this, I'll first explain some basic stuff.
<h3> Sockets, ip's and other tcp/ip basics </h3>
On the Internet, or any other network using tcp/ip, each machine who
needs to be adressed has an ip-address. This is the 4-number
identification you sometimes stumble upon. As these numbers are hard to
remember, one can also use names (strings) to identify a computer. When
you supply a name (for example: dark.x.dtu.dk), this name is fed into a
domain name server (dns) which translates it into an ip.<br>
Most internet traffic is handled through sockets. You can make a
socketconnection between two ip's using a portnumber.
There are as much ports as an integer can support so that
should be plenty. Each protocol that uses a socket has its own portnumber.
Between 2 ip's there can be many socketconnections (on different ports).
ClanLib needs only one portnumber, and through that socketconnection it can
use multiple 'NetChannels'. This way you can seperate the different datastreams
used in your game. A NetChannels thus is sometiming like a socket, only inside a socket. Hmmz, this probably doesn't make it any clearer. Skip that last remark,
forget all about sockets, and just use ClanLib's network support.
<h3> Servers and clients </h3>
To communicate between computers you can use a client-client model, or a
server-client model. In a client-client model all computers participating are
equal. For most games, this isn't a good idea because a computer could easily
cheat or read information which is not meant for itself. A server-client model
is used in most cases. Here, all clients send there information to the server,
and the server sends each client the information they need. This is a more
secure way. ClanLib uses this model. Because a computer can easily be
both a server and a client this is the most used model anyway.
<p>
<a href="introduction.html"><img src="Images/prev.gif"></a>
<a href="index.html"><img src="Images/toc.gif"></a>
<a href="design.html"><img src="Images/next.gif"></a>
</body>
</xml>
|