![]() |
|
Drawing a level |
octotep
Member #11,180
July 2009
|
Hello everybody. For my game I'm trying to create a load_level function which loads a config file from disk to get all of the parameters for drawing the level. The problem is I have is in the level struct, where I have a int **, in order to hold the order of tiles to be drawn. The level struct looks like this: 1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <allegro5/allegro.h>
5
6#include "player.h"
7
8typedef struct level
9{
10 int size_x;
11 int size_y;
12 float start_x;
13 float start_y;
14 int tilesize;
15 int **tilemap;
16 ALLEGRO_BITMAP *tile_file;
17} level;
18
19extern level *load_level(int world_num, int level_num);
20extern void destroy_level(level *my_level);
21extern void setup_level(level *my_level, player *my_player);
The problem is in the load level function, where I try to assign the values from the config file to int **tilemap 1level *load_level(int world_num, int level_num)
2{
3 ALLEGRO_CONFIG *level_file;
4 level hard_level;
5 level *tmp_level;
6 tmp_level = &hard_level;
7 const char *tile_file_name; // for the tiles.bmp level.tile_file 31
8 char level_file_name[27]; // worldxx-levelyy.cfg 27
9
10 // Get all of the data from the level cfg file
11 sprintf(level_file_name, "levels/world%02d-level%02d.cfg", world_num, level_num);
12 level_file = al_load_config_file(level_file_name);
13 tmp_level->size_x = atoi(al_get_config_value(level_file, NULL, "size_x"));
14 tmp_level->size_y = atoi(al_get_config_value(level_file, NULL, "size_y"));
15 tmp_level->start_x = (float) atof(al_get_config_value(level_file, NULL, "start_x"));
16 tmp_level->start_y = (float) atof(al_get_config_value(level_file, NULL, "start_y"));
17 tmp_level->tilesize = atoi(al_get_config_value(level_file, NULL, "tilesize"));
18
19 // Get the tile file loaded into the level struct
20 tile_file_name = al_get_config_value(level_file, NULL, "tile_file");
21 tmp_level->tile_file = al_load_bitmap(tile_file_name);
22
23
24 // Create the tilemap array
25 tmp_level->tilemap = malloc(tmp_level->size_y * sizeof(int *));
26 if(tmp_level->tilemap == NULL)
27 {
28 fprintf(stderr, "Out of memory for the pointer-pointer-int in the level struct!\n");
29 return NULL;
30 }
31 int i;
32 for(i = 0; i < tmp_level->size_y; i++)
33 {
34 tmp_level->tilemap[i] = malloc(tmp_level->size_x * sizeof(int));
35 if(tmp_level->tilemap[i] == NULL)
36 {
37 fprintf(stderr, "Out of memory for the **intergers in the level struct!\n");
38 return NULL;
39 }
40 }
41
42 // Get the tilemap data from the cfg file
43 char *result = NULL;
44 const char *tilemap_data;
45 tilemap_data = al_get_config_value(level_file, NULL, "map_data");
46 result = strtok((char *)tilemap_data, ",");
47 int x = 0;
48 int y = 0;
49
50 while (result != NULL)
51 {
52 hard_level.tilemap[y][x] = atoi(result);
53 while(x < tmp_level->size_x)
54 {
55 hard_level.tilemap[y][x] = atoi(result);
56 result = strtok(NULL, ",");
57 x++;
58 }
59 x = 0;
60 result = strtok(NULL, ",");
61 y++;
62 }
63 fprintf(stderr, "done the strtok loop\n");
64
65 // See if the pointer was filled correctly
66 int b, c;
67 for(b = 0; b < tmp_level->size_y; b++)
68 {
69 for(c = 0; c < tmp_level->size_x; c++)
70 fprintf(stderr, "%i,", tmp_level->tilemap[b][c]);
71 }
72
73 al_destroy_config(level_file);
74 fprintf(stderr, "~~CREATE LEVEL - DONE~~\n");
75 return tmp_level;
76}
Inside the function, getting the values from a_level->tilemap[y][x] returns the expected values. Outside the function, a_level->tilemap[y][x] returns garbage values and crashes the program. The config file that I am using looks like this: size_x = 20 size_y = 15 start_x = 32.0 start_y = 416.0 tilesize = 32 tile_file = tiles/tiles.bmp map_data = 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,1,2,2,2,2,2,2,3,3,3,2,2,2,2,2,2,2,2,3,1,0,3,3,3,3,3,3,1,1,1,3,3,3,3,3,3,3,3,1,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,0,0 How would I need to change my code in order to access the **tilemap pointer and get correct values?
|
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
octotep said:
level hard_level; level *tmp_level;
You are returning the address of a temporary level object. As soon as load_level returns 'hard_level' is no longer a valid object. You have to create a new 'level' using malloc. It crashes because the area in memory where 'hard_level' was has most likely been overwritten or else it causes a segfault. 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 |
octotep
Member #11,180
July 2009
|
Ok, I think I see what the problem is now, but I have one more question. Could you point me in the right direction as to what I need to do to malloc() the level? Thanks
|
gnolam
Member #2,030
March 2002
![]() |
Since you're now dealing with a pointer to a struct instead of a struct itself, you're using the wrong member access operator - "." instead of "->". -- |
octotep
Member #11,180
July 2009
|
Hrm... I fixed that, but now my main loop always crashes when I try to access the tilemap (even though I allocate memory for that and the level struct pointer), while I can access the other values of the level struct just fine. 1 // In main, before the loop checking for events and after initializing
2 // everything
3 level *first_level;
4 first_level = load_level(current_world, current_level);
5 if(!first_level)
6 {
7 fprintf(stderr, "Couldnt create the level!\n");
8 // shutdown everything
9 return -1;
10 }
11 fprintf(stderr, "Back to main\n");
12 player *player;
13 player = create_player();
14 if(!player)
15 {
16 fprintf(stderr, "Couldnt create the player!\n");
17 // shutdown everything
18 return -1;
19 }
20 fprintf(stderr, "Back to main2\n");
21 al_set_new_bitmap_flags(0);
22 printf("Set the flag");
23 int level_x = SCREEN_W + (2 * first_level->tilesize);
24 int level_y = SCREEN_H + (2 * first_level->tilesize);
25 level_bitmap = al_create_bitmap(level_x, level_y);
26 if(!level_bitmap)
27 {
28 fprintf(stderr, "Couldn't create the level bitmap!\n");
29 // shutdown everything
30 return -1;
31 }
32
33 //crashes right here
34 int b, c;
35 for(b = 0; b < first_level->size_y; b++)
36 {
37 for(c = 0; c < first_level->size_x; c++)
38 fprintf(stderr, "%i,", first_level->tilemap[b][c]);
39 }
I feel bad for asking so many questions, because I feel that there's just one really stupid thing I'm missing...
|
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Post your latest load_level function. Either level->size_y or level->size_x is wrong, or you are not allocating level->tilemap correctly. 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 |
octotep
Member #11,180
July 2009
|
Here it is: 1level *load_level(int world_num, int level_num)
2{
3 ALLEGRO_CONFIG *level_file;
4 level *tmp_level = malloc(sizeof(level *));
5 if(tmp_level == NULL)
6 {
7 fprintf(stderr, "Out of memory for the level struct!\n");
8 return NULL;
9 }
10 printf("Break here!\n");
11
12 const char *tile_file_name; // for the tiles.bmp level.tile_file 31
13 char level_file_name[27]; // worldxx-levelyy.cfg 27
14
15 // Get all of the data from the level cfg file
16 sprintf(level_file_name, "levels/world%02d-level%02d.cfg", world_num, level_num);
17 level_file = al_load_config_file(level_file_name);
18 tmp_level->size_x = atoi(al_get_config_value(level_file, NULL, "size_x"));
19 tmp_level->size_y = atoi(al_get_config_value(level_file, NULL, "size_y"));
20 tmp_level->start_x = (float) atof(al_get_config_value(level_file, NULL, "start_x"));
21 tmp_level->start_y = (float) atof(al_get_config_value(level_file, NULL, "start_y"));
22 //without this, I can't access tilesize from outside this function...
23 tmp_level->tilesize = (int) malloc(sizeof(int));
24 tmp_level->tilesize = (int) atoi(al_get_config_value(level_file, NULL, "tile_size"));
25
26 // Get the tile file loaded into the level struct
27 tile_file_name = al_get_config_value(level_file, NULL, "tile_file");
28 tmp_level->tile_file = al_load_bitmap(tile_file_name);
29 if(!tmp_level->tile_file)
30 {
31 printf("TILE FILE NOT LOADED!\n");
32 return NULL;
33 }
34
35
36 // Create the tilemap array
37 tmp_level->tilemap = malloc(tmp_level->size_y * sizeof(int *));
38 if(tmp_level->tilemap == NULL)
39 {
40 fprintf(stderr, "Out of memory for the pointer-pointer-int in the level struct!\n");
41 return NULL;
42 }
43 int i;
44 for(i = 0; i < tmp_level->size_y; i++)
45 {
46 tmp_level->tilemap[i] = malloc(tmp_level->size_x * sizeof(int));
47 if(tmp_level->tilemap[i] == NULL)
48 {
49 fprintf(stderr, "Out of memory for the **intergers in the level struct!\n");
50 return NULL;
51 }
52 }
53
54
55 // Get the tilemap data from the cfg file
56 char *result = NULL;
57 const char *tilemap_data;
58 tilemap_data = al_get_config_value(level_file, NULL, "map_data");
59 result = strtok((char *)tilemap_data, ",");
60 int x = 0;
61 int y = 0;
62
63 while (result != NULL)
64 {
65 tmp_level->tilemap[y][x] = atoi(result);
66 while(x < tmp_level->size_x)
67 {
68 tmp_level->tilemap[y][x] = atoi(result);
69 result = strtok(NULL, ",");
70 x++;
71 }
72 x = 0;
73 result = strtok(NULL, ",");
74 y++;
75 }
76
77 int b, c;
78 for(b = 0; b < tmp_level->size_y; b++)
79 {
80 for(c = 0; c < tmp_level->size_x; c++)
81 fprintf(stderr, "%i,", tmp_level->tilemap[b][c]);
82 }
83
84 al_destroy_config(level_file);
85 printf("%i\n", tmp_level->tilesize);
86 fprintf(stderr, "~~CREATE LEVEL - DONE~~\n");
87 return tmp_level;
88}
|
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
That should be level* tmp_level = malloc(sizeof(level));, like you had it before. You're only allocating enough memory to hold a pointer. octotep said:
//without this, I can't access tilesize from outside this function... // tmp_level->tilesize = (int) malloc(sizeof(int)); tmp_level->tilesize = atoi(al_get_config_value(level_file, NULL, "tile_size"));
The line I commented out (the second one) is not good C. You allocate an integer's worth of memory and then cast that address to an integer - it's value would likely be huge, and totally incorrect. The third line there is correct. octotep said:
1 tilemap_data = al_get_config_value(level_file, NULL, "map_data");
2 result = strtok((char *)tilemap_data, ",");
3 int x = 0;
4 int y = 0;
5
6 while (result != NULL)
7 {
8// tmp_level->tilemap[y][x] = atoi(result);// this is not necessary
9 while(x < tmp_level->size_x)
10 {
11 tmp_level->tilemap[y][x] = atoi(result);
12 result = strtok(NULL, ",");
13 x++;
14 }
15 x = 0;
16// result = strtok(NULL, ",");// You're skipping a token here
17 y++;
18 }
I commented out two lines - the first commented line is unnecessary and is overwritten by your second assignment, and the second commented line is a mistake, because it would skip one of your values. 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 |
octotep
Member #11,180
July 2009
|
Thank you, it works perfectly!
|
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Glad to hear it. Got a screenshot you could show us? 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 |
octotep
Member #11,180
July 2009
|
Here's one. Unfortunately I'm not the best artist, so all I have right now is a stick figure for testing purposes.
|
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Well, your basic ground tile looks good. It blends perfectly with the tiles next to it. 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 |
|