Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Weird flex with my Bitmaps on my Screen

This thread is locked; no one can reply to it. rss feed Print
Weird flex with my Bitmaps on my Screen
nico_c++
Member #16,940
January 2019

Hey,

I have a problem.
I have 10000 Tiles, all with a size of 10 times 10 Pixels.
I give them their positions like this:

#SelectExpand
1 tiles = new vector<TILE>(10000); 2 listofbombs = new vector<short>(0); 3 4 5 for (int i = 0; i < 10000;) 6 { 7 for (int y = 1; y <= 100; y++) 8 { 9 for (int x = 1; x <= 100; x++) 10 { 11 (*tiles)[i].getPositioned(x * 10, y * 10); 12 (*tiles)[i].draw(); 13 i++; 14 } 15 } 16 } //POSITIONS

Meanwhile they get projected on the screen like this:

#SelectExpand
1void TILE::draw(void) 2{ 3 if (*status == 1) 4 { 5 al_draw_bitmap(TILE_BITMAP_NORMAL, *x_pos, *y_pos, 0); 6 } 7 if (*status == 2) 8 { 9 if (*bomb == 1) al_draw_bitmap(TILE_BITMAP_RED, *x_pos, *y_pos, 0); 10 else al_draw_bitmap(TILE_BITMAP_GREEN, *x_pos, *y_pos, 0); 11 } 12 13}

getPositioned(short, short) just give them Tiles their positions, defined in the class TILE as *x_pos and *y_pos.

Its kind of all working.
But as you can see in my screenshot
71551e-1573062597.png,
(bigger that you can see something here: PICTURE
there is something weird happening in the 12/13 row from bottom.
I dont know what this is.

I have some routines, that some things happen, when I click on a TILE,
but when I click on TILE in the 12th row from bottom, it activates one in the 13th.
But just sometimes. So I dont know what this means, I am pretty sure, I did my math right.
Somebody can help me?

EDIT: Screenshot is not very good.
DB should be better!

Edgar Reynaldo
Member #8,592
May 2007
avatar

Nico, you're using a triply nested loop. You only need a doubly nested loop. All iterations of i < 9999 are overwritten by the inner xy loop when [i = 9999].

nico_c++
Member #16,940
January 2019

Thx for answering me.
I wrote it down like that now:

#SelectExpand
1 short INDEX_counter = 0; 2 3 for (int y = 1; y <= 100; y++) 4 { 5 for (int x = 1; x <= 100; x++) 6 { 7 (*tiles)[INDEX_counter].getPositioned(x * 10, y * 10); 8 (*tiles)[INDEX_counter].draw(); 9 INDEX_counter++; 10 } 11 } //POSITIONS

But its still not working!

Edgar Reynaldo
Member #8,592
May 2007
avatar

You can combine those two methods into one.

Make the draw method take an x and y pos. Then you don't even have to store the position.

I can't see why it's not working just from the little bit you've shown me. Show more code.

nico_c++
Member #16,940
January 2019

No, I need to store the position, I need it later.
What else do you want to see?
My drawing code is still the same!

I just want to store the positions in the vector (which I do with my new code), and then draw it.
I dont understand why it isnt working.

DanielH
Member #934
January 2001
avatar

  for (int i = 0; i < 10000;)
  {
    for (int y = 1; y <= 100; y++)
    {
      for (int x = 1; x <= 100; x++)
      {
        (*tiles)[i].getPositioned(x * 10, y * 10);
        (*tiles)[i].draw();
        i++;
      }
    }
  } //POSITIONS

You are drawing 10000 tiles 1000 times each. That is what the question or response was about.

How big is 1 tile?

Each tile gets drawn

for (int y = 1; y <= 100; y++)
{
  for (int x = 1; x <= 100; x++)
  {
      // draw tile
  }
}

nico_c++
Member #16,940
January 2019

Look at my new code, but even in the old one:

I draw each tile one time. The index "i" is increasing with each loop.
In my first code there was a problem, because when "i" was 9999, it would get overwritten by the inner loops.

In my new code this isnt the case.

I am debugging my code, and when I view my vector "tiles", everything is alright.
Each TILE has the right position, as I see it.

So I dont know, why there is something wrong in the projection.

I hope you understand my english XD

DanielH
Member #934
January 2001
avatar

What are the values of status and bomb at those locations that are drawn funny?

What do TILE_BITMAP_NORMAL, TILE_BITMAP_RED, TILE_BITMAP_GREEN look like?

Some things I question:
What is *status, *x_pos and *y_pos? Why are they pointers and being dereferenced?

Can *status be anything but 1 or 2?

nico_c++
Member #16,940
January 2019

Okay, that are many questions.

I use pointers, because in this project memory managment is very important.

While the TILES are drawn the first time, *status is 1 for EVERY Tile.
That means, that there are only TILE_BITMAP_NORMAL drawn.
What the TILE_BITMAP_NORMAL looks like, that can you see in my screenshot.
But while you say it, I changed the bitmap.
Here is the screenshot, on it you can see even better what I mean:
PICTURE 2

*bomb is of course in that state always 0, but that doesnt matter, because the *status is never 2, so it doesnt get in that if-clause.

And *x_pos and *y_pos are attributes in my vector<TILE>, which every TILE gets in the xy-loop, as in the code above.

DanielH
Member #934
January 2001
avatar

I'm more curious as to how these variables are created and modified. Are these variables actually allocated and deallocated in your routines?

nico_c++ said:

I use pointers, because in this project memory managment is very important.

Using an integer vs an allocated integer isn't going to save you memory.

nico_c++
Member #16,940
January 2019

No, but I can controll it. Dont mind it, it has nothing to do with the error.

Look,
I overwatch my (*tiles) vector. And all the variables are correct.
I had an excellent Idea.

After every (*tiles)[i].draw() i would do a al_rest(0.01).

And the positions are all correct.
Its just drawing the bitmaps wrong. Sometimes.
I even made a video, please look at it.
Maybe it can tell you more than it does to me.
VIDEO

Of course the Video Quality is super shitty, because I just have the free version and probably a bad PC, but you can see a little bit.
You can see, that every row and every line is drawn correctly.
Everytime you see a grey ... something, there is missing a line.

In the screenshot SCREENSHOT you can see with good quality what I mean!

Oh, and to your question.
These variables get standard constructed when creating my vector<TILE>.

MikiZX
Member #17,092
June 2019

Are you drawing directly to the display or to a separate bitmap which is then drawn to the screen scaled?
As Edgar suggested if you could provide more source code (only code related to the drawing - no need to disclose your entire program logic) or create a small separate project that re-creates the issue so we could test on our end it would greatly help in understanding the problem.

nico_c++
Member #16,940
January 2019

I am drawing directly to the Backbuffer.
And I dont understand to what you want to see more code.
Thats all there is related to the drawing.
I give them tiles their positions, and then I draw them on the buffer.
After that whole routine, I do an al_flip_display(), and thats it.

PLS CAN SOMEBODY HELP ME :((((((((((((
I get desperate!
Trying to fix this shit for more than 24 Hours! :,(

Edgar Reynaldo
Member #8,592
May 2007
avatar

Dude. Even I need to sleep once in a while.

EDIT
Often, the problem has nothing to do with the code you think it does. That's the messed up beauty of coding. If you want me to help, show more code, like your Tile class.

nico_c++
Member #16,940
January 2019

Okay, here you go:
Header

#SelectExpand
1class TILE 2{ 3private: 4 short *x_pos, *y_pos; 5 short *x_size, *y_size; 6 7 short *status; // 1 = Normal, 2 = Aufgedeckt 8 bool *bomb; // 0 = keine bombe, 1 = bombe 9 10 11public: 12 TILE(); 13 TILE(short _x_pos, short _y_pos); 14 void activate(void); 15 void draw(void); 16 void getBombed(void); 17 void getUnbombed(); 18 void getPositioned(short _x_pos, short _y_pos); 19 bool ISBOMBED(); 20 short STATUS(); 21 void DELETE(); 22}; 23 24class GAME 25{ 26private: 27 short x_size, y_size; 28 short maus_x, maus_y; 29 vector<short> *listofbombs; 30 31 vector<TILE> *tiles; 32 bool running; 33 34 ALLEGRO_EVENT event; 35 ALLEGRO_EVENT_QUEUE *eventqueue; 36 ALLEGRO_TIMER *timer; 37 38 short clickcounter; 39 40 double EXCounter; 41 42 43public: 44 GAME(); 45 void lose(void); 46 void plantbombs(void); 47 void losebombs(void); 48 void drawClickCounter(void); 49 void losingscreen(void); 50 void deleteTiles(); 51 void drawGraph(); 52 53 double EXPONENTIAL(double x); 54 55};

SOURCE

#SelectExpand
1TILE::TILE() 2{ 3 bomb = new bool(0); 4 status = new short(1); 5 x_pos = new short(0); 6 y_pos = new short(0); 7 x_size = new short(0); 8 y_size = new short(0); 9} 10 11TILE::TILE(short _x_pos, short _y_pos) 12{ 13 14} 15 16void TILE::activate(void) 17{ 18 *status = 2; 19} 20 21void TILE::draw(void) 22{ 23 if (*status == 1) 24 { 25 al_draw_bitmap(TILE_BITMAP_NORMAL, *x_pos, *y_pos, 0); 26 /*al_flip_display(); 27 al_rest(0.002);*/ //This is just for debugging purposes, to see, how each tile gets drawn 28 } 29 if (*status == 2) 30 { 31 if (*bomb == 1) al_draw_bitmap(TILE_BITMAP_RED, *x_pos, *y_pos, 0); 32 else al_draw_bitmap(TILE_BITMAP_GREEN, *x_pos, *y_pos, 0); 33 } 34 35} 36 37void TILE::getBombed(void) 38{ 39 *bomb = 1; 40} 41 42void TILE::getUnbombed() 43{ 44 *bomb = 0; 45} 46 47void TILE::getPositioned(short _x_pos, short _y_pos) 48{ 49 *x_pos = _x_pos; 50 *y_pos = _y_pos; 51} 52 53bool TILE::ISBOMBED() 54{ 55 return *bomb; 56} 57 58short TILE::STATUS() 59{ 60 return *status; 61} 62 63void TILE::DELETE() 64{ 65 x_pos = NULL; delete x_pos; 66 y_pos = NULL; delete y_pos; 67 x_size = NULL; delete x_size; 68 y_size = NULL; delete y_size; 69 status = NULL; delete status; 70 bomb = NULL; delete status; 71} 72 73 74 75GAME::GAME() 76{ 77 78 NEWGAME = 0; 79 x_size = 1100; 80 y_size = 1100; 81 82 tiles = new vector<TILE>(10000); 83 listofbombs = new vector<short>(0); 84 85 al_clear_to_color(*WHITE); 86 87 short INDEX_counter = 0; 88 89 for (int y = 1; y <= 100; y++) 90 { 91 for (int x = 1; x <= 100; x++) 92 { 93 (*tiles)[INDEX_counter].getPositioned(x * 10, y * 10); 94 (*tiles)[INDEX_counter].draw(); 95 INDEX_counter++; 96 } 97 } //POSITIONS 98 99 al_flip_display(); 100 [..........] }

In my main I just make a GAME newGame;

Edgar Reynaldo
Member #8,592
May 2007
avatar

This code is wrong, but it's not necessarily the problem.

Nico_C++ said:

void TILE::DELETE() {
   x_pos = NULL; delete x_pos;
   y_pos = NULL; delete y_pos;
   x_size = NULL; delete x_size;
   y_size = NULL; delete y_size;
   status = NULL; delete status;
   bomb = NULL; delete status;
}

That's the same thing as xpos = 0; delete 0;. Which means it is a memory leak.

There's no reason to be using dynamically allocated memory. You're over engineering the problem.

Something else to keep in mind is the Rule of Three.

You need to learn the difference between a shallow copy and a deep copy.

You need to learn the difference between the heap and the stack.

Look up RAII.

I still need to see more code.

nico_c++
Member #16,940
January 2019

[PART 1] (seems to long for a post)

There is not much more code right now XD
But I dont get why do you want to see more code.
I debugged the program to this point, and thats exactly the point where it is already drawn wrong. I mean, everything is there.
I give the positions, i draw them with this positions.
I can give you the part, where my newgame is allocated, but I dont know if thats for any help.
You know what, I give you the whole code.
minesweep.cpp

#SelectExpand
1// MineSweep.cpp : Diese Datei enthält die Funktion "main". Hier beginnt und endet die Ausführung des Programms. 2// 3 4#include "global.h" 5//ALLEGRO 6#include <allegro5\allegro.h> 7#include <allegro5\allegro_primitives.h> 8#include <allegro5\keyboard.h> 9#include <allegro5\allegro_ttf.h> 10#include <allegro5\allegro_font.h> 11#include <allegro5\allegro_image.h> 12#include <allegro5\allegro_audio.h> 13#include <allegro5\allegro_acodec.h> 14#include <allegro5\allegro_native_dialog.h> 15#include <allegro5\allegro_color.h> 16 17//INGAME 18#include "game.h" 19//STD 20#include <string> 21using namespace std; 22 23int main() 24{ 25 if (!(init())) return 0; //Initialisieren 26 init_colors(); //Farben für Menüs 27 28 al_set_new_display_flags(ALLEGRO_WINDOWED); 29 maindisplay = al_create_display(1920, 1080); //Display erstellen 30 31 bool runningMAIN = 1; 32 ALLEGRO_EVENT eventMAIN; 33 ALLEGRO_EVENT_QUEUE *eventqueueMAIN; 34 ALLEGRO_TIMER *timerMAIN; 35 TILE_BITMAP_NORMAL = al_load_bitmap("Pixel.bmp"); 36 TILE_BITMAP_GREEN = al_load_bitmap("Pixel_Gruen.bmp"); 37 TILE_BITMAP_RED = al_load_bitmap("Pixel_Rot.bmp"); 38 39 timerMAIN = al_create_timer(1.0 / 15.0); 40 eventqueueMAIN = al_create_event_queue(); 41 al_start_timer(timerMAIN); 42 al_register_event_source(eventqueueMAIN, al_get_display_event_source(maindisplay)); 43 al_register_event_source(eventqueueMAIN, al_get_keyboard_event_source()); 44 al_register_event_source(eventqueueMAIN, al_get_mouse_event_source()); 45 al_register_event_source(eventqueueMAIN, al_get_timer_event_source(timerMAIN)); 46 47 48 49 NEWGAME = 0; 50 MAINDRAWING = 1; 51 percentage = 50; 52 EXfactor = 0.98; 53 54 do 55 { 56 al_wait_for_event(eventqueueMAIN, &eventMAIN); //MAUS, KEYBOARD, usw. 57 58 if (MAINDRAWING == 1) 59 { 60 al_clear_to_color(*WHITE); 61 62 al_draw_text(font, *RED, 100, 60, 0, "N = Neues Spiel"); 63 al_draw_text(font, *RED, 100, 100, 0, "ESC = Beenden"); 64 al_draw_text(font, *RED, 100, 140, 0, "HOCH o. RUNTER = Prozentzahl ändern"); 65 al_draw_text(font, *RED, 100, 180, 0, "RECHTS o. LINKS = Faktor ändern"); 66 67 string TEXT = to_string(percentage) + " Prozent Bomben"; 68 al_draw_text(font, *BLACK, 150, 240, 0, TEXT.c_str()); 69 70 TEXT = to_string(EXfactor) + " -> Faktor, je niedriger, desto mehr Bomben werden gelöscht! 1 = Keine Veränderung"; 71 al_draw_text(font, *BLACK, 150, 260, 0, TEXT.c_str()); 72 73 al_flip_display(); 74 MAINDRAWING = false; 75 } 76 77 switch (eventMAIN.type) 78 { 79 case ALLEGRO_EVENT_KEY_DOWN: 80 al_get_keyboard_state(&keyboardstate); 81 if (al_key_down(&keyboardstate, ALLEGRO_KEY_ESCAPE)) runningMAIN = false; 82 if (al_key_down(&keyboardstate, ALLEGRO_KEY_N)) newGame = new GAME; 83 /*if (al_key_down(&keyboardstate, ALLEGRO_KEY_UP)) 84 { 85 if (percentage < 100) 86 { 87 percentage++; 88 MAINDRAWING = true; 89 } 90 } 91 if (al_key_down(&keyboardstate, ALLEGRO_KEY_DOWN)) 92 { 93 if (percentage > 0) 94 { 95 percentage--; 96 MAINDRAWING = true; 97 } 98 }*/ 99 break; 100 101 case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: 102 al_get_mouse_state(&mousestate); 103 break; 104 105 case ALLEGRO_EVENT_TIMER: 106 107 al_get_keyboard_state(&keyboardstate); 108 109 //MOVE MAP, bzw. Kamera 110 if (al_key_down(&keyboardstate, ALLEGRO_KEY_UP)) 111 { 112 if (percentage < 100) 113 { 114 percentage++; 115 MAINDRAWING = true; 116 } 117 } 118 if (al_key_down(&keyboardstate, ALLEGRO_KEY_DOWN)) 119 { 120 if (percentage > 0) 121 { 122 percentage--; 123 MAINDRAWING = true; 124 } 125 } 126 if (al_key_down(&keyboardstate, ALLEGRO_KEY_RIGHT)) 127 { 128 if (EXfactor < 1) 129 { 130 EXfactor+= 0.001; 131 MAINDRAWING = true; 132 } 133 } 134 if (al_key_down(&keyboardstate, ALLEGRO_KEY_LEFT)) 135 { 136 if (EXfactor > 0.001) 137 { 138 EXfactor -= 0.001; 139 MAINDRAWING = true; 140 } 141 } 142 break; 143 144 default: 145 al_flush_event_queue(eventqueueMAIN); 146 } 147 148 newGame = NULL; 149 delete newGame; 150 151 if (NEWGAME == 1) 152 { 153 NEWGAME = 0; 154 newGame = new GAME; 155 } 156 } while (runningMAIN); 157 158 159 al_destroy_event_queue(eventqueueMAIN); 160 al_destroy_timer(timerMAIN); 161 al_destroy_bitmap(TILE_BITMAP_NORMAL); 162 al_destroy_bitmap(TILE_BITMAP_RED); 163 al_destroy_bitmap(TILE_BITMAP_GREEN); 164 165 destroy(); 166 167 168 169} 170 171// Programm ausführen: STRG+F5 oder "Debuggen" > Menü "Ohne Debuggen starten" 172// Programm debuggen: F5 oder "Debuggen" > Menü "Debuggen starten"

global.h

#SelectExpand
1#pragma once 2//ALLEGRO 3#include <allegro5\allegro.h> 4#include <allegro5\allegro_primitives.h> 5#include <allegro5\keyboard.h> 6#include <allegro5\allegro_ttf.h> 7#include <allegro5\allegro_font.h> 8#include <allegro5\allegro_image.h> 9#include <allegro5\allegro_audio.h> 10#include <allegro5\allegro_acodec.h> 11#include <allegro5\allegro_native_dialog.h> 12#include <allegro5\allegro_color.h> 13 14//INGAME 15#include "game.h" 16 17//STD 18#include <string> 19 20 21 22//VORWÄRTSDEKLARATIONEN KLASSEN, wahrscheinlich gar nicht nötig 23class TILE; 24class GAME; 25class MAP; 26 27 28//GLOBALE VARIABLEN UND KLASSEN (EXTERN 29extern ALLEGRO_COLOR *BLUE, *RED, *GREEN, *BLACK, *YELLOW, *WHITE, *BROWN, *MENU_COLOR; //FARBEN 30 31extern ALLEGRO_FONT *font; 32 33extern ALLEGRO_DISPLAY *maindisplay; 34 35extern ALLEGRO_DISPLAY_MODE disp_data; //(DISPDATA) speichert momentane display einstellungen des systems 36 37extern ALLEGRO_KEYBOARD_STATE keyboardstate; 38extern ALLEGRO_MOUSE_STATE mousestate; //MAUSSTATUS (xpos, ypos usw;) 39 40 41extern ALLEGRO_BITMAP *TILE_BITMAP_GREEN; 42extern ALLEGRO_BITMAP *TILE_BITMAP_NORMAL; 43extern ALLEGRO_BITMAP *TILE_BITMAP_RED;//wäre unsinnig für jede Instanz einzeln zu definieren 44 45extern GAME *newGame; 46 47extern short percentage; 48extern double EXfactor; 49extern short position; 50//HIER FOLGT DANN AUCH DIE GLOBALE VEKTORDEFINITION FÜR DIE BITMAPS DER EINZELNEN UNITS UND TILES 51//Speichereffizienzfrage, -> in Arbeit 52 53extern bool NEWGAME; 54 55extern bool MAINDRAWING; 56 57//GLOBALE FUNKTIONEN 58 59extern int init(void); 60extern int init_colors(void); 61 62extern void destroy();

global.cpp

#SelectExpand
1#include "global.h" 2//ALLEGRO 3#include <allegro5\allegro.h> 4#include <allegro5\allegro_primitives.h> 5#include <allegro5\keyboard.h> 6#include <allegro5\allegro_ttf.h> 7#include <allegro5\allegro_font.h> 8#include <allegro5\allegro_image.h> 9#include <allegro5\allegro_audio.h> 10#include <allegro5\allegro_acodec.h> 11#include <allegro5\allegro_native_dialog.h> 12#include <allegro5\allegro_color.h> 13 14//INGAME 15#include "game.h" 16 17//STD 18#include <cstdlib> 19#include <ctime> 20#include <iostream> 21#include <string> 22 23 24ALLEGRO_COLOR *BLUE = NULL, *RED = NULL, *GREEN = NULL, *BLACK = NULL, *YELLOW = NULL, *WHITE = NULL, *BROWN = NULL, *MENU_COLOR = NULL; 25 26ALLEGRO_DISPLAY *maindisplay; 27ALLEGRO_DISPLAY_MODE disp_data; 28 29ALLEGRO_MOUSE_STATE mousestate; 30ALLEGRO_KEYBOARD_STATE keyboardstate; 31 32ALLEGRO_FONT *font; 33 34 35ALLEGRO_BITMAP *TILE_BITMAP_GREEN = NULL; 36ALLEGRO_BITMAP *TILE_BITMAP_NORMAL = NULL; 37ALLEGRO_BITMAP *TILE_BITMAP_RED = NULL; 38 39GAME *newGame; 40 41short percentage; 42short position; 43double EXfactor; 44 45bool NEWGAME; 46 47bool MAINDRAWING; 48 49 50 51 52int init(void) 53{ 54 al_init(); 55 al_init_primitives_addon(); 56 al_init_image_addon(); 57 al_init_font_addon(); 58 al_init_ttf_addon(); 59 al_install_keyboard(); 60 al_install_mouse(); 61 al_get_display_mode(al_get_num_display_modes() - 1, &disp_data); 62 std::srand(time(NULL)); 63 font = al_load_font("OpenSans-Bold.ttf", 20, 0); 64 return 1; 65} 66 67int init_colors(void) 68{ 69 BLUE = new ALLEGRO_COLOR(al_map_rgb(30, 144, 255)); 70 WHITE = new ALLEGRO_COLOR(al_map_rgb(255, 255, 255)); 71 RED = new ALLEGRO_COLOR(al_map_rgb(204, 0, 0)); 72 BLACK = new ALLEGRO_COLOR(al_map_rgb(0, 0, 0)); 73 YELLOW = new ALLEGRO_COLOR(al_map_rgb(255,255,0)); 74 GREEN = new ALLEGRO_COLOR(al_map_rgb(0, 255, 0)); 75 MENU_COLOR = new ALLEGRO_COLOR(al_map_rgb(0, 105, 107)); // a blue color 76 return 1; 77} 78 79void destroy(void) 80{ 81 delete BLUE; BLUE = nullptr; 82 delete WHITE; WHITE = nullptr; 83 delete RED; RED = nullptr; 84 delete BLACK; BLACK = nullptr; 85 delete MENU_COLOR; MENU_COLOR = nullptr; 86 delete YELLOW; YELLOW = nullptr; 87 88 89 if (font != NULL) al_destroy_font(font); 90 91 92 //Allegro 5 für Visual Studio macht das automatisch beim Austreten aus der MAIN 93 /*al_uninstall_keyboard(); 94 al_uninstall_mouse(); 95 al_shutdown_primitives_addon(); 96 al_shutdown_font_addon(); 97 al_shutdown_image_addon(); 98 al_shutdown_ttf_addon();*/ 99 100 al_destroy_display(maindisplay); 101}

Please write something, so I can make the part 2 with game.cpp
and game.h

Edgar Reynaldo
Member #8,592
May 2007
avatar

The problem is here :

Nico_C++ said:

minesweep.cpp#SelectExpand
147 148 newGame = NULL; 149 delete newGame; 150 151 if (NEWGAME == 1) 152 { 153 NEWGAME = 0; 154 newGame = new GAME; 155 } 156 } while (runningMAIN);

The code I quoted is run every time an event occurs. This means I need to see the GAME class.

It looks like a classic memory leak and dangling pointer.

Note that you're doing the same thing I warned you about before.

You're calling delete 0; again.

nico_c++
Member #16,940
January 2019

[PART 2]

game.h

#SelectExpand
1#pragma once 2#include "global.h" 3//ALLEGRO 4#include <allegro5\allegro.h> 5#include <allegro5\allegro_primitives.h> 6#include <allegro5\keyboard.h> 7#include <allegro5\allegro_ttf.h> 8#include <allegro5\allegro_font.h> 9#include <allegro5\allegro_image.h> 10#include <allegro5\allegro_audio.h> 11#include <allegro5\allegro_acodec.h> 12#include <allegro5\allegro_native_dialog.h> 13#include <allegro5\allegro_color.h> 14 15//INGAME 16 17 18//STD 19#include <vector> 20#include <string> 21using namespace std; 22 23class TILE 24{ 25private: 26 short *x_pos, *y_pos; 27 short *x_size, *y_size; 28 29 short *status; // 1 = Normal, 2 = Aufgedeckt 30 bool *bomb; // 0 = keine bombe, 1 = bombe 31 32 33public: 34 TILE(); 35 TILE(short _x_pos, short _y_pos); 36 void activate(void); 37 void draw(void); 38 void getBombed(void); 39 void getUnbombed(); 40 void getPositioned(short _x_pos, short _y_pos); 41 bool ISBOMBED(); 42 short STATUS(); 43 void DELETE(); 44}; 45 46class GAME 47{ 48private: 49 short x_size, y_size; 50 short maus_x, maus_y; 51 vector<short> *listofbombs; 52 53 vector<TILE> *tiles; 54 bool running; 55 56 ALLEGRO_EVENT event; 57 ALLEGRO_EVENT_QUEUE *eventqueue; 58 ALLEGRO_TIMER *timer; 59 60 short clickcounter; 61 62 double EXCounter; 63 64 65public: 66 GAME(); 67 void lose(void); 68 void plantbombs(void); 69 void losebombs(void); 70 void drawClickCounter(void); 71 void losingscreen(void); 72 void deleteTiles(); 73 void drawGraph(); 74 75 double EXPONENTIAL(double x); 76 77};

game.cpp

#SelectExpand
1#include "game.h" 2 3//ALLEGRO 4#include <allegro5\allegro.h> 5#include <allegro5\allegro_primitives.h> 6#include <allegro5\keyboard.h> 7#include <allegro5\allegro_ttf.h> 8#include <allegro5\allegro_font.h> 9#include <allegro5\allegro_image.h> 10#include <allegro5\allegro_audio.h> 11#include <allegro5\allegro_acodec.h> 12#include <allegro5\allegro_native_dialog.h> 13#include <allegro5\allegro_color.h> 14 15 16#include <stdio.h> 17#include <stdlib.h> 18#include <time.h> 19 20#include <vector> 21#include <string> 22using namespace std; 23 24// 1000 Mal 1000 Pixel 25// 100 Mal 100 Kästchen = 10000 Kästchen 26 27TILE::TILE() 28{ 29 bomb = new bool(0); 30 status = new short(1); 31 x_pos = new short(0); 32 y_pos = new short(0); 33 x_size = new short(0); 34 y_size = new short(0); 35} 36 37TILE::TILE(short _x_pos, short _y_pos) 38{ 39 40} 41 42void TILE::activate(void) 43{ 44 *status = 2; 45} 46 47void TILE::draw(void) 48{ 49 if (*status == 1) 50 { 51 al_draw_bitmap(TILE_BITMAP_NORMAL, *x_pos, *y_pos, 0); 52 al_flip_display(); 53 al_rest(0.002); 54 } 55 if (*status == 2) 56 { 57 if (*bomb == 1) al_draw_bitmap(TILE_BITMAP_RED, *x_pos, *y_pos, 0); 58 else al_draw_bitmap(TILE_BITMAP_GREEN, *x_pos, *y_pos, 0); 59 } 60 61} 62 63void TILE::getBombed(void) 64{ 65 *bomb = 1; 66} 67 68void TILE::getUnbombed() 69{ 70 *bomb = 0; 71} 72 73void TILE::getPositioned(short _x_pos, short _y_pos) 74{ 75 *x_pos = _x_pos; 76 *y_pos = _y_pos; 77} 78 79bool TILE::ISBOMBED() 80{ 81 return *bomb; 82} 83 84short TILE::STATUS() 85{ 86 return *status; 87} 88 89void TILE::DELETE() 90{ 91 x_pos = NULL; delete x_pos; 92 y_pos = NULL; delete y_pos; 93 x_size = NULL; delete x_size; 94 y_size = NULL; delete y_size; 95 status = NULL; delete status; 96 bomb = NULL; delete status; 97} 98 99 100 101GAME::GAME() 102{ 103 104 NEWGAME = 0; 105 x_size = 1100; 106 y_size = 1100; 107 108 tiles = new vector<TILE>(10000); 109 listofbombs = new vector<short>(0); 110 111 al_clear_to_color(*WHITE); 112 113 short INDEX_counter = 0; 114 115 for (int y = 1; y <= 100; y++) 116 { 117 for (int x = 1; x <= 100; x++) 118 { 119 (*tiles)[INDEX_counter].getPositioned(x * 10, y * 10); 120 (*tiles)[INDEX_counter].draw(); 121 INDEX_counter++; 122 } 123 } //POSITIONS 124 125 al_flip_display(); 126 127 plantbombs(); 128 129 running = true; 130 clickcounter = 0; 131 timer = al_create_timer(1.0 / 60.0); 132 eventqueue = al_create_event_queue(); 133 al_start_timer(timer); 134 al_register_event_source(eventqueue, al_get_display_event_source(maindisplay)); 135 al_register_event_source(eventqueue, al_get_keyboard_event_source()); 136 al_register_event_source(eventqueue, al_get_mouse_event_source()); 137 al_register_event_source(eventqueue, al_get_timer_event_source(timer)); 138 139 EXCounter = (*listofbombs).size(); 140 drawGraph(); 141 142 do 143 { 144 al_wait_for_event(eventqueue, &event); //MAUS, KEYBOARD, usw. 145 switch (event.type) 146 { 147 case ALLEGRO_EVENT_KEY_DOWN: 148 al_get_keyboard_state(&keyboardstate); 149 if (al_key_down(&keyboardstate, ALLEGRO_KEY_ESCAPE)) 150 { 151 running = false; 152 MAINDRAWING = true; 153 } 154 if (al_key_down(&keyboardstate, ALLEGRO_KEY_N)) 155 { 156 running = 0; 157 NEWGAME = 1; 158 } 159 break; 160 case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: 161 al_get_mouse_state(&mousestate); 162 maus_x = mousestate.x; 163 maus_y = mousestate.y; 164 165 if (maus_x < 1010 && maus_y < 1010 && maus_x > 10 && maus_y > 10) 166 { 167 maus_x /= 10; 168 maus_x *= 10; 169 if (maus_x > mousestate.x) maus_x -= 10; 170 maus_x /= 10; // Genaue X - Stelle Kästchen + 1 weiter 171 maus_x -= 1; 172 173 maus_y /= 10; 174 maus_y *= 10; 175 if (maus_y > mousestate.y) maus_y -= 10; 176 maus_y /= 10; // Genaue Y - Stelle Kästchen + 1 weiter 177 maus_y -= 1; 178 179 if ((*tiles)[maus_y * 100 + maus_x].ISBOMBED() == true) lose(); 180 else if ((*tiles)[maus_y * 100 + maus_x].STATUS() == 1) 181 { 182 (*tiles)[maus_y * 100 + maus_x].activate(); 183 (*tiles)[maus_y * 100 + maus_x].draw(); 184 al_flip_display(); 185 losebombs(); 186 clickcounter++; 187 drawClickCounter(); 188 } 189 } 190 191 192 193 break; 194 case ALLEGRO_EVENT_TIMER: 195 al_get_keyboard_state(&keyboardstate); 196 break; 197 198 default: 199 al_flush_event_queue(eventqueue); 200 } 201 202 } while (running); 203 204 205 al_destroy_event_queue(eventqueue); 206 eventqueue = nullptr; 207 al_destroy_timer(timer); 208 timer = nullptr; 209 210 deleteTiles(); 211 tiles = NULL; 212 listofbombs = NULL; 213 delete tiles; 214 delete listofbombs; 215} 216 217void GAME::lose(void) 218{ 219 (*tiles)[maus_y * 100 + maus_x].activate(); 220 (*tiles)[maus_y * 100 + maus_x].getBombed(); 221 (*tiles)[maus_y * 100 + maus_x].draw(); 222 for (int i = 0; i < (*listofbombs).size(); i++) 223 { 224 (*tiles)[(*listofbombs)[i]].activate(); 225 (*tiles)[(*listofbombs)[i]].getBombed(); 226 (*tiles)[(*listofbombs)[i]].draw(); 227 } 228 losingscreen(); 229} 230 231void GAME::plantbombs(void) 232{ 233 //TESTWEISE percentage hier definiert 234 //percentage = 1; 235 236 237 short numberofbombs = percentage * 100; 238 239 short counter = 0; 240 short RANDOM; 241 242 if (numberofbombs != 0) 243 { 244 do 245 { 246 RANDOM = rand() % 10000; 247 if ((*tiles)[RANDOM].ISBOMBED() == 0) 248 { 249 (*tiles)[RANDOM].getBombed(); 250 counter++; 251 (*listofbombs).push_back(RANDOM); 252 } 253 254 } while (counter != numberofbombs); 255 } 256 257} 258 259void GAME::losebombs(void) 260{ 261 double _EXCounter = EXCounter; 262 EXCounter = _EXCounter * EXfactor; 263 264 265 short NUMBERtoDelete = (short)(round((*listofbombs).size() - EXCounter)); 266 267 if ((*listofbombs).size() != 1 && (*listofbombs).size() != 0) 268 { 269 for (int i = 0; i < NUMBERtoDelete; i++) 270 { 271 short RANDOM = rand() % (*listofbombs).size(); 272 273 (*tiles)[(*listofbombs)[RANDOM]].getUnbombed(); 274 (*listofbombs).erase((*listofbombs).begin() + RANDOM); 275 } 276 } 277} 278 279void GAME::drawClickCounter(void) 280{ 281 al_draw_filled_rectangle(1200, 400, 1300, 425, *YELLOW); 282 string TEXT = to_string(clickcounter); 283 al_draw_text(font, *RED, 1200, 400, 0, TEXT.c_str()); 284 285 al_draw_filled_rectangle(1200, 500, 1450, 525, *YELLOW); 286 TEXT = "Anzahl der Bomben: " + to_string((*listofbombs).size()); 287 al_draw_text(font, *RED, 1200, 500, 0, TEXT.c_str()); 288 al_flip_display(); 289} 290 291void GAME::losingscreen(void) 292{ 293 do 294 { 295 al_draw_textf(font, *RED, 1100, 800, 0, "Sie haben verloren! R = Restart, H = Hauptmenü"); 296 al_flip_display(); 297 al_wait_for_event(eventqueue, &event); 298 switch (event.type) 299 { 300 case ALLEGRO_EVENT_KEY_DOWN: 301 al_get_keyboard_state(&keyboardstate); 302 if (al_key_down(&keyboardstate, ALLEGRO_KEY_R)) 303 { 304 running = 0; 305 NEWGAME = 1; 306 } 307 if (al_key_down(&keyboardstate, ALLEGRO_KEY_H)) 308 { 309 running = 0; 310 MAINDRAWING = 1; 311 } 312 break; 313 } 314 315 } while (running); 316} 317 318void GAME::deleteTiles() 319{ 320 for (int i = 0; i < (*tiles).size(); i++) 321 { 322 (*tiles)[i].DELETE(); 323 } 324} 325 326void GAME::drawGraph() 327{ 328 for (int i = 1; i <= 10000; i++) 329 { 330 al_draw_pixel((i/25 + 1100), (EXPONENTIAL(i)/25 + 300), *RED); 331 } 332 al_flip_display(); 333} 334 335double GAME::EXPONENTIAL(double x) 336{ 337 return -((*listofbombs).size() * pow(EXfactor, x)); 338}

Yea, I know, but the GAME is going in a loop and stays there.
So this shouldnt be a problem.
If you know what I mean

MikiZX
Member #17,092
June 2019

Hi Nico,
from what I can see your code looks OK. It is possible that something is wrong with the data used to draw the bitmaps and I believe Edgar will have a quick look to try to help you with this.

I am not an expert so I cannot help much but maybe you can try this (just for test):

-because your screenshot is in HD and you are creating a full hd window maybe try running your program with 650x650 window and see if the problem repeats (you might need to multiply the x and y position with 5 instead of 10 for the entire map to fit in the window)

-also, try running your program in full screen(using native resolution of your monitor) and see if the problem repeats

If you have the time to try these two things it is possible we can isolate the problem to a graphics end instead to memory data.

nico_c++
Member #16,940
January 2019

Hey Miki,

Fullscreen I already tried, it was the same.
And the resolution wont work because the bmps are 10x10 Pixels.
I can try to do the resolution with scaled bitmaps, but that I have to do later, because I am outside.

DanielH
Member #934
January 2001
avatar

Your code keeps changing. Where is your draw routine called now?

Also, besides the very beginning, do you draw your tiles at any other point?
EDIT: oh I see under your mouse event

What does this code do?

void GAME::drawGraph()
{
  for (int i = 1; i <= 10000; i++)
  {
    al_draw_pixel((i/25 + 1100), (EXPONENTIAL(i)/25 + 300), *RED);
  }
  al_flip_display();
}

Can you create a temp bitmap of the size of the grid? Draw the tiles to the temp bitmap and save it. Then upload as attachment. Just the tiles before anything else is done to them.

Just some helpful criticism, keep you logic separate from your drawing.
All drawing should be done in one place. You can use states and variables to differentiate what is drawn.

nico_c++
Member #16,940
January 2019

Yeah, thats true, but actually I have just one place where the most is drawn.
TILE:draw()
The GAME:drawGraph() just happens one time.
And I mean, you have the code, what dont you understand in it.
It plots a function on the screen.

I will try this with the temp bitmap.
You mean, i should create a new bitmap, set it as a target and save it as file?
Or what exactly do you mean?

DanielH
Member #934
January 2001
avatar

1st, fix your memory leaks.

Delete pointer then set to null

See if that does anything. Is it a memory leak issue or not?

2nd, are your bitmaps being loaded correctly? You don't check. I don't know what your tile bitmaps look like so I don't know.

3rd, My suggestion was yes to create temp bitmap, set as target, draw, save, delete. This should be done before any logic or loops.

You can add the image as an attachment like so
{"name":"612184","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/f\/8fd36c1ad264f294fee9c0ecf7c4fc4a.png","w":1920,"h":1080,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/f\/8fd36c1ad264f294fee9c0ecf7c4fc4a"}612184

4th, try a small program. Load 1 tile and draw the same 100x100 grid.

Go to: