Added entities. Rewrote stage, half 'working'.
[cantaveria.git] / graphics.c
blob09719a6f8492063789759960cf3474c4ed0d65cd
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 <kernel.h>
37 #include <video.h>
38 #include <graphics.h>
39 #include <loader.h>
40 #include <camera.h>
43 /* graphics data */
44 sprite* sprites[MAX_SPRITES];
45 int sprite_count = 0;
47 animation* animations[MAX_ANIMATIONS];
48 int anim_count = 0;
50 int minifont_gfx = 1;
51 int panic_gfx = 0;
54 int stage_enabled = 0;
58 void graphics_init(){
59 int i;
60 load_panic_gfx();
61 for(i=0; i<MAX_ANIMATIONS; i++){
62 animations[i] = NULL;
67 /* drawing */
69 void draw_sprite(sprite* spr){
70 int x = spr->x - camera_x();
71 int y = spr->y - camera_y();
72 int W = spr->w;
73 int H = spr->h;
74 int X = spr->frame.x;
75 int Y = spr->frame.y;
76 int g = spr->gfxid;
77 draw_gfx(g, x, y, X, Y, W, H);
81 void draw_screen(zone* z, int si, int sj){
82 struct screen* scr = z->screens+si+z->w*sj;
83 int G = z->tileset;
84 int x = si*20*16 - camera.x;
85 int y = sj*15*16 - camera.y;
87 for(int j=0; j < 15; j++){
88 for(int i=0; i < 20; i++){
89 if(x > 320 || y > 240 || x < -16 || y < -16) continue;
90 int id = scr->tiles[i][j].id;
91 if(id != 0){
92 int X = id&7;
93 int Y = id>>3;
94 draw_gfx(G, x, y, X, Y, 16, 16);
96 else{
97 //draw background
99 x += 16;
101 x -= 320;
102 y += 16;
114 void draw_small_text(string str, int x, int y){
115 const char* c;
116 for(c=str; *c; c++){
117 int X = *c & 0x0f;
118 int Y = *c >> 4;
119 draw_gfx_raw(minifont_gfx, x, y, X*4, Y*9, 3, 8);
120 x+=4;
126 void printf_small(int x, int y, string format, ...){
127 char str[128];
128 va_list ap;
129 va_start(ap, format);
130 vsnprintf(str, 128, format, ap);
131 va_end(ap);
132 str[127]='\0';
133 draw_small_text(str, x, y);
139 void draw_sprites(){
140 int i;
141 for(i=0; i<sprite_count; i++){
142 draw_sprite(sprites[i]);
146 void draw_final(){
147 //fps_draw();
148 update_video();
149 clear_video();
157 void animate_sprite(int i){
158 sprite* spr = sprites[i];
160 // spr->frame_counter += dt;
161 animation* ani = animations[spr->anim];
164 while(spr->frame_counter > ani->frame_lens[spr->current_frame]){
165 spr->frame_counter -= ani->frame_lens[spr->current_frame];
166 spr->current_frame++;
167 if(spr->current_frame == ani->frame_count){
168 spr->current_frame = 0;
170 spr->frame = ani->frames[spr->current_frame];
173 //if(spr->update) spr->update(spr, spr->userdata);
176 void animate_sprites(){
177 int i;
178 for(i=0; i<sprite_count; i++){
179 animate_sprite(i);
186 int load_sprite(string path, int id){
187 int i;
188 int W, H;
190 reader* rd = loader_open(path);
191 if(!rd){
192 return -1;
195 animation* ani = xmalloc(sizeof(animation));
197 char str[256];
198 int w, h;
199 int frame_count;
200 int loop_mode;
202 loader_scanline(rd,"%256s",str);
203 loader_scanline(rd,"%d %d %d %d",&w,&h,&loop_mode,&frame_count);
205 ani->frame_lens = xmalloc(frame_count*sizeof(short));
206 ani->frames = xmalloc(frame_count*sizeof(struct frame));
207 ani->frame_count = frame_count;
209 int g = load_gfx(str);
210 if(g < 0)
211 return -1;
213 ani->gfxid = g;
215 //int W = gfx[g].w;
216 //int H = gfx[g].h;
217 gfx_dimensions(g, &W, &H);
218 ani->w = w;
219 ani->h = h;
221 for(i=0; i < frame_count; i++){
222 int l, x, y;
223 loader_scanline(rd, "%d %d %d", &l, &x, &y);
224 ani->frame_lens[i] = l;
225 ani->frames[i].x = x;
226 ani->frames[i].y = y;
227 ani->frames[i].x0 = ((double)x)/W;
228 ani->frames[i].y0 = ((double)y)/H;
229 ani->frames[i].x1 = ((double)(x+w))/W;
230 ani->frames[i].y1 = ((double)(y+h))/W;
233 loader_close(rd);
234 animations[id] = ani;
235 return 0;
241 /********************/
242 /* graphics control */
243 /********************/
245 sprite* enable_sprite(int sprnum){
246 if(!animations[sprnum]){
247 fatal_error("enable_sprite: you just tried to enable sprite with type %d, which does not exist\n",sprnum);
249 if(sprite_count == MAX_SPRITES){
250 /* need a priority based way to create important sprites if full */
251 return NULL;
253 sprite* spr = xmalloc(sizeof(sprite));
254 animation* ani = animations[sprnum];
256 spr->number = sprite_count;
257 spr->frame_counter = 0;
258 spr->current_frame = 0;
259 spr->frame = ani->frames[0];
260 spr->gfxid = ani->gfxid;
261 spr->anim = sprnum;
262 spr->x = 0;
263 spr->y = 0;
264 spr->w = ani->w;
265 spr->h = ani->h;
266 //spr->vx = 0;
267 //spr->vy = 0;
268 //spr->update = NULL;
269 //spr->userdata = NULL;
271 sprites[sprite_count++] = spr;
272 return spr;
275 void disable_sprite(sprite* spr){
276 sprite* tmp = sprites[spr->number];
277 sprites[spr->number] = sprites[sprite_count--];
278 free(tmp);
281 sprite* copy_sprite(sprite* spr){
282 if(sprite_count == MAX_SPRITES){
283 /* need way to make important sprites when full */
284 return NULL;
286 sprite* copy = xmalloc(sizeof(sprite));
287 *copy = *spr;
288 sprites[sprite_count++] = copy;
289 return copy;
294 void enable_stage(int _yn){
295 stage_enabled = _yn;
300 int load_bitmap(string filename){
301 int g = load_gfx(filename);
302 return g;
305 void draw_bitmap(int id, int x, int y){
306 int W, H;
307 gfx_dimensions(id, &W, &H);
308 draw_gfx(id, x, y, 0, 0, W, H);