SDL Issues

Hi,
I've been working through the lazyfoo tutorials for SDL and have been trying to make something as a small little project. I am trying to modify the Tiling tutorial with additional tiles and splitting it into many files. It compiles and links fine but that's about it. Upon running it simply loads the window with the title but then closes instantly. This has only started happening since I added in the tiling sections so I'm fairly certain its a problem there but I am stumped and very tired so any help would be greatly appreciated. I think I've included all the important files. If you want to see any more just shout. Thanks in advance.

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "SDL.h"
#include "constants.h"
#include "globals.h"
#include "functions.h"
#include "timer.h"
#include "player.h"
#include "tile.h"

int main( int argc, char* args[] )
{
	//The player
	Player myPlayer;

	//The tiles
	Tile *tiles[ TOTAL_TILES ];

	//Declare FPS Timer
	Timer fps;

	if( init() == false )
	{
		return 1;
	}
	
	if( load_files() == false )
	{
		return 1;
	}
	
	clip_tiles();

	//Set the tiles
	if( set_tiles( tiles ) == false )
	{
		return 1;
	}
	
	while( quit == false )
	{
		//Start FPS Counter
		fps.start();

		while( SDL_PollEvent( &event ) )
		{
			myPlayer.handle_input();

			if( event.type == SDL_QUIT )
			{
				quit = true;
			}
		}

		myPlayer.move( tiles );

		myPlayer.set_camera();

		for( int t = 0; t < TOTAL_TILES; t++ ) 
		{ 
			tiles[ t ]->show(); 
		}

		myPlayer.show();

		if( SDL_Flip( screen ) == -1 ) 
		{ 
			return 1; 
		}

		//Cap the frame rate
        if( fps.get_ticks() < 1000 / SCREEN_FPS )
        {
            SDL_Delay( ( 1000 / SCREEN_FPS ) - fps.get_ticks() );
        }
	}

	//Clean Up
	clean_up( tiles );

	return 0;
}


constants.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#ifndef CONSTANTS_H
#define CONSTANTS_H

//Screen Attributes
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;
const int SCREEN_BPP = 32;
const int SCREEN_FPS = 60;

//Level Dimensions
const int LEVEL_WIDTH = 1280;
const int LEVEL_HEIGHT = 960;

//Player Dimensions
const int PLAYER_WIDTH = 20;
const int PLAYER_HEIGHT = 20;

//Tile Constants
const int TILE_WIDTH = 40;
const int TILE_HEIGHT = 40;
const int TOTAL_TILES = 768;
const int TILE_SPRITES = 24;

//Tile Sprites
const int TILE_WATER = 0;
const int TILE_WATER_TL = 1;
const int TILE_WATER_TR = 2;
const int TILE_WATER_BL = 3;
const int TILE_WATER_BR = 4;

const int TILE_SAND = 5;
const int TILE_SAND_TL = 6;
const int TILE_SAND_TR = 7;
const int TILE_SAND_BL = 8;
const int TILE_SAND_BR = 9;

const int TILE_GRASS = 10;
const int TILE_GRASS_TL = 11;
const int TILE_GRASS_TR = 12;
const int TILE_GRASS_BL = 13;
const int TILE_GRASS_BR = 14;

const int TILE_ROCK = 15;
const int TILE_ROCK_TL = 16;
const int TILE_ROCK_TR = 17;
const int TILE_ROCK_BL = 18;
const int TILE_ROCK_BR = 19;

const int TILE_PATH = 20;
const int TILE_PATH_TL = 21;
const int TILE_PATH_TR = 22;
const int TILE_PATH_BL = 23;
const int TILE_PATH_BR = 24;

#endif 


globals.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#ifndef GLOBALS_H
#define GLOBALS_H

#include "SDL.h"
#include "constants.h"

//Quit flag
extern bool quit;

//SDL Surfaces
extern SDL_Surface *player;
extern SDL_Surface *screen;
extern SDL_Surface *tileSheet;

extern SDL_Rect clips[ TILE_SPRITES ];
extern SDL_Rect camera;

extern SDL_Event event;

#endif 


tile.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "SDL.h"
#include "globals.h"
#include "constants.h"
#include "functions.h"
#include "tile.h"

Tile::Tile( int x, int y, int tileType )
{
	//Get the offsets
	box.x = x;
	box.y = y;

	//Set the collision box
	box.w = TILE_WIDTH;
	box.h = TILE_HEIGHT;

	type = tileType;
}

void Tile::show()
{
	if( check_collision( camera, box ) == true )
	{
		//Show the tile
		apply_surface( box.x - camera.x, box.y - camera.y, tileSheet, screen, &clips[ type ] );
	}
}

int Tile::get_type()
{
	return type;
}

SDL_Rect Tile::get_box()
{
	return box;
}


player.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include "SDL.h"
#include "globals.h"
#include "constants.h"
#include "functions.h"
#include "player.h"

Player::Player()
{
    //Initialize the offsets
    box.x = 0;
    box.y = 0;
    box.w = PLAYER_WIDTH;
    box.h = PLAYER_HEIGHT;

    //Initialize the velocity
    xVel = 0;
    yVel = 0;
}

void Player::handle_input()
{
    //If a key was pressed
    if( event.type == SDL_KEYDOWN )
    {
        //Adjust the velocity
        switch( event.key.keysym.sym )
        {
            case SDLK_UP: yVel -= PLAYER_HEIGHT / 2; break;
            case SDLK_DOWN: yVel += PLAYER_HEIGHT / 2; break;
            case SDLK_LEFT: xVel -= PLAYER_WIDTH / 2; break;
            case SDLK_RIGHT: xVel += PLAYER_WIDTH / 2; break;
        }
    }
    //If a key was released
    else if( event.type == SDL_KEYUP )
    {
        //Adjust the velocity
        switch( event.key.keysym.sym )
        {
            case SDLK_UP: yVel += PLAYER_HEIGHT / 2; break;
            case SDLK_DOWN: yVel -= PLAYER_HEIGHT / 2; break;
            case SDLK_LEFT: xVel += PLAYER_WIDTH / 2; break;
            case SDLK_RIGHT: xVel -= PLAYER_WIDTH / 2; break;
        }
    }
}

void Player::move( Tile *tiles[] )
{
	//Move the dot left or right
    box.x += xVel;

    //If the dot went too far to the left or right or touched a wall
    if( ( box.x < 0 ) || ( box.x + PLAYER_WIDTH > LEVEL_WIDTH ) || touches_wall( box, tiles ) )
    {
        //move back
        box.x -= xVel;
    }

    //Move the dot up or down
    box.y += yVel;

    //If the dot went too far up or down or touched a wall
    if( ( box.y < 0 ) || ( box.y + PLAYER_HEIGHT > LEVEL_HEIGHT ) || touches_wall( box, tiles ) )
    {
        //move back
        box.y -= yVel;
    }
}

void Player::show()
{
    //Show the dot
    apply_surface( box.x - camera.x, box.y - camera.y, player, screen );
}

void Player::set_camera()
{
    //Center the camera over the dot
    camera.x = ( box.x + PLAYER_WIDTH / 2 ) - SCREEN_WIDTH / 2;
    camera.y = ( box.y + PLAYER_HEIGHT / 2 ) - SCREEN_HEIGHT / 2;

    //Keep the camera in bounds.
    if( camera.x < 0 )
    {
        camera.x = 0;
    }
    if( camera.y < 0 )
    {
        camera.y = 0;
    }
    if( camera.x > LEVEL_WIDTH - camera.w )
    {
        camera.x = LEVEL_WIDTH - camera.w;
    }
    if( camera.y > LEVEL_HEIGHT - camera.h )
    {
        camera.y = LEVEL_HEIGHT - camera.h;
    }
}
functions.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
#include <iostream>
#include <fstream>
#include <string>
#include "SDL.h"
#include "SDL_image.h"
#include "constants.h"
#include "globals.h"
#include "functions.h"
#include "tile.h"

bool init()
{
	//Initialize SDL
    if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
    {
        return false;
    }

    //Create Window
    if( SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE ) == NULL )
    {
        return false;
    }

	//Set caption
    SDL_WM_SetCaption( "YAZ SG", NULL );

    return true;
}

SDL_Surface *load_image( std::string filename ) 
{
    //The image that's loaded
    SDL_Surface* loadedImage = NULL;
    
    //The optimized surface that will be used
    SDL_Surface* optimizedImage = NULL;
    
    //Load the image
    loadedImage = IMG_Load( filename.c_str() );
    
    //If the image loaded
    if( loadedImage != NULL )
    {
        //Create an optimized surface
        optimizedImage = SDL_DisplayFormat( loadedImage );
        
        //Free the old surface
        SDL_FreeSurface( loadedImage );
        
        //If the surface was optimized
        if( optimizedImage != NULL )
        {
            //Color key surface
            SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF ) );
        }
    }
    
    //Return the optimized surface
    return optimizedImage;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip )
{
    //Holds offsets
    SDL_Rect offset;
    
    //Get offsets
    offset.x = x;
    offset.y = y;
    
    //Blit
    SDL_BlitSurface( source, clip, destination, &offset );
}

bool load_files()
{
    //Load the dot image
    player = load_image( "player.png" );

    //If there was a problem in loading the dot
    if( player == NULL )
    {
        return false;
    }

    //Load the tile sheet
    tileSheet = load_image( "terrain.png" );

    //If there was a problem in loading the tiles
    if( tileSheet == NULL )
    {
        return false;
    }

    //If everything loaded fine
    return true;
}

void clip_tiles()
{
    //Clip the sprite sheet
    clips[ TILE_WATER ].x = 0;
    clips[ TILE_WATER ].y = 0;
    clips[ TILE_WATER ].w = TILE_WIDTH;
    clips[ TILE_WATER ].h = TILE_HEIGHT;

	clips[ TILE_WATER_TL ].x = 40;
	clips[ TILE_WATER_TL ].y = 0;
	clips[ TILE_WATER_TL ].w = TILE_WIDTH;
	clips[ TILE_WATER_TL ].h = TILE_HEIGHT;

	clips[ TILE_WATER_TR ].x = 80;
	clips[ TILE_WATER_TR ].y = 0;
	clips[ TILE_WATER_TR ].w = TILE_WIDTH;
	clips[ TILE_WATER_TR ].h = TILE_HEIGHT;

	clips[ TILE_WATER_BL ].x = 120;
	clips[ TILE_WATER_BL ].y = 0;
	clips[ TILE_WATER_BL ].w = TILE_WIDTH;
	clips[ TILE_WATER_BL ].h = TILE_HEIGHT;

	clips[ TILE_WATER_BR ].x = 160;
	clips[ TILE_WATER_BR ].y = 0;
	clips[ TILE_WATER_BR ].w = TILE_WIDTH;
	clips[ TILE_WATER_BR ].h = TILE_HEIGHT;

	clips[ TILE_SAND ].x = 0;
	clips[ TILE_SAND ].y = 40;
	clips[ TILE_SAND ].w = TILE_WIDTH;
	clips[ TILE_SAND ].h = TILE_HEIGHT;

	clips[ TILE_SAND_TL ].x = 40;
	clips[ TILE_SAND_TL ].y = 40;
	clips[ TILE_SAND_TL ].w = TILE_WIDTH;
	clips[ TILE_SAND_TL ].h = TILE_HEIGHT;

	clips[ TILE_SAND_TR ].x = 80;
	clips[ TILE_SAND_TR ].y = 40;
	clips[ TILE_SAND_TR ].w = TILE_WIDTH;
	clips[ TILE_SAND_TR ].h = TILE_HEIGHT;

	clips[ TILE_SAND_BL ].x = 120;
	clips[ TILE_SAND_BL ].y = 40;
	clips[ TILE_SAND_BL ].w = TILE_WIDTH;
	clips[ TILE_SAND_BL ].h = TILE_HEIGHT;

	clips[ TILE_SAND_BR ].x = 160;
	clips[ TILE_SAND_BR ].y = 40;
	clips[ TILE_SAND_BR ].w = TILE_WIDTH;
	clips[ TILE_SAND_BR ].h = TILE_HEIGHT;

	clips[ TILE_GRASS ].x = 0;
	clips[ TILE_GRASS ].y = 80;
	clips[ TILE_GRASS ].w = TILE_WIDTH;
	clips[ TILE_GRASS ].h = TILE_HEIGHT;

	clips[ TILE_GRASS_TL ].x = 40;
	clips[ TILE_GRASS_TL ].y = 80;
	clips[ TILE_GRASS_TL ].w = TILE_WIDTH;
	clips[ TILE_GRASS_TL ].h = TILE_HEIGHT;

	clips[ TILE_GRASS_TR ].x = 80;
	clips[ TILE_GRASS_TR ].y = 80;
	clips[ TILE_GRASS_TR ].w = TILE_WIDTH;
	clips[ TILE_GRASS_TR ].h = TILE_HEIGHT;

	clips[ TILE_GRASS_BL ].x = 120;
	clips[ TILE_GRASS_BL ].y = 80;
	clips[ TILE_GRASS_BL ].w = TILE_WIDTH;
	clips[ TILE_GRASS_BL ].h = TILE_HEIGHT;

	clips[ TILE_GRASS_BR ].x = 160;
	clips[ TILE_GRASS_BR ].y = 120;
	clips[ TILE_GRASS_BR ].w = TILE_WIDTH;
	clips[ TILE_GRASS_BR ].h = TILE_HEIGHT;

	clips[ TILE_ROCK ].x = 0;
	clips[ TILE_ROCK ].y = 120;
	clips[ TILE_ROCK ].w = TILE_WIDTH;
	clips[ TILE_ROCK ].h = TILE_HEIGHT;

	clips[ TILE_ROCK_TL ].x = 40;
	clips[ TILE_ROCK_TL ].y = 120;
	clips[ TILE_ROCK_TL ].w = TILE_WIDTH;
	clips[ TILE_ROCK_TL ].h = TILE_HEIGHT;

	clips[ TILE_ROCK_TR ].x = 80;
	clips[ TILE_ROCK_TR ].y = 120;
	clips[ TILE_ROCK_TR ].w = TILE_WIDTH;
	clips[ TILE_ROCK_TR ].h = TILE_HEIGHT;

	clips[ TILE_ROCK_BL ].x = 120;
	clips[ TILE_ROCK_BL ].y = 120;
	clips[ TILE_ROCK_BL ].w = TILE_WIDTH;
	clips[ TILE_ROCK_BL ].h = TILE_HEIGHT;

	clips[ TILE_ROCK_BR ].x = 160;
	clips[ TILE_ROCK_BR ].y = 120;
	clips[ TILE_ROCK_BR ].w = TILE_WIDTH;
	clips[ TILE_ROCK_BR ].h = TILE_HEIGHT;

	clips[ TILE_PATH ].x = 0;
	clips[ TILE_PATH ].y = 160;
	clips[ TILE_PATH ].w = TILE_WIDTH;
	clips[ TILE_PATH ].h = TILE_HEIGHT;

	clips[ TILE_PATH_TL ].x = 40;
	clips[ TILE_PATH_TL ].y = 160;
	clips[ TILE_PATH_TL ].w = TILE_WIDTH;
	clips[ TILE_PATH_TL ].h = TILE_HEIGHT;

	clips[ TILE_PATH_TR ].x = 80;
	clips[ TILE_PATH_TR ].y = 160;
	clips[ TILE_PATH_TR ].w = TILE_WIDTH;
	clips[ TILE_PATH_TR ].h = TILE_HEIGHT;

	clips[ TILE_PATH_BL ].x = 120;
	clips[ TILE_PATH_BL ].y = 160;
	clips[ TILE_PATH_BL ].w = TILE_WIDTH;
	clips[ TILE_PATH_BL ].h = TILE_HEIGHT;

	clips[ TILE_PATH_BR ].x = 160;
	clips[ TILE_PATH_BR ].y = 160;
	clips[ TILE_PATH_BR ].w = TILE_WIDTH;
	clips[ TILE_PATH_BR ].h = TILE_HEIGHT;
}

bool set_tiles( Tile *tiles[] )
{
	//Tile offsets
	int x = 0, y = 0;

	//Open the tile map
	std::ifstream map( "home.bfs" );

	//If the map couldn't be loaded
	if( map == NULL )
	{
		return false;
	}

	//Initialise the tiles
	for( int t = 0; t < TOTAL_TILES; t++ )
	{
		//Determine type of tile
		int tileType = -1;

		//Read tile from map
		map >> tileType;

		//If an error happened
		if( map.fail() == true )
		{
			//Stop loading map
			map.close();
			return false;
		}

		//If its a valid tile
		if( ( tileType >= 0 ) && ( tileType < TILE_SPRITES ) )
		{
			tiles[ t ] = new Tile( x, y, tileType );
		}

		//If its not valid
		else
		{
			//Stop loading map
			map.close();
			return false;
		}

		//Move to the next tile
		x += TILE_WIDTH;

		//If too far
		if( x >= LEVEL_WIDTH )
		{
			//Move back
			x = 0;
			
			//Move to next row
			y += TILE_HEIGHT;
		}
	}

	//Close the map
	map.close();

	//If loaded fine
	return true;
}

bool touches_wall( SDL_Rect box, Tile *tiles[] )
{
	//Go through the tiles
	for( int t = 0; t < TOTAL_TILES; t++ )
    {
        //If the tile is a wall type tile
        if( ( tiles[ t ]->get_type() >= TILE_WATER ) && ( tiles[ t ]->get_type() <= TILE_WATER_BR ) )
        {
            //If the collision box touches the wall tile
            if( check_collision( box, tiles[ t ]->get_box() ) == true )
            {
                return true;
            }
        }
    }

    //If no wall tiles were touched
    return false;
}

bool check_collision( SDL_Rect A, SDL_Rect B )
{
    //The sides of the rectangles
    int leftA, leftB;
    int rightA, rightB;
    int topA, topB;
    int bottomA, bottomB;

    //Calculate the sides of rect A
    leftA = A.x;
    rightA = A.x + A.w;
    topA = A.y;
    bottomA = A.y + A.h;

    //Calculate the sides of rect B
    leftB = B.x;
    rightB = B.x + B.w;
    topB = B.y;
    bottomB = B.y + B.h;

    //If any of the sides from A are outside of B
    if( bottomA <= topB )
    {
        return false;
    }

    if( topA >= bottomB )
    {
        return false;
    }

    if( rightA <= leftB )
    {
        return false;
    }

    if( leftA >= rightB )
    {
        return false;
    }

    //If none of the sides from A are outside B
    return true;
}

What is the initial value of quit?

TILE_SPRITES == 24 when it should be 25.
quit is being initialised as false.

Thanks for pointing that out but unforutnately itis still happening.
You could print a message when something goes wrong so that you know what the problem is. It could be that it fails to load the images.
I've done that and its saying that it can't load the player.png image. I've checked the filename, its in all the directories that I can think might work. If I comment out the "player.png" loading section then the next problem arises at the set_tiles() function. More specifically this boils down to a problem with reading the map file. It appears to be loading it fine. The contents of my map file is

 
00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00


I don't get why one image load appears to work and the other doesnt'.

EDIT: Ok Im an idiot. I didn't have libPNG.dll in my Debug folder ><. So the images are now loading fine. Still getting errors reading the map though.
Last edited on
anyone?
Is that the whole map file? It's not containing as many numbers as TOTAL_TILES.
Last edited on
Yeah I'm an idiot. It now runs but is getting an unhandled exception at SDL_Flip(). It seems to be having a problem getting the information from screen. Not entirely sure why.
You never set screen to point to anything.
Topic archived. No new replies allowed.