PDA

View Full Version : Game Developement



Realeg
01-03-2015, 10:44 AM
Hi everyone! My name is Alex and i'm 17 years old. I'm in 11th grade at highschool with the specialisation in mathematics and informatics. Here, we study Turbo Pascal as programming language. I know most of the pascal programming language till the backtracking and graph theory. I wonder, how could i make games in Turbo Pascal using graphics? I tried to use the "graph unit" integrated with pascal, but i can't use the keyboard in the graphic window.
So, i'm here to ask you, what i need to start create a graphic game using Pascal language?

Anton
01-03-2015, 08:36 PM
Hello Alex!

I was wondering the same thing maybe about 10 years ago..
You can use the keyboard in graphic mode. But you can't use the "console" functionality provided by ReadLn/WriteLn; You can do the following: write a function to handle what will happen if the player presses some key. Also you make function to render your game objects to the screen. Then you cycle both functions until some event occur (like pressing Escape) that will exit the game cycle.

This is just brief pseudo code, i dont have Turbo Pascal to test it.

var
C: Char;
GameRunning: Boolean;

Function HandleKeypress(Key: Char): Boolean;
Begin
Case Key of
#27: GameRunning := False; //Pressing Escape will cause the game cycle to break;
'Z': ;//here you write code to handle what happen if the player presses "Z" button,
//etc
End;

Result := True; //Return error(success) code
End;

Function DrawGameScene: Boolean;
Begin
//here you draw all your game objects using graph unit functions

Result := True;
End;

Begin
InitGraph(...) //you initialize graphics here
GameRunning:= True;

Repeat
DrawGameScene;

If KeyPressed then Begin
C := ReadKey;
HandleKeyPress( C );
End;
Until GameRunning = False;
End.


I think the last Turbo Pascal is released in the mid 90-ties so it is about 20 years from now. And it can compile only for 16bit DOS (correct me if Im wrong).

But if your wish to use is Pascal, not concretely Turbo Pascal, you definitely have to make a search for FreePascal / Lazarus. And you have to learn another graphical library, because I doubt Graph will do the work for you. For example some 2d library based on OpenGL.

Realeg
02-03-2015, 10:04 AM
Yes, we still use Turbo Pascal as a compiler at our informatics class. I took a peek into this forum and saw all the games released(i never knew Pascal has such a power to render 3D graphics). I downloaded Free Pascal as a compiler and i'm thinking using the SDL library, but i'm not sure which one, because i saw tehre are SDL 1.2 and SDL 2.0. I'm waiting for your suggestion.

Super Vegeta
02-03-2015, 12:16 PM
I've been thinking about writing some kind of a tutorial on SDL or programming in general for some time. If you'd be interested and willing to wait a bit, I might give it a try.

As for SDL, 2.0 is still quite young so there may be some bugs or compatibility issues, but considering that 1.2 is officially EOL and no work will be done on it, I'd say that 2.0 is the safer bet. The workflow doesn't differ much, and the myriad of new features make way more fun to work with.

JC_
02-03-2015, 11:06 PM
SDL might work, but much better choice is ZenGL library. Is very easy to use etc.

Of course it has also some drawbacks like incomplete documentation but overall there is nothing better.

Realeg
08-03-2015, 03:50 PM
Hello!
I've been learning the SDL2 library for graphic development. And here is where i got stuck. I need to load a texture as a *.bmp file from my computer, and the procedure looks like this: "texture:=IMG_LOADTEXTURE(<render>,<path to file>);"
The path to the file is for me the big problem. I don't know how to make the application to load a texture file from the folder where the .exe is. For example, if the aplication is in C:\X-FOLDER\Y-FOLDER, how can i load a texture from Y-FOLDER without writing the whole path?To write instead of 'C:\X-FOLDER\Y-FOLDER\file.bmp\, just 'file.bmp'?

SilverWarior
08-03-2015, 06:03 PM
The path to the file is for me the big problem. I don't know how to make the application to load a texture file from the folder where the .exe is. For example, if the aplication is in C:\X-FOLDER\Y-FOLDER, how can i load a texture from Y-FOLDER without writing the whole path?To write instead of 'C:\X-FOLDER\Y-FOLDER\file.bmp\, just 'file.bmp'?

You can extract the executable path from the FileName of your executable file using:


MyAppPath := ExtractFilePath(Application.ExeName);

Also I strongly recomend you don't store your resource files in your application folder but instead create seperate subfolders for this like:
MyAppPath\Data\Images
MyAppPath\Data\Sounds
MyAppPath\Data\Videos
MyAppDataLevels
and so on.
This way you nicely organize your files so you can quickly find specific file manually when you need it.

When dealing with paths it is also good to make use of IncludeTrailingPathDelimiter method to make sure that all your paths are proprly ended with TrailingPathDelimiter character so you don't need to worry by yourself wheter specific API function returns path with or without the TrailingPathDelimiter

Realeg
08-03-2015, 06:58 PM
So, let's see if i got it. Using that instruction that you gave me, i should be able to get the location of my file. It should be an ansistring right?
And placing it instead of this <path name>, i should get something like this <path name>+'\data\file.bmp' right?
Sorry if i get it bad, i just figured it out how much lack of knowledge i have in this think.

SilverWarior
09-03-2015, 07:08 AM
Method ExtractFilePath does include the TrailingPathDelimiter character so you don't need to add it in your string. This means that instead of


<path name>+'\data\file.bmp'

you would use


<path name>+'data\file.bmp'

As for the string type returned it is same string type that is the default string type of your development environment (AnsiString in Delphi 7, Unicode string in Delphi 2009 and newer, not sure for FPC/Lazarus thou).

As for you being sorry about your lack of knowledge. Don't be. We all have been in your position once but we learned and so will you.
Just don't be afraid to ask. The main purpose of this community is to help each other.

Realeg
09-03-2015, 02:16 PM
So this is the code i just write about *.exe file manipulation:


program TextureLoad;


uses crt,SDL2,SDL2_image,SysUtils;


type R=array[1..100] of pSDL_Renderer;
T=array[1..100] of pSDL_Texture;


var window:pSDL_Window; Render:R; Texture:T; i:byte;


procedure Graphic_Initialisation;
begin
clrscr;
if SDL_INIT(SDL_INIT_VIDEO)<0 then
begin
writeln('The graphic mode could not be initializated');
writeln('The application will now exit');
exit;
end
else
window:=SDL_CreateWindow('Texture Window',50,50,600,480,SDL_WINDOW_SHOWN);
end;


Procedure Load_Texture(ExePath:AnsiString);
begin
Texture[1]:=IMG_LOADTEXTURE(Render[1],ExePath+'data\space_armada1.bmp');
Texture[2]:=IMG_LOADTEXTURE(Render[2],ExePath+'data\space_armada2.bmp');
Texture[3]:=IMG_LOADTEXTURE(Rrender[3],ExePath+'data\space_armada3.bmp');
end;




Procedure ComposerFrame;
var Path:AnsiString;
begin
Path:=ExtractPathFile('Texture.exe');
Load_Texture(Path);
end;



procedure Graphic_Destruction;
begin
SDL_DestroyWindow(window);
SDL_QUIT;
end;


Begin
Graphic_Initialisation;
SDL_Delay(2000);
ComposerFrame;
Graphic_Destruction;
end.


The error i recive is this: Incompatible type for arg no. 2: Got "AnsiString", expected "PChar"

Realeg
09-03-2015, 02:28 PM
This is the code i write to manipulate the *.exe file path extractor:



program TextureLoad;


uses crt,SDL2,SDL2_image,SysUtils;


type R=array[1..100] of pSDL_Renderer;
T=array[1..100] of pSDL_Texture;


var window:pSDL_Window; Render:R; Texture:T; i:byte;


procedure Graphic_Initialisation;
begin
clrscr;
if SDL_INIT(SDL_INIT_VIDEO)<0 then
begin
writeln('The graphic mode could not be initializated');
writeln('The application will now exit');
exit;
end
else
window:=SDL_CreateWindow('Texture Window',50,50,600,480,SDL_WINDOW_SHOWN);
end;


Procedure Load_Texture(ExePath:AnsiString);
begin
T[1]:=IMG_LOADTEXTURE(R[1],ExePath+'data\space_armada1.bmp');
T[2]:=IMG_LOADTEXTURE(R[2],ExePath+'data\space_armada2.bmp');
T[3]:=IMG_LOADTEXTURE(R[3],ExePath+'data\space_armada3.bmp');
end;




Procedure ComposerFrame;
var Path:AnsiString;
begin
Path:=ExtractPathFile('Texture.exe');
Load_Texture(Path);
end;



procedure Graphic_Destruction;
begin
SDL_DestroyWindow(window);
SDL_QUIT;
end;


Begin
Graphic_Initialisation;
SDL_Delay(2000);
ComposerFrame;
Graphic_Destruction;
end.

And the error is this: Arg no 2: AnsiString found but expected PChar.
How do i solve it? Is there some kind of function that convert a AnsiString to a PChar? Or something like this?

Realeg
11-03-2015, 09:15 PM
This is the code i just write to handle the files. The error i recive is that the path variable gets an AnsiString and the parameter for the IMG_LoadTexture is a pChar. How do i convert them?




program grafica;


uses SysUtils,crt,SDL2,SDL2_image;


type Textures=array[1..100] of pSDL_Texture;


var Window:pSDL_Window; var Tex:Textures; Ren:pSDL_Renderer;


procedure Graphic_Initialisation(var Window:pSDL_Window);
begin
if SDL_INIT(SDL_INIT_VIDEO)<0 then
writeln('An error ocurred, the program will now quit')
else
begin
writeln('Graphic mode succesfully initialisated');
Window:=SDL_CreateWindow('Test',50,50,600,400,SDL_ WINDOW_SHOWN);
end;
end;


procedure Texture_Loading;
var path:pChar;
begin
Ren:=SDL_CreateRenderer(window,-1,0);
path:=ExtractFilePath('grafica.exe');
Tex[1]:=IMG_LoadTexture(Ren,path+'\monster.bmp');
Tex[2]:=IMG_LoadTexture(Ren,path+'\monster1.bmp');;
end;


procedure Graphic_Composer;
var i:byte;
begin
Texture_Loading;
for i:=1 to 100 do
begin
if (i mod 2)=1 then
begin
SDL_RenderCopy(Ren,Tex[1],nil,nil);
SDL_RenderPresent(Ren);
SDL_DELAY(50);
end
else
begin
SDL_RenderCopy(Ren,Tex[2],nil,nil);
SDL_RenderPresent(Ren);
SDL_Delay(50);
end;
end;
end;


procedure Graphic_Destroy;
var i:byte;
begin
for i:=1 to 100 do
SDL_DestroyTexture(Tex[i]);
SDL_DestroyRenderer(Ren);
SDL_DestroyWindow(Window);
SDL_QUIT;
end;




begin
clrscr;
Graphic_Initialisation(Window);
Graphic_Composer;
Graphic_Destroy;
end.

SilverWarior
11-03-2015, 10:45 PM
This is the code i just write to handle the files. The error i recive is that the path variable gets an AnsiString and the parameter for the IMG_LoadTexture is a pChar. How do i convert them?

Wrap the code defining path into PChar method:



Tex[1]:=IMG_LoadTexture(PChar(Ren,path+'\monster.bmp'));

Realeg
12-03-2015, 03:06 PM
Tried your solution, it dosen't work...

pitfiend
13-03-2015, 01:10 AM
program grafica;

uses SysUtils,crt,SDL2,SDL2_image;

type Textures=array[1..100] of pSDL_Texture;

var Window:pSDL_Window; var Tex:Textures; Ren:pSDL_Renderer;

procedure Graphic_Initialisation(var Window:pSDL_Window);
begin
if SDL_INIT(SDL_INIT_VIDEO)<0 then
writeln('An error ocurred, the program will now quit')
else
begin
writeln('Graphic mode succesfully initialisated');
Window:=SDL_CreateWindow('Test',50,50,600,400,SDL_ WINDOW_SHOWN);
end;
end;

procedure Texture_Loading;
var path:pChar;
begin
Ren:=SDL_CreateRenderer(window,-1,0);
path:=ExtractFilePath('grafica.exe');
Tex[1]:=IMG_LoadTexture(Ren,path+'\monster.bmp');
Tex[2]:=IMG_LoadTexture(Ren,path+'\monster1.bmp');;
end;

procedure Graphic_Composer;
var i:byte;
begin
Texture_Loading;
for i:=1 to 100 do
begin
if (i mod 2)=1 then
begin
SDL_RenderCopy(Ren,Tex[1],nil,nil);
SDL_RenderPresent(Ren);
SDL_DELAY(50);
end
else
begin
SDL_RenderCopy(Ren,Tex[2],nil,nil);
SDL_RenderPresent(Ren);
SDL_Delay(50);
end;
end;
end;

procedure Graphic_Destroy;
var i:byte;
begin
for i:=1 to 100 do
SDL_DestroyTexture(Tex[i]);
SDL_DestroyRenderer(Ren);
SDL_DestroyWindow(Window);
SDL_QUIT;
end;

begin
clrscr;
Graphic_Initialisation(Window);
Graphic_Composer;
Graphic_Destroy;
end.


I think you must validate that ExtractFilePath didn't gets you a string path with '\' at the end. That could produce unexpected results as you are having.

User137
13-03-2015, 04:33 AM
I wonder, how could i make games in Turbo Pascal using graphics? I tried to use the "graph unit" integrated with pascal, but i can't use the keyboard in the graphic window.
So, i'm here to ask you, what i need to start create a graphic game using Pascal language?
I would recommend installing Lazarus for that kind of stuff. Turbo pascal is only for learning basics, starting to use graphics on it won't lead anywhere, and gives you too much information you don't need. No modern time games can be made with Turbo Pascal.

phibermon
13-03-2015, 02:13 PM
What Silverwarrior suggested :

Tex[1]:=IMG_LoadTexture(PChar(Ren,path+'\monster.bmp'));

should read :

Tex[1]:=IMG_LoadTexture(Ren,PChar(path+'\monster.bmp'));

SilverWarior
13-03-2015, 04:13 PM
What Silverwarrior suggested :

Tex[1]:=IMG_LoadTexture(PChar(Ren,path+'\monster.bmp'));

should read :

Tex[1]:=IMG_LoadTexture(Ren,PChar(path+'\monster.bmp'));

You are absolutely correct. How could I have made such trivial mistake :-[

Realeg
13-03-2015, 08:29 PM
I've tried the the second solution from the very beginning. The error is now that i got a short string instead of pChar. I've tried this solution, but it had the same result.


path:=pChar(ExtractFilePath('grafica.exe'));

EDIT: The fact is that i just realise that by writing the upper instruction, the path variable is empty. Only if you write the whole path it is kept in the variable, the problem i want to avoid. In the problem with the short-string to pChar, i solved, the problem is this thing now. Getting the file path, without writing the whole path

If i write


path:=pChar(ExtractFilePath('C:\Pascal\Projects\gr afica.exe');

the variable will keep C:\Pascal\Projects\, otherwise it will be empty.

SilverWarior
13-03-2015, 09:34 PM
When you use


ExtractFilePath('grafica.exe');

your program tires to search for file named grafica.exe in your current directory also know as working directory which may not be the folder from which your application was launched and then extract its path. If the file can't be found in current directoy you will get empty path as a result.

So extract your program path using


MyAppPath := ExtractFilePath(Application.ExeName);

as I have suggested to you in the first place.

Now you already know what ExtractFilePath method does right.
And Application.ExeName property returns the full filename of your program executable from which you can extract path to the folder in which your executable resides.

Realeg
17-03-2015, 03:11 PM
Ok, it seems that my brain let me down. I simply can't figure out how to use the instruction. Can you give a concerete example if i need to get the path of file 'graphics.exe'?

SilverWarior
17-03-2015, 07:42 PM
Is graphics.exe the executable of your application?

Realeg
17-03-2015, 08:54 PM
Yes, an executable application has been build when i compiled the program, i presume that should be the executable from which i need to extract the path.

SilverWarior
17-03-2015, 10:05 PM
That is correct. Adn you get full finelane (path of your file + filename) of your executable with


Application.ExeName

Realeg
19-03-2015, 09:17 PM
Am i doing it wrong or... i tried to use what you told me below and got this

path:=pChar(ExtractFilePath(grafica.exeName));
I know it's wrong, but with what should i replace that to make it work?

SilverWarior
19-03-2015, 10:46 PM
Ahh now I see what is confusing you.

When I write use Application.ExeName I mean that literally.

You see in modern pascal dialects the Application is actually a global variable for TApplication class which contains several properties and methods. Best example of seeing this in use is looking ath the source of your project file (*.dpr file).

And one of its properties is ExeName which contains full filename of your application executable.

Cybermonkey
21-03-2015, 09:27 AM
With Freepascal you can also use the "old school" way:

path:=ExtractFilePath(ParamStr(0));
(No need for pChar as you can see.)

Realeg
21-03-2015, 06:18 PM
Ok, in the end i mananged to find out how to make it work with paths, thanks to both of you:)
Another question: I've heard from my teacher that in the Pascal IDE are some options or something like that to show the amount of memory and time execution of a program. Can you tell me how to make use of them?

Anton
24-03-2015, 10:21 PM
For which operating system do you compile your program? For windows or linux?

About the amount of memory, you should definately be able to get information from the memory manager about the allocated memory size. But when you use external libraries usually they allocate memory using their own memory managers so you cannot catch their memory usage. If you need to monitor you program's memory usage and track for memory leaks and your program is running on windows, i can definately advise you to try this program - VMMap (https://technet.microsoft.com/en-us/library/dd535533.aspx). It can monitor the memory blocks your process has allocated, and it can trace the call stack of each allocation.

About performance, you could measure execution time of your whole program or separate procedures very easily. For example if you want to measure how much time does it take to execute procedure called DoSomething(), then you can do like this:


var
T: Int64;
begin
T := GetTickCount;
DoSomething();
T := GetTickCount - T; //Now variable T will hold the execution time of your procedure in milisecond units.
//Output this value somewhere you can see it.
End;

SilverWarior
24-03-2015, 11:07 PM
@Anton
As far as I know the TickCount can be updated more than once per ms. I think that many newer computer already update tckCount every half millisecond.
This means that variable T in your suggested code might not represent time taken in ms. Now it is possible to retrieve information from OS to see how often is TickCount updated so you can then properly calculate the time taken.

Newer versions of Delphi also provides a special record called TStopWatch which tries to use the approach with best percision that is available on your computer. I have use it several times now for time profiling.

But most of the times I simply go and store a time at the start of the process and another at the end and then check how much millisceconds did pas between them.
Now you would probably say SilverWarior that approach doesn't provide good enough accuracy.
That usually doesen't present a problem to me becouse if posible I tend to repeat certain procedure multiple times and check how much time is taken for that.
Why am I doing so? Nowadays all computer support CPU autothrotling which can affect the test performance. Not to mention that you always have bunch of other processes running in the background which can consume veriable amounts of CPU power and greatly screw up your tests.

Anton
25-03-2015, 07:02 AM
My comment was very brief, to show very basic example of profiling.

I'm not sure that GetTickCount actually gets a value from a hardware tick counter directly. At least in Delphi for Windows it is alias for WinApi function GetTickCount (https://msdn.microsoft.com/en-us/library/aa915056.aspx this is for windows mobile, because the original help is somehow unavailable, but i think its the same of desktop windows), which is stated to return "milliseconds until windows has started". And if you run windows for a while this value will reset, since it is wrapper by max value of DWORD/Cardinal. Well of course it is not very precise, actually it seems it is update by over 16 milliseconds.

I havent used LclIntf.GetTickCount in Lazarus but I think it will have the same behavior as Winapi.


if posible I tend to repeat certain procedure multiple times and check how much time is taken for that
Yes i think this is very effective approach