Ok heres part 2! And Ill guess Ill demonstrate some of that magic of arrays in part 3...
I dont know how I could forget to mention "arrays" since its my favorite thing ever!
An array is a collection of variables, if you type "int a,b;" you create 2 variables,
they can have any position in the memory and can be far apart from eachother in terms of adresses.
The beauty of arrays is that all the memory reserved will be right next to one and another
in terms of adresses, why would that matter? I will demonstrate the miraculous nearly magical
possibilitys later.
To create an array declare a data format and a name of your choise, just like a normal variable,
but follow it with the square parentesis symbols []. Like this: "int lol[2];".
That will create an array with 2 "elements", an element is like a single variable, so this will
create 2 integer variables that lies besides one and another in the RAM memory.
To access them you type the number of the element you wish to use, and then count of the elements
start from 0, when you create 2 elements you type 2 for the number you wish to create,
but once its created then when you use it you need to start counting from 0, so to access element
2 you type "lol[1]=5;", that will store the value 5 in the second element.
Now lets get some graphics on the screen finally!
**************************************************************************************************
#include "iostream"
#include "stdlib.h"
#include "SDL/SDL.h"
using namespace std;
int main(){
SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER);
SDL_Surface* dis=SDL_SetVideoMode(200,200,24,SDL_SWSURFACE|SDL_NOFRAME);
SDL_Event game;
SDL_Rect temp;
Uint8* key;
int quit=0;
Uint8 r=255,g=255,b=255;
int currentTime,oldTime,framerate = 10;
int xp=80,yp=80,tv1,tv2,tv3;
int tv4;
int change_color=0,change_color_pressed=0;
while (quit==0){
while (SDL_PollEvent(&game)){}
key=SDL_GetKeyState(NULL);
if(key[sDLK_ESCAPE]){quit=1;}
if(key[sDLK_a]){change_color=1;}else{change_color_pressed=0;}
if(key[sDLK_UP]){yp-=1;}
if(key[sDLK_DOWN]){yp+=1;}
if(key[sDLK_LEFT]){xp-=1;}
if(key[sDLK_RIGHT]){xp+=1;}
if(xp<0){xp=0;}
if(xp>200-40){xp=200-40;}
if(yp<0){yp=0;}
if(yp>200-40){yp=200-40;}
tv1=currentTime;
tv2=oldTime;
tv3=(tv1*tv2)/90909;
if(change_color==1&&change_color_pressed==0){
srand(tv1);
r=rand()%255;
srand(tv2);
g=rand()%255;
srand(tv3);
b=rand()%255;
cout<<"R = "<<(int)r<<", G = "<<(int)g<<", B = "<<(int)b<<endl;
change_color_pressed=1;}change_color=0;
temp.x=0;
temp.y=0;
temp.w=200;
temp.h=200;
SDL_FillRect(dis,&temp,SDL_MapRGB(dis->format,0,0,0));// CLEAN THE SCREEN.
temp.x=xp;
temp.y=yp;
temp.w=40;
temp.h=40;
SDL_FillRect(dis,&temp,SDL_MapRGB(dis->format,r,g, B) );
SDL_Flip(dis);
currentTime=SDL_GetTicks();
if(currentTime-oldTime<framerate)
{SDL_Delay(framerate-(currentTime-oldTime));}
oldTime=SDL_GetTicks();}
SDL_Quit();
return 0;
}
**********************************************************************************************
Here we have a lot of new stuff! Lets start from the top:
First we include 2 new librarys, stdlib is another standard C++ library. Standard C++ librarys
are always available with C++ compilers, so you dont need to give a path. If we look below we
find a library called SDL, short for Simple Direct Media Layer, its an open source library
thats free for use, you can find more info and tutorials and references on their webpage
http://www.libsdl.org/
Or google for questions to problems or anything that you might have, theres an abundance of
information available everywere of this very common library.
We include stdlib because of the functions for generating random numbers, srand() and rand()
both can be found in there.
The line "SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER);" is were we activate different parts of SDL,
there are many different parts and you might not want to activate them all for the specific
project you do. We will use SDL_GetTicks() wich is part of the TIMER function and the drawing
functions are ofcourse part of the VIDEO function.
Next we create a window, "SDL_Surface* dis=SDL_SetVideoMode(200,200,24,SDL_SWSURFACE|SDL_NOFRAME);".
SDL_Surface is a data format, its more complex then a int for example, but dont worry about that now.
Theres also a "*", this is a symbol used for making pointers, Im not an expert on pointers but I will
demonstrate them later.
So what we do is create a variable, but its not a normal variable its a pointer, but you dont need to
worry about this cos you dont need to know the details in order to be able to make use of it.
And then we assign something to it at the same time as we create it, we assign a function, and by
assigning a function you automatically activate it, this function will create the window accordingly
to the specifications given in the parameter section, 200 pixels wide, 200 pixels high, 24bit color,
SWSURFACE means it will be processed by CPU alone, HWSURFACE will use the GPU, but I dont know
to what extent... It might say somewere on the webpage or there might be an explenation to find
by googling, obviously you dont need to know the specific details of how everything works in order
to be able to make use of it. NOFRAME means that the window wont have a boarder, wich I personally
find cool and thats the only reason its there... Its actually better to have a boarder that you
can grab with mouse to move the window around... Anyway, these last 2 parameters are whats called
"flags", theyre seperated by a | instead of commas, I suspect it works in a single parameter slot
and that the function then reads the letters, but mayby Im completly wrong, all you need to know
to be able to make use of it is that you can add as many flags as you wish and wichever you want,
just seperate them with | symbols instead of commas.
Next comes another SDL specific data format, SDL_Event, we create a variable of this format that
will be used to read input from the keyboard. SDL_Rect is a good demonstration of more complex
data format as you will se later in the code. We will use the SDL_Rect variable to store
position and width/height of a drawing function.
Next up we have something I cant explain, "Uint8", U stands for unsigned wich defines the scale
of the number range that can be stored in the variable, as you can see here:
http://www.cplusplus.com/doc/tutorial/variables/
The 8 I would assume means that a special integer reserving 8 bytes of memory instead of normal 4.
Not all data formats are listed on C++ webpage. This "key" pointer variable will be used to store
the code that keyboard sends.
The other variables created should need no further explenation here.
Lets instead move on to some action!
Lets start with "while (quit==0){", this is the game loop so to say, if you exit this loop the
program will end.
Next we read the signal that comes from keyboard, "while (SDL_PollEvent(&game)){}" will read
the event queue, when you press keys on the keyboard they will end up in the queue, and here
we read that queue.
I think I might be able to explain what a pointer is now, you can access a pointer in two ways,
access directly or "by reference", you use pointers to store adressess, and if you access the
pointer by reference you can read or write the memory not in the pointer variable but in the
variable whos address is stored in the pointer variable.
So if we look at the line "key=SDL_GetKeyState(NULL);", remember that "key" is a pointer,
what we do here is activate a function, this function will update an array with the status
of the keyboard, if you press the "K" key the array element representing that key will get
assigned the value 1, and all keys that arent pressed will recieve the value 0.
Below we look at the array elements of the keys we wich to use in the program, I dont know
how the key pointer works here, or how the elements are found by letters, but again it is
obviously not necesary to understand exactly how this works in order to make use of it.
The "if" function will process the commands in its body if the definition in its parameter
section is TRUE, and "1" is used to symbolise TRUE aswell, so all array elements with value 1
will be processed.
Here we can also see something new thats a part of the "if" function, "else".
If the definition of the "if" parameter section is FALSE, the commands in the body of the "else"
will be processed, if the "if" parameter section is TRUE, the commands in the body of the "else"
will simply be ignored. The "else" must follow directly after the body of the "if" function
it belongs to.
If a key remains pressed the value of the array element will be 1 every time we read it, that means
if we use it to do something like move left on the screen, we will continue to move left until we
release the key. This behaviour isnt always wanted, one way of dealing with it is to use an "if"
function that checks 2 variables, were one will yield a FALSE value after the "if" function has
been processed once, this will keep the "if" function from being processed every frame, and then
reset both variables as key is released allowing for the process to be repeated again.
Lets look at the randomizer functions, "srand(tv1);" is used to establish a reference or something,
it needs to be set before using rand(). We can enter any value in srand() parameter section.
Then "r=rand()%255;" is used to give the "r" variable a random value between 0 and 255.
If we were to use rand() immidiatly again for the "g" variable, it would end up generating the
exact same value, so we need to once again set the reference in srand() to a different value.
Now lets look at "temp.x=0;", "temp" is a variable with a complex data format, this particular
format can hold several values, it has what is called "member variables" or something like that.
These individual members are accessible by entering their respective names after the main variables
name seperated by a dot. In the line "SDL_FillRect(dis,&temp,SDL_MapRGB(dis->format,0,0,0));" we use
the "temp" variable in the parameter section of the function, the function will use the adress of
the variable to automatically get all the data it wants from the member variables, so it has
similiarity to both arrays and pointers. The "&" symbol is used to signal the use of adress of a
variable rather then the value stored inside.
The SDL_FillRect() function will draw a square on the screen, the first parameter is a surface,
you can use as many surfaces as you like and draw individually to all of them and draw from one
surface to another, but here we use one single surface to cover the screen. First we pass the
surface as a parameter, then the "temp" variable that we have previously update with coordinates
describing how big rectangle we wish to draw and were it should be placed on the surface.
The temp.x defines the starting place, temp.w defines how long it stretches to the right of that
position. The coordinates 0,0 is lower left corner of the screen, since we have a window of size
200,200 that will also be the coordinates for the top right corner of the screen.
Now we may use different parts of the surface then 0-200, think of the surface as an endless
canvas, of wich we then overlay the screen window wich is 200 pixels wide and high. That means
that if we draw the canvas at -50 in X dimension the game world so to say will be displayed
50 pixels to the left, if you would run fowards to the right the screen would scroll along,
it means that an object with position -40 in X dimension would be visible on screen 10 pixels
to the right of the left edge initially, but as screen moved fowards the object would
disapear to the left off the screen, even though the coordinates of the object remained the
same, because we move the coordinates of the camera so to say, and we start drawing from
different position, different coordinates of the game world.
After the drawing function you see this "// CLEAN THE SCREEN.", a double slash "//" is
a commentator operator, the compiler will ignore all text that follows for the rest of that line.
You should use this function to comment on the source code you write, becasue code can become
very complex and very long, its therefor easy to forget what everything does and how things
may work, so remember to make good commenting to describe things as well as possible,
doing so will save you a lot of time having to study code and figure out once again what it is
and how it works.
Clean the screen, what I do there is fill the screen with black color, if I hadnt done that
the graphics memory would remain the old values, the values only change when you update them.
So if a caracter moves along the screen it will leave a trail behind it, once you have graphics
filling the entire screen and updating every frame it will naturally be prevented, but here and
now we dont want to fill the screen with "trails".
Next we draw our "caracter", we use the position of "xp" and "yp" variables, those values are
affected by the keyboard.
Now we have drawn graphics on the surface, now its time to send that data to the screen,
we do this with "SDL_Flip(dis);", it will update the GPU buffert that is used to fill the pixels
on the screen with color according to the values stored in that buffert. We pass the surface
we want to send as a parameter.
Next we have my way of limiting the framerate, without a limiter the program would process as
many frames as the CPU would be able to per second. If a caracter move 1 pixel per frame, and
if the CPU could process 1000 frames per second that means the caracter would move 1000 pixels
per second. By measuring the time we can use a delay function to limit the framerate, likewise
its good practise to make "framerate independant" physics, that means instead of moving a
caracter 1 pixel per frame, you move it how many pixels you want it to move per second but
multiply it with the time value you make. How do you create such a time value?
With SDL_GetTicks() you will recieve a value that starts counting at the time you initialise
the SDL_TIMER function. This value is counted in 1000 per second. So if you measure the time
between frames, you can calculate the framerate and create a value to multiply the physics with.
For example, if we use 2 variables to get the time between frames, we can subtract the old
time value from the new, then we might get something like the value 50. If we then divide this
by 1000 we end up with what is how many percentage of 100% we wish to multiply the physics with.
If framerate is to slow the value might become more then 100%. Since 1.0 would represent 100%,
0.5 represents 50%. I have a feeling Im not explaining this very well, but you will find a way
to achieve it thats comfortable to you.
Next we have SDL_Delay(), very simple, pass the time you want as the parameter, remember 1000
is 1 second. Then the program will essentialy freeze until that time have passed.
Freeze ofcourse means idle as in not using the full CPU capacity it would otherwise if we had not
limited the framerate.
And lastly we have the function SDL_Quit(), this cleans away all the memory SDL reserves when
you activate it.
And this is compiled by typing "g++ -o game1 game1.cpp -lSDL", the -l stands for link and is
needed for some librarys. I think this has to do with dll files, dynamically linked library,
but I may be wrong... However if you were to compile this program for Windows for example,
you would need a sdl.dll file in the same folder as the .exe file to be able to run it,
if you install SDL on Linux I dont think you need to worry about this, the OS handles it
automatically I think.
And to run the file type "./game1" or click on it in the file browser!
game1.cpp.zip