Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Storing an array into a file & Comparing keyboard states.

This thread is locked; no one can reply to it. rss feed Print
Storing an array into a file & Comparing keyboard states.
jason perkins
Member #10,524
January 2009

Hi, I've got a couple quick questions. The biggest and most pressing is about saving arrays as a file. I simply don't understand it.

So right now I have this array of tiles, each tile contains two numbers. I'd like to save thoes numbers into a file. In such a way that I can assign thoes values back to an array of tiles again.

#SelectExpand
1for (int x = 0; x < sizeX; x++) 2{ 3 for (int y = 0; y < sizeY; y++) 4 { 5 tiles[x][y].setBmpIdX(selectedTile.getBmpIdX()); 6 tiles[x][y].setBmpIdY(selectedTile.getBmpIdY()); 7 } 8 9}

Hokay, so next is. I'm looking for an easy way to compare one ALLEGRO_KEYBOARD_STATE to another.

It would be great If I could just do something like:

#SelectExpand
1 2void CInputManager::checkInput() 3{ 4 kOldState = kState; 5 al_get_keyboard_state(&kState); 6} 7 8bool CInputManager::stateChange() 9{ 10 if (kOldState == kState) 11 { return false;} 12 else 13 { return true;} 14}

That doesn't work, I ended up working around it and did this:

#SelectExpand
1bool CInputManager::tab() 2{ 3 if (al_key_down(&kState, ALLEGRO_KEY_TAB) && !al_key_down(&kOldState, ALLEGRO_KEY_TAB) ) 4 {return true;} 5 else 6 {return false;} 7}

I can see that being really riddiculous to do if you where asking someone to print their character name or something. So I guess the question is still how can I compare the whole keyboard state?

Edgar Reynaldo
Member #8,592
May 2007
avatar

Jason Perkins said:

Hi, I've got a couple quick questions. The biggest and most pressing is about saving arrays as a file. I simply don't understand it.

It's not so bad. Use al_fopen, al_fwrite32le or al_fwrite32be and to read, use al_fread32le or al_fread32be and close the file with al_fclose.

Jason Perkins said:

I can see that being really riddiculous to do if you where asking someone to print their character name or something. So I guess the question is still how can I compare the whole keyboard state?

#SelectExpand
1enum KEYSTATE { 2 KEY_PRESS = 1, 3 KEY_RELEASE = 2, 4 KEY_HELD = 4, 5 KEY_OPEN = 8 6}; 7 8bool keys[ALLEGRO_KEY_MAX]; 9bool oldkeys[ALLEGRO_KEY_MAX]; 10int keystates[ALLEGRO_KEY_MAX]; 11ALLEGRO_KEY_STATE al_key_state; 12 13 14void init_keyboard_handler() { 15 for (int i = 0 ; i < ALLEGRO_KEY_MAX ; ++i) { 16 keys[i] = false; 17 oldkeys[i] = false; 18 } 19} 20 21void update_keyboard_handler() { 22 al_get_keyboard_state(&keystates); 23 for (int i = 0 ; i < ALLEGRO_KEY_MAX ; ++i) { 24 oldkeys[i] = keys[i]; 25 keys[i] = al_key_down(&keystates , i); 26 } 27 for (int i = 0 ; i < ALLEGRO_KEY_MAX ; ++i) { 28 if (keys[i] && !oldkeys[i]) {keystates[i] = KEY_PRESS;} 29 if (!keys[i] && oldkeys[i]) {keystates[i] = KEY_RELEASE;} 30 if (keys[i] && oldkeys[i]) {keystates[i] = KEY_HELD;} 31 if (!keys[i] && !oldkeys[i]) {keystates[i] = KEY_OPEN;} 32 } 33} 34 35bool key_press(int al_key_code) {return keystates[al_key_code] & KEY_PRESS;} 36bool key_release(int al_key_code) {return keystates[al_key_code] & KEY_RELEASE;} 37bool key_held(int al_key_code) {return keystates[al_key_code] & KEY_HELD;} 38bool key_open(int al_key_code) {return keystates[al_key_code] & KEY_OPEN;}

update_keyboard_handler();

if (key_press(ALLEGRO_KEY_ESCAPE)) {quit = true;}

Using keystates can be a problem if it takes too long between updates, so a lot of people will probably recommend using keyboard events instead though. That makes it harder to detect double clicks and key held durations though.

jason perkins
Member #10,524
January 2009

Thanks again, Edgar! That looks like it covers pretty much everything.
And about the files. I think I've got a bit of a handle on it. I'm about half way there. I decided to just go with <fstream> as it looks simpler :P.

LennyLen
Member #5,313
December 2004
avatar

I decided to just go with <fstream> as it looks simpler

The fstream routines will work fine if you are reading/writing as text. However, if you are working with binary data, different architectures will represent the data in different ways, so your code will no longer be portable to other platforms.

The Allegro routines take care of this problem.

Edgar Reynaldo
Member #8,592
May 2007
avatar

Jason Perkins said:

I decided to just go with <fstream> as it looks simpler

Word to the wise, if you use fstream, you will have to handle endianness on your own if you want your data to be portable to other computers besides your own. Using iostream's write function will write your data in the order it appears on the computer in use, and if you try to read it from a computer with different endianness, then you will get backwards data.

Stick with A5's file I/O and you'll be much better off. There are functions to read/write a char, read/write in little_endian/big_endian for shorts and ints. I wonder why there isn't a function for read/write'ing doubles though?

jason perkins
Member #10,524
January 2009

Okay, so I got it working... But it just seems like magic, I have no clue why this works.

To me this feels like:

step 1: poop in a box.

step 2: wait 3 seconds.

step 3: retrieve gold from box.

Could someone please explain this a little bit?

#SelectExpand
1 2void CMap::save(void) 3{ 4 mapfile = al_fopen("map.txt", "w"); 5 6 for (int x = 0; x <sizeX; x++) 7 { 8 for (int y = 0; y < sizeY; y++) 9 { 10 al_fwrite32le(mapfile, tiles[x][y].getBmpIdX()); 11 al_fwrite32le(mapfile, tiles[x][y].getBmpIdY()); 12 13 } 14 } 15 16 al_fclose(mapfile); 17} 18 19void CMap::load(void) 20{ 21 mapfile = al_fopen("map.txt", "r"); 22 for (int x = 0; x < sizeX; x++) 23 { 24 for (int y = 0; y<sizeY; y++) 25 { 26 27 tiles[x][y].setBmpIdX(al_fread32le(mapfile)); 28 tiles[x][y].setBmpIdY(al_fread32le(mapfile)); 29 tiles[x][y].setBmp(bmpArray[tiles[x][y].getBmpIdX()][tiles[x][y].getBmpIdY()]); 30 } 31 } 32 33 al_fclose(mapfile); 34}

Matthew Leverton
Supreme Loser
January 1999
avatar

If you poop gold into a box, you will be able to later retrieve it. What part of that is hard to understand? ???

Tobias Dammers
Member #2,604
August 2002
avatar

Could someone please explain this a little bit?

Here you go:

#SelectExpand
1 2void CMap::save(void) 3{ 4 // Open a file for writing: 5 mapfile = al_fopen("map.txt", "w"); 6 7 // Iterate over the 2D array: 8 for (int x = 0; x < sizeX; x++) 9 { 10 for (int y = 0; y < sizeY; y++) 11 { 12 // Write the BmpIdX value to the file 13 al_fwrite32le(mapfile, tiles[x][y].getBmpIdX()); 14 // Write the BmpIdY value to the file 15 al_fwrite32le(mapfile, tiles[x][y].getBmpIdY()); 16 17 } 18 } 19 20 // Close the file handle. 21 al_fclose(mapfile); 22 23 // For all intents and purposes, the file now contains a stream of bytes; 24 // each group of 4 bytes can be interpreted as a little-endian 32 bit integer, 25 // containing a bitmap ID. 26} 27 28void CMap::load(void) 29{ 30 // Open file for reading 31 mapfile = al_fopen("map.txt", "r"); 32 33 // Iterate over the array 34 for (int x = 0; x < sizeX; x++) 35 { 36 for (int y = 0; y < sizeY; y++) 37 { 38 // Load the BmpX and BmpY values from the file 39 tiles[x][y].setBmpIdX(al_fread32le(mapfile)); 40 tiles[x][y].setBmpIdY(al_fread32le(mapfile)); 41 // Get the corresponding bitmap from the bmpArray. 42 // It is probably a good idea to add range checks here, to prevent 43 // broken map files from requesting invalid bitmaps and causing 44 // segfaults or the like 45 tiles[x][y].setBmp(bmpArray[tiles[x][y].getBmpIdX()][tiles[x][y].getBmpIdY()]); 46 } 47 } 48 49 // Close the file 50 al_fclose(mapfile); 51}

Maybe you're having trouble wrapping your head around the way the 2D array gets serialized into a 1D sequence of 32 bit integers?

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

jason perkins
Member #10,524
January 2009

Maybe you're having trouble wrapping your head around the way the 2D array gets serialized into a 1D sequence of 32 bit integers?

Yeah after what you wrote there It makes sense though. My interpretation now is, everything I write to the file is writtin as a chunk of data, and that gets placed after the chunk written before it. Which I think is good enough for a pass now :P Thanks for making it clear.

Tobias Dammers
Member #2,604
August 2002
avatar

A file is just a bunch of bytes. When you store bytes in it, you can later retrieve them in the same order. al_fwrite32le is just a convenience function that takes a 32-bit integer, chops it into four bytes, and sends them to the file, one by one, starting with the most significant one. al_fread32le reads them back in, in the same order they were written, and combines them back into a 32 bit integer. That's all there is to it, really.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

Go to: