Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [OpenLayer] Bitmaps and Iterators

Credits go to CGamesPlay and Dustin Dettmer for helping out!
This thread is locked; no one can reply to it. rss feed Print
 1   2 
[OpenLayer] Bitmaps and Iterators
Matthew Dalrymple
Member #7,922
October 2006
avatar

I'm trying to get this to work... here is the pastebin if you'd rather look at it through that http://pastebin.bafserv.com/699

Anyway, when using an iterator to call the Draw() method nothing actually draws. Pressing space in the example will draw them as Draw() is being called directly.

1/*
2 * Author: Matthew Dalrymple
3 * Revision: One zero one zero zero zero zero one zero
4 * Title: Testing OpenLayer's Bitmap's and vectors/iterators
5*/
6 
7// Include the OpenLayer graphical library
8#include <OpenLayer.hpp>
9#include <vector>
10 
11// Use the OpenLayer namespace
12using namespace ol;
13using namespace std;
14 
15class Test
16{
17public:
18 Test();
19 ~Test();
20 void Draw();
21private:
22 int x;
23 int y;
24 Bitmap theimage;
25};
26 
27Test::Test()
28{
29 this->x = 5;
30 this->y = 10;
31 this->theimage.Load("gnolam.png");
32 if(!theimage.IsValid())
33 allegro_message("ZOMG ITS NOT VALID");
34}
35 
36Test::~Test()
37{
38 this->theimage.Destroy();
39}
40 
41void Test::Draw()
42{
43 this->theimage.Blit(x, y);
44}
45 
46 
47 
48int main()
49{
50 // Sets up the devices needed
51 // keyboard, mouse, timer
52 Setup::SetupProgram(true, false, true);
53
54 // Sets up the screen dimensions
55 // Screen Width, Screen Height, WINDOWED OR FULLSCREEN
56 Setup::SetupScreen(800, 600, WINDOWED);
57
58 Bitmap TheScreen(800, 600, Rgba::WHITE);
59 Bitmap Logo("logo.png");
60
61 Test a, b, c, d;
62
63 vector< Test > TheList;
64 TheList.push_back(a);
65 TheList.push_back(b);
66 TheList.push_back(c);
67 TheList.push_back(d);
68
69 vector< Test >::iterator iter;
70 
71 /*
72 * This loop is a simple demonstration of continuing until
73 * a key is pressed, it is highly inefficient. It is strongly
74 * recommended that you read through the Allegro handbook for
75 * handling keyboard input.
76 */
77 float deltaTime = 0;
78 FpsCounter::Start( 60.0 );
79 while(!key[KEY_ESC])
80 {
81 FpsCounter::NewFrameStarted();
82 deltaTime = FpsCounter::GetDeltaTime();
83
84
85 TheScreen.Blit(0, 0);
86 Logo.Blit(250, 250);
87 for(iter = TheList.begin(); iter != TheList.end(); iter++)
88 iter->Draw();
89
90 // press space and see that Draw works properly
91 if(key[KEY_SPACE])
92 {
93 a.Draw();
94 b.Draw();
95 c.Draw();
96 d.Draw();
97 }
98 
99 Canvas::Refresh();
100 rest(1);
101 }
102
103 TheScreen.Destroy();
104 Logo.Destroy();
105 
106 return 0;
107}END_OF_MAIN() // Required by Allegro & OpenLayer, YOU MUST HAVE THIS

What am I doing wrong/how can I correct this?

Hehe don't ask why I used gnolam's avatar.

EDIT:

Here is the fix for this.. is there anyway to do this with the above example?

1/*
2 * Author: Matthew Dalrymple
3 * Revision: One zero one zero zero zero zero one zero
4 * Title: Testing OpenLayer's Bitmap's and vectors/iterators
5*/
6 
7// Include the OpenLayer graphical library
8#include <OpenLayer.hpp>
9#include <vector>
10 
11// Use the OpenLayer namespace
12using namespace ol;
13using namespace std;
14 
15class Test
16{
17public:
18 Test();
19 ~Test();
20 void Draw();
21private:
22 int x;
23 int y;
24 Bitmap theimage;
25};
26 
27Test::Test()
28{
29 this->x = 5;
30 this->y = 10;
31 this->theimage.Load("gnolam.png");
32 if(!theimage.IsValid())
33 allegro_message("ZOMG ITS NOT VALID");
34}
35 
36Test::~Test()
37{
38 this->theimage.Destroy();
39}
40 
41void Test::Draw()
42{
43 this->theimage.Blit(x, y);
44}
45 
46 
47 
48int main()
49{
50 // Sets up the devices needed
51 // keyboard, mouse, timer
52 Setup::SetupProgram(true, false, true);
53
54 // Sets up the screen dimensions
55 // Screen Width, Screen Height, WINDOWED OR FULLSCREEN
56 Setup::SetupScreen(800, 600, WINDOWED);
57
58 Bitmap TheScreen(800, 600, Rgba::WHITE);
59 Bitmap Logo("logo.png");
60
61 Test a, b, c, d;
62
63 vector< Test* > TheList;
64 TheList.push_back(&a);
65 TheList.push_back(&b);
66 TheList.push_back(&c);
67 TheList.push_back(&d);
68
69 vector< Test* >::iterator iter;
70 
71 /*
72 * This loop is a simple demonstration of continuing until
73 * a key is pressed, it is highly inefficient. It is strongly
74 * recommended that you read through the Allegro handbook for
75 * handling keyboard input.
76 */
77 float deltaTime = 0;
78 FpsCounter::Start( 60.0 );
79 while(!key[KEY_ESC])
80 {
81 FpsCounter::NewFrameStarted();
82 deltaTime = FpsCounter::GetDeltaTime();
83
84
85 TheScreen.Blit(0, 0);
86 Logo.Blit(250, 250);
87 for(iter = TheList.begin(); iter != TheList.end(); iter++)
88 (*iter)->Draw();
89
90 // press space and see that Draw works properly
91 if(key[KEY_SPACE])
92 {
93 a.Draw();
94 b.Draw();
95 c.Draw();
96 d.Draw();
97 }
98 
99 Canvas::Refresh();
100 rest(1);
101 }
102
103 TheScreen.Destroy();
104 Logo.Destroy();
105 
106 return 0;
107}END_OF_MAIN() // Required by Allegro & OpenLayer, YOU MUST HAVE THIS

=-----===-----===-----=
I like signatures that only the signer would understand. Inside jokes are always the best, because they exclude everyone else.

CGamesPlay
Member #2,559
July 2002
avatar

If Bitmap doesn't have a proper copy constructor, it won't be copied, and it won't be displayed. Maybe checking IsValid inside the Draw method will tell you something?

When you push the a, b, c, and d objects into the vector, you push the actual objects, so you actually make a copy of them. When this happens, OpenLayer has to send a copy of the Bitmap to the graphics card. I don't know if it handles this properly. One possible fix is to use a Bitmap* inside the class, and continue to use a vector of objects, but the pointer method is superior for most cases in terms of performance.

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Matthew Dalrymple
Member #7,922
October 2006
avatar

FYI: CGamesPlay was a major contributor to this being fixed :-D.

Another error that I'm having that CGamesPlay said was the right syntax and I thought so myself is this line:

...
vector < Avatars* > CurrentList, AvatarList;
// Avatar List gets filled so don't worry there is stuff in it
...

CurrentList.reserve(MAX_AVATARS_ON_SCREEN);
for(int i = 0; i < MAX_AVATARS_ON_SCREEN; i++)
  CurrentList.push_back(AvatarList.at(rand() % AvatarList.size()));

*.at() should return a pointer and so it compiles correctly. The problem is that it stops things from being drawn and causes my CPU to be 100% and lags like crazy. I comment that line out and "bam" it's fixed. Is their a correct way to do this or is their a workaround like maybe setting a temp Avatar instance setting it equal to *.at(...) then pushing it to the back of CurrentList? I would rather have a one line simple thing.

=-----===-----===-----=
I like signatures that only the signer would understand. Inside jokes are always the best, because they exclude everyone else.

CGamesPlay
Member #2,559
July 2002
avatar

What is the value of MAX_AVATARS_ON_SCREEN?

Like I said: that line of code is fine. Show the part where you draw, for instance.

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Matthew Dalrymple
Member #7,922
October 2006
avatar

MAX_AVATARS_ON_SCREEN is set to 15 for now.

This is how they're drawn:

bool Game::DrawAvatars()
{
  vector< Avatar* >::iterator curAvatar;
  for(curAvatar = CurrentList.begin(); curAvatar != CurrentList.end(); curAvatar++)
    (*curAvatar)->Draw();
  //Log::log("CurrentList.size() = %i", CurrentList.size());
  return true;
}

This is the Avatar's Draw method:

bool Avatar::Draw(void)
{
  this->m_Avatar.Blit(10, 10);
  return true;
}

EDIT: I hate having difficult questions that no one knows the exact answer to or just ignore me :P:P:P

=-----===-----===-----=
I like signatures that only the signer would understand. Inside jokes are always the best, because they exclude everyone else.

CGamesPlay
Member #2,559
July 2002
avatar

I wonder if you've found the answer yet?

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Dustin Dettmer
Member #3,935
October 2003
avatar

Donno why its hanging there, likely a copy paste error or something.

CurrentList.reserve(MAX_AVATARS_ON_SCREEN);
for(int i = 0; i < MAX_AVATARS_ON_SCREEN; i++)
  CurrentList.push_back(AvatarList.at(rand() % AvatarList.size()));

Should be:

#include <algorithm>

CurrentList.resize(AvatarList.size());
random_sample(AvatarList.begin(), AvatarList.end(), CurrentList.begin(), CurrentList.end());

Quote:

Here is the fix for this.. is there anyway to do this with the above example?

Its not pretty:

1class Test
2{
3public:
4 Test();
5 ~Test();
6 void Draw();
7
8 Test(const Test &t)
9 : x(t.x), y(t.y), theimage(t.theimage)
10 {
11 ((Test*)&t).theimage = 0;
12 }
13
14private:
15 int x;
16 int y;
17 Bitmap *theimage;
18};
19 
20Test::Test()
21: theimage(new Bitmap)
22{
23 this->x = 5;
24 this->y = 10;
25 this->theimage->Load("gnolam.png");
26 if(!theimage->IsValid())
27 allegro_message("ZOMG ITS NOT VALID");
28}
29 
30Test::~Test()
31{
32 if(theimage)
33 this->theimage->Destroy();
34 delete theimage;
35}
36 
37.. rest is same (except using -> instead of .)

Matthew Dalrymple
Member #7,922
October 2006
avatar

Quote:

I wonder if you've found the answer yet?

Haha nope, well now that DD has posted I might have.

To DD (Or anyone else):

I'm reading about random_sample() from cppreference.com and it seems that it confuses me haha.
AvatarList holds 1 copy of each avatar, now CurrentList is supposed to be holding the actual avatars you'll see and fight. When one dies a random avatar from AvatarList will be popped onto CurrentList. Now will random_sample() work for what I'm doing (just for the initialization though)? Does it randomly put them into CurrentList depending on CurrentList's size? The way it looks it seems like CurrentList needs to already be full :-/.

=-----===-----===-----=
I like signatures that only the signer would understand. Inside jokes are always the best, because they exclude everyone else.

CGamesPlay
Member #2,559
July 2002
avatar

random_sample(AvatarList.begin(), AvatarList.end(), CurrentList.begin() + dead_avatar_index, CurrentList.begin() + dead_avatar_index + 1);That will make it replace 1. I have no idea why you wouldn't just use your code.

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Matthew Dalrymple
Member #7,922
October 2006
avatar

I would use my code because it doesn't work. It may be logically correct but its causing things to not work, I mean I can rar it up again and show you how it doesn't work :D

Edit: I keep getting the error: random_sample().. first use of this function. And I've included algorithm >.< Rebuilt all... Baaaah.
Eww totally had to include <algo.h> to get it to work :-/ I dunno why.

=-----===-----===-----=
I like signatures that only the signer would understand. Inside jokes are always the best, because they exclude everyone else.

Jakub Wasilewski
Member #3,653
June 2003
avatar

Quote:

Edit: I keep getting the error: random_sample().. first use of this function. And I've included algorithm >.< Rebuilt all... Baaaah.
Eww totally had to include <algo.h> to get it to work :-/ I dunno why.

Err, maybe std::random_sample or "using namespace std;" would help? These seem like errors you get when you forget about a namespace :). This and the fact that <algorithm> probably only wraps <algo.h> in a namespace ;).

---------------------------
[ ChristmasHack! | My games ] :::: One CSS to style them all, One Javascript to script them, / One HTML to bring them all and in the browser bind them / In the Land of Fantasy where Standards mean something.

Dustin Dettmer
Member #3,935
October 2003
avatar

Quote:

When one dies a random avatar from AvatarList will be popped onto CurrentList.

[edit]Ah I see. Yes your code is better suited for this task. Just don't use reserve. Its generally useless unless you really know what you're doing. And even when you do, it pretty much will only apply to one compiler.

Matthew Dalrymple
Member #7,922
October 2006
avatar

Jakub Wasilewski said:

Err, maybe std::random_sample or "using namespace std;" would help?

Tried that and I am already using the standard namespace.

Dustin Dettmer said:

Just don't use reserve.

Then how do I set the size that CurrentList is going to be filled up to?

=-----===-----===-----=
I like signatures that only the signer would understand. Inside jokes are always the best, because they exclude everyone else.

CGamesPlay
Member #2,559
July 2002
avatar

vec.resize(newsize);:)

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Matthew Dalrymple
Member #7,922
October 2006
avatar

Bah I never saw resize() on cppreference.com, I always overlook things. That's totally what I wanted to use in my other projects too not reserve(). Umm where can I get an update for all the standard libraries because no matter what I try I can't get random_sample() to work with <algorithm>.

=-----===-----===-----=
I like signatures that only the signer would understand. Inside jokes are always the best, because they exclude everyone else.

Dustin Dettmer
Member #3,935
October 2003
avatar

What compiler are you using?

Matthew Dalrymple
Member #7,922
October 2006
avatar

MinGW (the version that came with Dev-C++ beta 5 [4.9.9.2 or whatever])

=-----===-----===-----=
I like signatures that only the signer would understand. Inside jokes are always the best, because they exclude everyone else.

Dustin Dettmer
Member #3,935
October 2003
avatar

Should support it just fine. Paste some code.

Matthew Dalrymple
Member #7,922
October 2006
avatar

Quote:

Paste some code.

#define MAX_AVATARS_ON_SCREEN 15
...
#include <algorithm>
...
CurrentList.resize(MAX_AVATARS_ON_SCREEN);
random_sample(AvatarList.begin(), AvatarList.end(), CurrentList.begin(), CurrentList.end());

When I use #include <algo.h>
I get errors when trying to draw my CurrentList using (*iter)->Draw() My logfile is full of

Quote:

 is not valid

for all of my Avatars in CurrentList. I changed CurrentList and AvatarList from vector < Avatar* > to vector < Avatar > and I got their names instead of that weird A but they were still not valid >.<. I'm thinking about trying this with an array instead of a vector. Or maybe try and STL::List (but lists and vectors are so similar I wouldn't see how that would effect things.

=-----===-----===-----=
I like signatures that only the signer would understand. Inside jokes are always the best, because they exclude everyone else.

CGamesPlay
Member #2,559
July 2002
avatar

Could you show the code that wrote the "Â is not valid", as well as the full code for the Avatar class?

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Matthew Dalrymple
Member #7,922
October 2006
avatar

Avatar.hpp

1#ifndef __AVATARS_HPP__
2#define __AVATARS_HPP__
3 
4#include "stdafx.hpp"
5 
6#define TOPLEFT 0
7#define TOPRIGHT 1
8#define BOTLEFT 2
9#define BOTRIGHT 3
10 
11 
12class Avatar
13{
14public:
15 Avatar();
16 Avatar(std::string fileName);
17 ~Avatar();
18 bool Load(std::string fileName);
19 void Draw(void);
20 void Update(void);
21
22 std::string GetName(void);
23 void SetName(std::string name);
24 
25 /**
26 * Position the image in one of the four corners of the screen
27 * Paramater takes: TOPLEFT | TOPRIGHT | BOTLEFT | BOTRIGHT
28 **/
29 void Reposition(int corner);
30private:
31 Bitmap m_Avatar;
32 std::string m_Name;
33 int x;
34 int y;
35 int m_Corner;
36};
37 
38#endif

Avatar.cpp

1#include "../include/stdafx.hpp"
2 
3Avatar::Avatar()
4{
5 // Starting the image at one of the four courners of the map
6 Reposition(rand() % 3);
7}
8Avatar::Avatar(std::string fileName)
9{
10 Load(fileName);
11}
12Avatar::~Avatar()
13{
14 this->m_Avatar.Destroy();
15}
16bool Avatar::Load(std::string fileName)
17{
18 this->m_Avatar.Load(fileName.c_str());
19 Log::verify(this->m_Avatar.IsValid(), "%s did not load correctly", fileName.c_str());
20 if(!this->m_Avatar.IsValid())
21 return false;
22 return true;
23}
24void Avatar::Draw(void)
25{
26 Log::verify(m_Avatar.IsValid(), "%s is not valid", m_Name.c_str());
27 this->m_Avatar.Blit(10, 10);
28}
29 
30void Avatar::Update(void)
31{
32}
33 
34/* DONT MIND THIS FUNCTION YET :D */
35void Avatar::Reposition(int corner)
36{
37 m_Corner = corner;
38 
39 this->x = rand() % SCREEN_W;
40 this->y = rand() % SCREEN_H;
41}
42 
43std::string Avatar::GetName(void)
44{
45 return this->m_Name;
46}
47void Avatar::SetName(std::string name)
48{
49 this->m_Name = name;
50}

Ok to get the log file to produce this:

1Á is not valid
2Á is not valid
3Á is not valid
4Á is not valid
5Á is not valid
6Á is not valid
7Á is not valid
8Á is not valid
9Á is not valid
10Á is not valid
11Á is not valid
12Á is not valid
13Á is not valid
14Á is not valid
15Á is not valid
16(null) is not valid
17(null) is not valid
18(null) is not valid
19(null) is not valid
20(null) is not valid
21(null) is not valid
22(null) is not valid
23(null) is not valid
24(null) is not valid
25(null) is not valid
26(null) is not valid
27(null) is not valid
28(null) is not valid
29(null) is not valid
30(null) is not valid

This is what I did
Game.cpp area:

1bool Game::LoadAvatars()
2{
3...
4 CurrentList.resize(MAX_AVATARS_ON_SCREEN);
5 random_sample(AvatarList.begin(), AvatarList.end(), CurrentList.begin(), CurrentList.end());
6...
7}
8/**
9* Draw the current list of avatars to the screen at their correct coordinates
10**/
11bool Game::DrawAvatars()
12{
13 vector< Avatar* >::iterator curAvatar;
14 for(curAvatar = CurrentList.begin(); curAvatar != CurrentList.end(); curAvatar++)
15 (*curAvatar)->Draw();
16 //Log::log("CurrentList.size() = %i", CurrentList.size());
17 return true;
18}
19 
20/**
21* Update the Avatar sprites to their new locations
22**/
23bool Game::UpdateAvatars()
24{
25 vector< Avatar* >::iterator curAvatar;
26 for(curAvatar = CurrentList.begin(); curAvatar != CurrentList.end(); curAvatar++)
27 (*curAvatar)->Update();
28 return true;
29}

=-----===-----===-----=
I like signatures that only the signer would understand. Inside jokes are always the best, because they exclude everyone else.

CGamesPlay
Member #2,559
July 2002
avatar

Add a copy constructor to your object:

Avatar::Avatar(const Avatar& other)
{
    Log::error("Object not allowed to be copied");
}

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Matthew Dalrymple
Member #7,922
October 2006
avatar

Same log file. The object isn't being copied. Is that good or bad?

=-----===-----===-----=
I like signatures that only the signer would understand. Inside jokes are always the best, because they exclude everyone else.

CGamesPlay
Member #2,559
July 2002
avatar

Good :)

Unfortunately, I'm at a loss. Start dumping your objects at very frequent intervals and see what causes them to screw up. Make sure they are loaded correctly.

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Matthew Dalrymple
Member #7,922
October 2006
avatar

Baaaaah, this is what always defers me away from programming sometimes. Everything always looks right, seems like it should work... BAM! RUN TIME ERRORS that are hard as hell to solve.

=-----===-----===-----=
I like signatures that only the signer would understand. Inside jokes are always the best, because they exclude everyone else.

 1   2 


Go to: