Advertisement

SDL tilemap overlapping player

Started by October 11, 2011 12:43 AM
-1 comments, last by KellerHood 13 years, 1 month ago
I'm using SDL for an RPG I am making, and it seems that the tilemap I am rendering is overlapping the player object. Even though I am drawing the player after the tiles. And only some tiles will overlap him.
Take this diagram ([O] being a tile that would not overlap the player,

being the player, and [X ] being a tile that overlaps the player):
[O][O][O][O][O]
[O][O][O][O][O]
[O][O]

[X ][X ]
[X ][X ][X ][X ][X ]
[X ][X ][X ][X ][X ]

All tiles that are both below the player and to his right overlap him. But not any of the others.
I have a tilemap struct and a sprite struct. The tilemap has an array of tiles and an array of entities.
Written in plain C, here is tilemap.h:


#ifndef TILEMAP_H
#define TILEMAP_H

/*TODO: Change the entities array to only one dimension*/

/*
Tilemaps have two layers: An image layer and an entity layer.
Images do not move. They cannot destroyed in any way.
Entities can move, and can be destroyed. Entities also have underlying images upon creation.
*/
#include "sprite.h"
#include "player.h"
typedef struct
{
int** tiles; /*numeric index for each tile*/
sprite*** images; /*array of sprites to draw*/
sprite*** entities; /*array of entities to maintain and draw*/
int w, h;
} tilemap;

tilemap* new_tilemap(int w, int h, const char* filename)
{
tilemap* tm = malloc(sizeof(tilemap));
tm->w = w;
tm->h = h;
tm->tiles = malloc(sizeof(int*) * h);
int i;
for (i = 0; i < h; ++i)
{
tm->tiles = malloc(sizeof(int) * w);
}

tm->entities = malloc(sizeof(sprite**) * h);
for (i = 0; i < h; ++i)
{
tm->entities = malloc(sizeof(sprite*) * w);
}

FILE* file = fopen (filename, "rb");
if (file == NULL)
{
printf("Failed to open map %s\n", filename);
}
int j;
for (j = 0; j < h; ++j)
{
for (i = 0; i < w; ++i)
{
fscanf(file, "%d", &(tm->tiles[j]));
}
}
fclose(file);

tm->images = malloc(sizeof(sprite**) * h);
for (i = 0; i < h; ++i)
{
tm->images = malloc(sizeof(sprite*) * w);
}
for (j = 0; j < h; ++j)
{
for (i = 0; i < w; ++i)
{
switch (tm->tiles[j])
{
case 0:
tm->images[j] = new_sprite_file("dat/tiles/0.bmp", 1);
tm->entities[j] = NULL;
break;
case 1:
tm->images[j] = new_sprite_file("dat/tiles/1.bmp", 2);
tm->entities[j] = NULL;
break;
case 2:
tm->images[j] = new_sprite_file("dat/tiles/0.bmp", 1);
tm->tiles[j] = 0;
tm->entities[j] = new_player();
break;
default:
tm->images[j] = NULL;
tm->entities[j] = NULL;
break;
}
tm->images[j]->x = i*tm->images[j]->w;
tm->images[j]->y = j*tm->images[j]->h;
if(tm->entities[j] != NULL)
{
tm->entities[j]->x = i*tm->entities[j]->w;
tm->entities[j]->y = j*tm->entities[j]->h;
}
}
}
return tm;
}

/*DRAWING CODE FOR THE TILEMAP HERE*/
void render_tilemap(tilemap* tm, SDL_Surface* dest)
{
int i, j;
for (j = 0; j < tm->h; ++j)
{
for (i = 0; i < tm->w; ++i)
{
sprite* img = tm->images[j];
if (img != NULL)
{
img->update(img);
render_sprite(img, dest);
}
sprite* ent = tm->entities[j];
if (ent != NULL)
{
ent->update(ent);
render_sprite(ent, dest);
}
}
}
}

void free_tilemap(tilemap* tm)
{
int i, j;
for (i = 0; i < tm->h; ++i)
{
free(tm->tiles);
}
free(tm->tiles);

for (j = 0; j < tm->h; ++j)
{
for (i = 0; i < tm->w; ++i)
{
SDL_FreeSurface(tm->images[j]->image);
free(tm->images[j]);
}
}
for (i = 0; i < tm->h; ++i)
{
free(tm->images);
}
free(tm->images);

for (j = 0; j < tm->h; ++j)
{
for (i = 0; i < tm->w; ++i)
{
if(tm->entities[j] != NULL)
{
SDL_FreeSurface(tm->entities[j]->image);
free(tm->entities[j]);
}
}
}
for (i = 0; i < tm->h; ++i)
{
free(tm->entities);
}
free(tm->entities);
free(tm);
}
#endif



And here is sprite.h:


#ifndef SPRITE_H
#define SPRITE_H
#include <stdlib.h>
#include <SDL/SDL.h>

typedef struct sprite sprite;

struct sprite
{
SDL_Surface* image;
SDL_Rect bbox;
float x;
float y;
int w;
int h;
float frame;
int framenumber;
float speed;
int frames;
void(*update)(sprite* this); /*To be overidden by subtypes*/
};
void sprite_update(sprite* this)
{
this->bbox.x = this->x;
this->bbox.y = this->y;
if (this->frames > 1) /*If there is even an animation to play*/
{
if (this->frame > this->frames-0.5f)
this->frame = 0;
else
this->frame+=this->speed;
this->framenumber = (int)(this->frame);
}
}

sprite* new_sprite() /*to be overidden by subtypes*/
{
sprite* s = malloc(sizeof(sprite));
SDL_Surface* image = SDL_LoadBMP("dat/defaults.bmp");
SDL_Surface* opimage = SDL_DisplayFormat(image);
SDL_FreeSurface(image);
*s = (const sprite)
{
.image = opimage,
.x = 0,
.y = 0,
.frame = 0,
.speed = 0.0f,
.frames = 1,
.framenumber = 0,
.update = *sprite_update
};
s->w = s->image->w/s->frames;
s->h = s->image->h;
s->bbox = (const SDL_Rect){.x = s->x, .y = s->y, .w = s->w, .h = s->h};

Uint32 colorkey=SDL_MapRGB(s->image->format, 255, 0, 255);
SDL_SetColorKey(s->image, SDL_RLEACCEL | SDL_SRCCOLORKEY, colorkey);

return s;
}
sprite* new_sprite_file(const char* filename, int frames) /*to be overidden by subtypes*/
{
sprite* s = malloc(sizeof(sprite));
SDL_Surface* image = SDL_LoadBMP(filename);
SDL_Surface* opimage = SDL_DisplayFormat(image);
SDL_FreeSurface(image);
*s = (const sprite)
{
.image = opimage,
.x = 0,
.y = 0,
.frame = 0,
.speed = 0.125f,
.frames = frames,
.framenumber = 0,
.update = *sprite_update
};
s->w = s->image->w/s->frames;
s->h = s->image->h;
s->bbox = (const SDL_Rect){.x = s->x, .y = s->y, .w = s->w, .h = s->h};

Uint32 colorkey=SDL_MapRGB(s->image->format, 255, 0, 255);
SDL_SetColorKey(s->image, SDL_RLEACCEL | SDL_SRCCOLORKEY, colorkey);

return s;
}

void render_sprite(sprite* s, SDL_Surface* dest)
{
SDL_Rect currentframe;
currentframe = (const SDL_Rect){.x = s->framenumber * s->w, .y = 0, .w = s->w, .h = s->h};
SDL_BlitSurface(s->image, &currentframe, dest, &(s->bbox));
}
#endif


And finally, player.h:


/*'player' subtype of the 'sprite' class*/
#ifndef PLAYER_H
#define PLAYER_H
#include "sprite.h"

extern int g_key[321];

void player_update(sprite* this)
{
this->bbox.x = this->x;
this->bbox.y = this->y;
if (this->frames > 1) /*If there is even an animation to play*/
{
if (this->frame > this->frames-0.5f)
this->frame = 0;
else
this->frame+=this->speed;
this->framenumber = (int)(this->frame);
}
if (g_key[SDLK_LEFT])
if(this->x > 0)
this->x -= 1;
if (g_key[SDLK_RIGHT])
if (this->x+this->w < 160)
this->x += 1;
if (g_key[SDLK_UP])
if (this->y > 0)
this->y -= 1;
if (g_key[SDLK_DOWN])
if (this->y+this->h < 144)
this->y += 1;
}

sprite* new_player()
{
sprite* s = malloc(sizeof(sprite));
SDL_Surface* image = SDL_LoadBMP("dat/linkwalkd.bmp");
SDL_Surface* opimage = SDL_DisplayFormat(image);
SDL_FreeSurface(image);
*s = (const sprite)
{
.image = opimage,
.x = 0,
.y = 0,
.frame = 0,
.speed = 0.125f,
.frames = 2,
.framenumber = 0,
.update = *player_update
};
s->w = s->image->w/s->frames;
s->h = s->image->h;
s->bbox = (const SDL_Rect){.x = s->x, .y = s->y, .w = s->w, .h = s->h};

Uint32 colorkey=SDL_MapRGB(s->image->format, 255, 0, 255);
SDL_SetColorKey(s->image, SDL_RLEACCEL | SDL_SRCCOLORKEY, colorkey);

return s;
}

#endif


I think the error may have something to do with the bbox member of the player, but I'm not sure. I can't see where this problem is coming from, and if it's SDL related or related to my own logic.

EDIT: Never mind. Simply separated the drawing of the entities and the drawing of the tiles to two separate loops.

This topic is closed to new replies.

Advertisement