source: trunk/src/tileset.cpp @ 633

Last change on this file since 633 was 633, checked in by sam, 10 years ago

TileSets can now be initialised either using the tile size, or the
known number of tiles in a row and a column. Necessary for ticket #24.

  • Property svn:keywords set to Id
File size: 4.5 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <cstdlib>
16#include <cmath>
17
18#ifdef WIN32
19#   define WIN32_LEAN_AND_MEAN
20#   include <windows.h>
21#endif
22#if defined __APPLE__ && defined __MACH__
23#   include <OpenGL/gl.h>
24#else
25#   define GL_GLEXT_PROTOTYPES
26#   include <GL/gl.h>
27#endif
28
29#include <SDL.h>
30#include <SDL_image.h>
31
32#include "core.h"
33
34/*
35 * TileSet implementation class
36 */
37
38class TileSetData
39{
40    friend class TileSet;
41
42private:
43    char *name, *path;
44    int *tiles, ntiles;
45    int2 size, count;
46    float dilate, tx, ty;
47
48    SDL_Surface *img;
49    GLuint texture;
50};
51
52/*
53 * Public TileSet class
54 */
55
56TileSet::TileSet(char const *path, int2 size, int2 count, float dilate)
57  : data(new TileSetData())
58{
59    data->name = (char *)malloc(10 + strlen(path) + 1);
60    data->path = data->name + 10;
61    sprintf(data->name, "<tileset> %s", path);
62
63    data->tiles = NULL;
64    data->img = NULL;
65    data->texture = 0;
66
67    for (char const *name = path; *name; name++)
68        if ((data->img = IMG_Load(name)))
69            break;
70
71    if (!data->img)
72    {
73#if !FINAL_RELEASE
74        fprintf(stderr, "ERROR: could not load %s\n", path);
75#endif
76        SDL_Quit();
77        exit(1);
78    }
79
80    if (count.i > 0 && count.j > 0)
81    {
82        data->count = count;
83        data->size = int2(data->img->w, data->img->h) / count;
84    }
85    else
86    {
87        if (size.x <= 0 || size.y <= 0)
88            size = 32;
89        data->count.i = data->img->w > size.i ? data->img->w / size.i : 1;
90        data->count.j = data->img->h > size.j ? data->img->h / size.j : 1;
91        data->size = size;
92    }
93
94    data->dilate = dilate;
95    data->ntiles = data->count.i * data->count.j;
96    data->tx = (float)data->size.x / PotUp(data->img->w);
97    data->ty = (float)data->size.y / PotUp(data->img->h);
98
99    drawgroup = DRAWGROUP_BEFORE;
100}
101
102TileSet::~TileSet()
103{
104    free(data->tiles);
105    free(data->name);
106    delete data;
107}
108
109void TileSet::TickDraw(float deltams)
110{
111    Entity::TickDraw(deltams);
112
113    if (IsDestroying())
114    {
115        if (data->img)
116            SDL_FreeSurface(data->img);
117        else
118            glDeleteTextures(1, &data->texture);
119    }
120    else if (data->img)
121    {
122        GLuint format = data->img->format->Amask ? GL_RGBA : GL_RGB;
123        int planes = data->img->format->Amask ? 4 : 3;
124
125        int w = PotUp(data->img->w);
126        int h = PotUp(data->img->h);
127
128        uint8_t *pixels = (uint8_t *)data->img->pixels;
129        if (w != data->img->w || h != data->img->h)
130        {
131            uint8_t *tmp = (uint8_t *)malloc(planes * w * h);
132            for (int line = 0; line < data->img->h; line++)
133                memcpy(tmp + planes * w * line,
134                       pixels + planes * data->img->w * line,
135                       planes * data->img->w);
136            pixels = tmp;
137        }
138
139        glGenTextures(1, &data->texture);
140        glBindTexture(GL_TEXTURE_2D, data->texture);
141
142        glTexImage2D(GL_TEXTURE_2D, 0, planes, w, h, 0,
143                     format, GL_UNSIGNED_BYTE, pixels);
144
145        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
146        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
147
148        if (pixels != data->img->pixels)
149            free(pixels);
150        SDL_FreeSurface(data->img);
151        data->img = NULL;
152    }
153}
154
155char const *TileSet::GetName()
156{
157    return data->name;
158}
159
160void TileSet::BlitTile(uint32_t id, int x, int y, int z, int o)
161{
162    float tx = data->tx * ((id & 0xffff) % data->count.i);
163    float ty = data->ty * ((id & 0xffff) / data->count.i);
164    float dilate = data->dilate;
165
166    int dx = data->size.x;
167    int dy = o ? 0 : data->size.y;
168    int dz = o ? data->size.y : 0;
169
170    if (!data->img)
171    {
172        glBindTexture(GL_TEXTURE_2D, data->texture);
173        glBegin(GL_QUADS);
174            glTexCoord2f(tx, ty);
175            glVertex3f(x, dilate * (y + dy), dilate * (z + dz));
176            glTexCoord2f(tx + data->tx, ty);
177            glVertex3f(x + dx, dilate * (y + dy), dilate * (z + dz));
178            glTexCoord2f(tx + data->tx, ty + data->ty);
179            glVertex3f(x + dx, dilate * y, dilate * z);
180            glTexCoord2f(tx, ty + data->ty);
181            glVertex3f(x, dilate * y, dilate * z);
182        glEnd();
183    }
184}
185
Note: See TracBrowser for help on using the repository browser.