kettek2/wiki/games/newsboy/Newsboy_0x00/engine/FrameSheet.c

122 lines
3.4 KiB
C

#include <SDL2/SDL_image.h>
#include <stdlib.h>
#include "opengl.h"
#include "FrameSheet.h"
#include "fifo.h"
#include "report.h"
#include "string.h"
struct FrameSheet *newFrameSheet() {
struct FrameSheet *sheet = malloc(sizeof(struct FrameSheet));
sheet->textures = NULL;
sheet->surfaces = NULL;
sheet->count = 0;
sheet->state = 0;
return sheet;
}
struct FrameSheet *loadFrameSheet(const char *name, const char *framedir) {
if (framedir == NULL) return NULL;
struct Dir *dir = openDir(framedir, 0);
if (dir == NULL) {
report(ERROR, "loadFrameSheet", "dir %s does not exist", framedir);
return NULL;
}
struct FrameSheet *sheet = newFrameSheet();
struct DirEntry *entry;
while ((entry = readDir(dir)) != NULL) {
if (entry->d_type != F_REG) continue;
char *filename = NULL;
filename = setStringF(filename, "%s/%s", framedir, entry->d_name);
SDL_Surface *surface = NULL;
if ((surface = IMG_Load(filename)) == NULL) {
report(ERROR, "loadFrameSheet", "error loading surface: %s", SDL_GetError());
free(filename);
continue;
}
free(filename);
// seems valid, let's add it as a frame
sheet->count++;
sheet->surfaces = realloc(sheet->surfaces, sheet->count*sizeof(SDL_Surface*));
if (sheet->surfaces == NULL) {
report(ERROR, "loadFrameSheet", "could not realloc surfaces");
freeFrameSheet(sheet);
return NULL;
}
sheet->surfaces[sheet->count-1] = surface;
}
sheet->textures = realloc(sheet->textures, sheet->count*sizeof(GLuint));
closeDir(dir);
return sheet;
}
int freeFrameSheet(struct FrameSheet *sheet) {
if (sheet == NULL) return 1;
int i;
if (sheet->surfaces != NULL) {
for (i = 0; i < sheet->count; i++) {
SDL_FreeSurface(sheet->surfaces[i]);
}
free(sheet->surfaces);
}
// clean up textures if open
if (sheet->textures != NULL) {
closeFrameSheet(sheet);
free(sheet->textures);
}
free(sheet);
return 0;
}
int openFrameSheet(struct FrameSheet *sheet) {
if (sheet == NULL) return 1;
if (sheet->state == 0) {
int i;
for (i = 0; i < sheet->count; i++) {
sheet->textures[i] = createTexture(sheet->surfaces[i]);
}
}
sheet->state = 1;
return 0;
}
int closeFrameSheet(struct FrameSheet *sheet) {
if (sheet == NULL) return 1;
if (sheet->state == 1) {
int i;
for (i = 0; i < sheet->count; i++) {
glDeleteTextures(1, &sheet->textures[i]);
}
}
sheet->state = 0;
return 0;
}
int renderFrame(struct FrameSheet *sheet, int frame, int x, int y) {
if (sheet == NULL) return 1;
if (frame < 0 || frame >= sheet->count) return 2;
if (sheet->state == 0) {
openFrameSheet(sheet);
}
x -= sheet->surfaces[frame]->w/2;
y -= sheet->surfaces[frame]->h/2;
float sx = sheet->surfaces[frame]->w;
float sy = sheet->surfaces[frame]->h;
// bind our texture
glBindTexture(GL_TEXTURE_2D, sheet->textures[frame]);
// make sure we're rendering textures
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// reset view
glLoadIdentity();
// translate to a quad
glTranslated(x, y, 1.0f);
// draw !
glBegin(GL_QUADS);
// top left
glTexCoord2d(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
// top right
glTexCoord2d(1.0, 0.0f); glVertex2f(sx, 0.0f);
// bottom right
glTexCoord2d(1.0f, 1.0f); glVertex2f(sx, sy);
// bottom left
glTexCoord2d(0.0f, 1.0f); glVertex2f(0.0f, sy);
glEnd();
return 0;
}