Merge branch 'stage'
[cantaveria.git] / graphics.c
blob7d704a051373c818a073869a072b5093c08861fc
1 /*
2 Cantaveria - action adventure platform game
3 Copyright (C) 2009 2010 Evan Rinehart
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to
18 The Free Software Foundation, Inc.
19 51 Franklin Street, Fifth Floor
20 Boston, MA 02110-1301, USA
22 evanrinehart@gmail.com
24 /* graphics */
26 /* these graphics routines wrap video.c low level stuff */
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <math.h>
34 #include <list.h>
35 #include <util.h>
36 #include <input.h>
37 #include <kernel.h>
38 #include <video.h>
39 #include <graphics.h>
40 #include <loader.h>
41 #include <console.h>
45 /* graphics data */
46 sprite* sprites[MAX_SPRITES];
47 int sprite_count = 0;
49 animation* animations[MAX_ANIMATIONS];
50 int anim_count = 0;
52 int minifont_gfx = 0;
56 int stage_enabled = 0;
60 struct {
61 int x, y;
62 } camera;
65 void graphics_init(){
66 int i;
67 minifont_gfx = load_gfx("smallfont.tga");
68 for(i=0; i<MAX_ANIMATIONS; i++){
69 animations[i] = NULL;
74 /* drawing */
76 void draw_sprite(sprite* spr){
77 int x = spr->x - camera.x;
78 int y = spr->y - camera.y;
79 int W = spr->w;
80 int H = spr->h;
81 int X = spr->frame.x;
82 int Y = spr->frame.y;
83 int g = spr->gfxid;
84 draw_gfx(g, x, y, X, Y, W, H);
88 void draw_screen(zone* z, int si, int sj){
89 struct screen* scr = z->screens+si+z->w*sj;
90 int G = z->tileset;
91 int x = si*20*16 - camera.x;
92 int y = sj*15*16 - camera.y;
94 for(int j=0; j < 15; j++){
95 for(int i=0; i < 20; i++){
96 if(x > 320 || y > 240 || x < -16 || y < -16) continue;
97 int id = scr->tiles[i][j].id;
98 if(id != 0){
99 int X = id&7;
100 int Y = id>>3;
101 draw_gfx(G, x, y, X, Y, 16, 16);
103 else{
104 //draw background
106 x += 16;
108 x -= 320;
109 y += 16;
121 void draw_small_text(char* str, int x, int y){
122 char* c;
123 for(c=str; *c; c++){
124 int X = *c & 0x0f;
125 int Y = *c >> 4;
126 draw_gfx_raw(minifont_gfx, x, y, X*4, Y*9, 3, 8);
127 x+=4;
133 void printf_small(int x, int y, char* format, ...){
134 char str[128];
135 va_list ap;
136 va_start(ap, format);
137 vsnprintf(str, 128, format, ap);
138 va_end(ap);
139 str[127]='\0';
140 draw_small_text(str, x, y);
146 void draw_sprites(){
147 int i;
148 for(i=0; i<sprite_count; i++){
149 draw_sprite(sprites[i]);
153 void draw_final(){
154 fps_draw();
155 console_draw();
156 update_video();
157 clear_video();
163 void point_camera(int x, int y){
164 camera.x = x;
165 camera.y = y;
170 void animate_sprite(int i){
171 sprite* spr = sprites[i];
173 // spr->frame_counter += dt;
174 animation* ani = animations[spr->anim];
177 while(spr->frame_counter > ani->frame_lens[spr->current_frame]){
178 spr->frame_counter -= ani->frame_lens[spr->current_frame];
179 spr->current_frame++;
180 if(spr->current_frame == ani->frame_count){
181 spr->current_frame = 0;
183 spr->frame = ani->frames[spr->current_frame];
186 //if(spr->update) spr->update(spr, spr->userdata);
189 void animate_sprites(){
190 int i;
191 for(i=0; i<sprite_count; i++){
192 animate_sprite(i);
199 int load_sprite(char* filename, int id){
200 int i;
202 printf("loading %s\n",filename);
204 char path[1024] = "sprites/";
205 strncat(path, filename, 1023 - strlen(filename));
207 reader* rd = loader_open(path);
208 if(!rd){
209 return -1;
212 animation* ani = xmalloc(sizeof(animation));
214 char str[256];
215 int w, h;
216 int frame_count;
217 int loop_mode;
219 loader_scanline(rd,"%256s",str);
220 loader_scanline(rd,"%d %d %d %d",&w,&h,&loop_mode,&frame_count);
222 ani->frame_lens = xmalloc(frame_count*sizeof(short));
223 ani->frames = xmalloc(frame_count*sizeof(struct frame));
224 ani->frame_count = frame_count;
226 int g = load_gfx(str);
227 if(g < 0)
228 return -1;
230 ani->gfxid = g;
232 //int W = gfx[g].w;
233 //int H = gfx[g].h;
234 int W = gfx_width(g);
235 int H = gfx_height(g);
236 ani->w = w;
237 ani->h = h;
239 for(i=0; i < frame_count; i++){
240 int l, x, y;
241 loader_scanline(rd, "%d %d %d", &l, &x, &y);
242 ani->frame_lens[i] = l;
243 ani->frames[i].x = x;
244 ani->frames[i].y = y;
245 ani->frames[i].x0 = ((double)x)/W;
246 ani->frames[i].y0 = ((double)y)/H;
247 ani->frames[i].x1 = ((double)(x+w))/W;
248 ani->frames[i].y1 = ((double)(y+h))/W;
251 loader_close(rd);
252 animations[id] = ani;
253 return 0;
259 /********************/
260 /* graphics control */
261 /********************/
263 sprite* enable_sprite(int sprnum){
264 if(!animations[sprnum]){
265 fatal_error("enable_sprite: you just tried to enable sprite with type %d, which does not exist\n",sprnum);
267 if(sprite_count == MAX_SPRITES){
268 /* need a priority based way to create important sprites if full */
269 return NULL;
271 sprite* spr = xmalloc(sizeof(sprite));
272 animation* ani = animations[sprnum];
274 spr->number = sprite_count;
275 spr->frame_counter = 0;
276 spr->current_frame = 0;
277 spr->frame = ani->frames[0];
278 spr->gfxid = ani->gfxid;
279 spr->anim = sprnum;
280 spr->x = 0;
281 spr->y = 0;
282 spr->w = ani->w;
283 spr->h = ani->h;
284 //spr->vx = 0;
285 //spr->vy = 0;
286 //spr->update = NULL;
287 //spr->userdata = NULL;
289 sprites[sprite_count++] = spr;
290 return spr;
293 void disable_sprite(sprite* spr){
294 sprite* tmp = sprites[spr->number];
295 sprites[spr->number] = sprites[sprite_count--];
296 free(tmp);
299 sprite* copy_sprite(sprite* spr){
300 if(sprite_count == MAX_SPRITES){
301 /* need way to make important sprites when full */
302 return NULL;
304 sprite* copy = xmalloc(sizeof(sprite));
305 *copy = *spr;
306 sprites[sprite_count++] = copy;
307 return copy;
312 void enable_stage(int yn){
313 stage_enabled = yn;
318 int load_bitmap(char* filename){
319 int g = load_gfx(filename);
320 return g;
323 void draw_bitmap(int id, int x, int y){
324 int W = gfx_width(id);
325 int H = gfx_height(id);
326 draw_gfx(id, x, y, 0, 0, W, H);