|
|
| Looking for a Game Tutorial |
|
Thomas Fjellstrom
Member #476
June 2000
|
I dunno, if you treat the "index" as an opaque "bitmap id", rather than an index then you can change the underlying implementation at any time and not have to worry about passing pointers around, or using string based hashing. -- |
|
J-Gamer
Member #12,491
January 2011
|
Quote: J-Gamer said: Thanks... I was wondering how you guys all do that :p
acc.js [github.com] I was actually talking about how to be able to copy both the text AND the link to the specific post ^^ I haven't studied Java yet, so I don't really understand the code ._. bamccaig said: The object doesn't actually need to know what the image index refers to because (presumably) it will be passed in and set from the outside world by something that does know. Using indexes like that for your sprites isn't a terrible idea, but there are better ways to do it, especially in C++. For example, you could store boost::shared_ptr<BITMAP> and then store a copy of the sprite's smart pointer directly in your class. You could even load your sprites into a std::map<std::string, boost::shared_ptr<BITMAP> > so that you could later refer to them by name. That's generally how I have done it.
In the code we get to see, it's clear that he wants the function to know which number to return, probably based on some state parameters of the object itself. " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
|
Thomas Fjellstrom
Member #476
June 2000
|
J-Gamer said: I was actually talking about how to be able to copy both the text AND the link to the specific post ^^ The forum auto links it most times. -- |
|
bamccaig
Member #7,536
July 2006
|
J-Gamer said: I was actually talking about how to be able to copy both the text AND the link to the specific post ^^
That's actually specifically what it can do. J-Gamer said:
I haven't studied Java yet, so I don't really understand the code ._.
It's JavaScript, not Java. They are two completely different languages with little in common. In theory, you should be able to just drop it in and use it, but in practice having some JavaScript experience would come in handy because it isn't perfect. J-Gamer said: In the code we get to see, it's clear that he wants the function to know which number to return, probably based on some state parameters of the object itself. The object would just store its sprite index, or an animation, which itself would contain a set of indexes. That would be part of the object's state. The object doesn't physically need to know what those indexes mean. It can trust the outside world to give it the right indexes. Of course, it's not a perfect model, but it can work if you're careful. A better model is probably storing an animation or a set of animations, each of which containing a set of smarter pointers to your sprites. J-Gamer said: I have to say I never used Boost, so I don't know how it works. Boost is a very large C++ framework. The boost::shared_ptr<T> is a smart pointer that manages the memory for you automatically. Essentially, it just stores a copy-count/reference-count internally. When you make copies of it the count is incremented, and when those copies are destroyed the count is decremented. When the count reaches zero, the stored object is automatically destroyed, freeing the memory. It's entirely automatic. 1typedef boost::shared_ptr<int> IntPtr;
2typedef boost::shared_ptr<ALLEGRO_BITMAP> AlBitmapPtr;
3
4{
5 {
6 IntPtr i(new int(5));
7 } // The int is deleted here automatically.
8
9 AlBitmapPtr b;
10
11 {
12 AlBitmapPtr b2(
13 al_load_bitmap("./path/to/file.bmp"),
14 al_destroy_bitmap);
15
16 b = b2;
17 }
18} // The ALLEGRO_BITMAP is destroyed here automatically.
It's a bit like garbage collection, except that it works immediately instead of waiting some indeterminate amount of time and checking for objects that can be freed. The downside is that it can't handle cyclical references, so you do need to pay some attention if you end up creating those. -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
|
gnolam
Member #2,030
March 2002
|
I said: gnolam said: Also: the code you're giving us shouldn't even compile...
Quote: masked_blit(Sprite[Object->GetImage()], Buffer, Object->GetFrame() * Object->GetW(); Object->GetStance() * Object->GetH(); Object->GetX() - Camera->GetX(); Object->GetY() - Camera->GetY(); Object->GetW(), Object->GetH());
I was referring to the semicolons. -- |
|
J-Gamer
Member #12,491
January 2011
|
bamccaig said: It's JavaScript, not Java.
" There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
|
Gabriel Campos
Member #12,034
June 2010
|
gnolam said: I was referring to the semicolons.
Oh..yes, I dont realized...
|
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Gabriel Campos said:
The function works nicely after I declared pure virtual... It's because every function you declare has to also be defined. Also, you should note that every base class that has virtual functions should also have a virtual destructor. This is so that the appropriate destructors get called for the derived classes. /// In Base.hpp class Base { protected : Data d; public : Base() : d() {} virtual ~Base() {} virtual void DoSomething(); }; /// In Base.cpp void Base::DoSomething() {/*...*/}
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
Gabriel Campos
Member #12,034
June 2010
|
But why to put in the destructor?? 1/// In Base.hpp
2
3class Base {
4protected :
5 Data d; // Couldn understand
6public :
7 Base() : d() {} // Couldn understand
8 virtual ~Base() {}
9 virtual void DoSomething();
10};
11
12/// In Base.cpp
13
14void Base::DoSomething() {/*...*/}
Other thing I want to learn is..why use this implementation on the constructor code of some object, something like player.. 1class cPlayer{
2 cPlayer(int x, int y) : (x, y); // can someone explain to me?
I want to thanx evebody too.. Since this post I learned a lot about OOP..
|
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Gabriel Campos said: But why to put in the destructor??
Edgar Reynaldo said: This is so that the appropriate destructors get called for the derived classes.
Gabriel Campos said: I couldnt understand this part of the code Data is just a made up class, used for an example. 1class Data {
2private :
3 int i;
4 float f;
5 char c;
6public :
7 Data();
8 Data(int _integer , float _float , char _char);
9};
10
11Data::Data() :
12 i(0), // call int constructor for integer type
13 f(0.0f), // call float constructor for float type
14 c('\0') // call char constructor for char type
15{}
16
17Data::Data(int _integer , float _float , char _char) :
18 i(_integer),
19 f(_float),
20 c(_char)
21{}
The code in the constructor after the semicolon and before the braces is called an initialization list. It gives the member variables of the class an initialization value. Always initialize the members of the class before using them. If you don't, then their starting values are undefined, and hold the value of whatever was left over in memory from before. An example of what not to do : Data::Data() { printf("i = %i , f = %f , c = %c" , i , f , c);// Could print anything // because i , f , and c are // uninitialized }
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
Gabriel Campos
Member #12,034
June 2010
|
Well, couldnt understand yet...But I got a c++ book from a good university here, so I will study all this part. . . 1
2int main(){
3 init();
4 Stage01();
5 Stage02();
6 Stage03();
7 deinit();
8}
9END_OF_MAIN();
10
11int Stage01(){
12 // Here I create the objects
13 cPlayer Player(200, 200); // x, y, parameters
14 cEnemy Enemy[10]; // and on and on
15
16while(inGame){
17 // the game code
18}
19} // end of Stage
20
21
22int Stage02(){
23 // Here I create the objects again
24 cPlayer Player(100, 250); // x, y, parameters
25 cEnemy Enemy[6];
26
27while(inGame){
28 // the game code
29}
30} // end of Stage
So, this is the right way to do this??
|
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
I would use something like this. You can set up the current stage in the CreateStage function, and then just run the current stage in main. 1class Stage {
2private :
3 BITMAP* stage_map;
4 BITMAP* buffer;
5 cPlayer Player;
6 vector<cEnemy*> Enemies;
7 cCamera Camera;
8
9public :
10 Stage() : stage_map() , Player() , Enemies() {}
11 ~Stage() {Free();}
12 void Free() {
13 if (buffer) {
14 destroy_bitmap(buffer);
15 buffer = 0;
16 }
17 if (stage_map) {
18 destroy_bitmap(stage_map);
19 stage_map = 0;
20 }
21 for (int i = 0 ; i < Enemies.size() ; ++i) {delete Enemies[i];}
22 Enemies.clear();
23 }
24 void SetStageMap(BITMAP* bmp) {
25 if (!bmp) {return;}
26 if (stage_map) {destroy_bitmap(stage_map);}
27 stage_map = bmp;
28 }
29 bool Update(double tsec) {
30 // collision testing goes here
31 Player.Update(tsec);
32 for (int i = 0 ; i < Enemies.size() ; ++i) {
33 Enemies[i]->Update(tsec);
34 }
35 Camera.CenterOn(Player.CX() , Player.CY());
36 }
37 void CheckInputs() {
38 Player.CheckInputs();
39 for (int i = 0 ; i < Enemies.size() ; ++i) {
40 Enemies[i]->CheckInputs();
41 }
42 }
43 void Draw(BITMAP* dest) {
44 int camx = Camera.X();
45 int camy = Camera.Y();
46 int camw = Camera.W();
47 int camh = Camera.H();
48 blit(stage_map , buffer , camx , camy , 0 , 0 , camw , camh);
49 Player.Draw(buffer , -camx , -camy);
50 for (int i = 0 ; i < Enemies.size() ; ++i) {Enemies[i]->Draw(buffer , -camx , -camy);}
51 blit(buffer , dest , 0 , 0 , 0 , 0 , buffer->w , buffer->h);
52 }
53
54 void SetPlayerStats(/*...*/);
55 void AddEnemy(cEnemy* enemy) {
56 Enemies.push_back(enemy);
57 }
58};
59
60
61Stage* CreateStage(int stage_num) {
62 Stage* new_stage = 0;
63 switch (stage_num) {
64 case 1 :
65 return new Stage(/*... parameters ...*/);
66 break;
67 case 2 :
68 new_stage = new Stage();
69 /* Alter the new stage here */
70 return new_stage;
71 break;
72 default :
73 Error();
74 break;
75 }
76 return new_stage;
77}
78
79/// In main
80
81int stage_num = 1;
82Stage* current_stage = CreateStage(stage_num);
83
84while (playing) {
85 current_stage->Draw(screen);
86 current_stage->CheckInputs();
87 current_stage->Update(time_passed);
88 if (current_stage->StageComplete()) {
89 delete current_stage;
90 ++stage_num;
91 current_stage = CreateStage(stage_num);
92 }
93 if (current_stage->GameOver()) {playing = false;}
94}
95
96if (current_stage) {delete current_stage;}
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
Gabriel Campos
Member #12,034
June 2010
|
Hmm... So you are telling me to make all the game in a class and there make a system to load the maps and the enemies..??
|
|
|
|