Added music.c module.
[cantaveria.git] / graphics.c
blob3c0c6cd0faddc57e626f49fa5e75bf4eab0584ed
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 <util.h>
35 #include <input.h>
36 #include <kernel.h>
37 #include <video.h>
38 #include <graphics.h>
39 #include <loader.h>
40 #include <console.h>
44 /* graphics data */
45 sprite* sprites[MAX_SPRITES];
46 int sprite_count = 0;
48 animation* animations[MAX_ANIMATIONS];
49 int anim_count = 0;
51 int minifont_gfx = 0;
55 int stage_enabled = 0;
59 struct {
60 int x, y;
61 } camera;
64 void graphics_init(){
65 int i;
66 minifont_gfx = load_gfx("smallfont.tga");
67 for(i=0; i<MAX_ANIMATIONS; i++){
68 animations[i] = NULL;
73 /* drawing */
75 void draw_sprite(sprite* spr){
76 int x = spr->x - camera.x;
77 int y = spr->y - camera.y;
78 int W = spr->w;
79 int H = spr->h;
80 int X = spr->frame.x;
81 int Y = spr->frame.y;
82 int g = spr->gfxid;
83 draw_gfx(g, x, y, X, Y, W, H);
87 void draw_screen(zone* z, int si, int sj){
88 struct screen* scr = z->screens+si+z->w*sj;
89 int G = z->tileset;
90 int x = si*20*16 - camera.x;
91 int y = sj*15*16 - camera.y;
93 for(int j=0; j < 15; j++){
94 for(int i=0; i < 20; i++){
95 if(x > 320 || y > 240 || x < -16 || y < -16) continue;
96 int id = scr->tiles[i][j].id;
97 if(id != 0){
98 int X = id&7;
99 int Y = id>>3;
100 draw_gfx(G, x, y, X, Y, 16, 16);
102 else{
103 //draw background
105 x += 16;
107 x -= 320;
108 y += 16;
120 void draw_small_text(char* str, int x, int y){
121 char* c;
122 for(c=str; *c; c++){
123 int X = *c & 0x0f;
124 int Y = *c >> 4;
125 draw_gfx_raw(minifont_gfx, x, y, X*4, Y*9, 3, 8);
126 x+=4;
132 void printf_small(int x, int y, char* format, ...){
133 char str[128];
134 va_list ap;
135 va_start(ap, format);
136 vsnprintf(str, 128, format, ap);
137 va_end(ap);
138 str[127]='\0';
139 draw_small_text(str, x, y);
145 void draw_sprites(){
146 int i;
147 for(i=0; i<sprite_count; i++){
148 draw_sprite(sprites[i]);
152 void draw_final(){
153 fps_draw();
154 console_draw();
155 update_video();
156 clear_video();
162 void point_camera(int x, int y){
163 camera.x = x;
164 camera.y = y;
169 void animate_sprite(int i){
170 sprite* spr = sprites[i];
172 // spr->frame_counter += dt;
173 animation* ani = animations[spr->anim];
176 while(spr->frame_counter > ani->frame_lens[spr->current_frame]){
177 spr->frame_counter -= ani->frame_lens[spr->current_frame];
178 spr->current_frame++;
179 if(spr->current_frame == ani->frame_count){
180 spr->current_frame = 0;
182 spr->frame = ani->frames[spr->current_frame];
185 //if(spr->update) spr->update(spr, spr->userdata);
188 void animate_sprites(){
189 int i;
190 for(i=0; i<sprite_count; i++){
191 animate_sprite(i);
198 int load_sprite(char* filename, int id){
199 int i;
201 printf("loading %s\n",filename);
203 char path[1024] = "sprites/";
204 strncat(path, filename, 1023 - strlen(filename));
206 reader* rd = loader_open(path);
207 if(!rd){
208 return -1;
211 animation* ani = xmalloc(sizeof(animation));
213 char str[256];
214 int w, h;
215 int frame_count;
216 int loop_mode;
218 loader_scanline(rd,"%256s",str);
219 loader_scanline(rd,"%d %d %d %d",&w,&h,&loop_mode,&frame_count);
221 ani->frame_lens = xmalloc(frame_count*sizeof(short));
222 ani->frames = xmalloc(frame_count*sizeof(struct frame));
223 ani->frame_count = frame_count;
225 int g = load_gfx(str);
226 if(g < 0)
227 return -1;
229 ani->gfxid = g;
231 //int W = gfx[g].w;
232 //int H = gfx[g].h;
233 int W = gfx_width(g);
234 int H = gfx_height(g);
235 ani->w = w;
236 ani->h = h;
238 for(i=0; i < frame_count; i++){
239 int l, x, y;
240 loader_scanline(rd, "%d %d %d", &l, &x, &y);
241 ani->frame_lens[i] = l;
242 ani->frames[i].x = x;
243 ani->frames[i].y = y;
244 ani->frames[i].x0 = ((double)x)/W;
245 ani->frames[i].y0 = ((double)y)/H;
246 ani->frames[i].x1 = ((double)(x+w))/W;
247 ani->frames[i].y1 = ((double)(y+h))/W;
250 loader_close(rd);
251 animations[id] = ani;
252 return 0;
258 /********************/
259 /* graphics control */
260 /********************/
262 sprite* enable_sprite(int sprnum){
263 if(!animations[sprnum]){
264 fatal_error("enable_sprite: you just tried to enable sprite with type %d, which does not exist\n",sprnum);
266 if(sprite_count == MAX_SPRITES){
267 /* need a priority based way to create important sprites if full */
268 return NULL;
270 sprite* spr = xmalloc(sizeof(sprite));
271 animation* ani = animations[sprnum];
273 spr->number = sprite_count;
274 spr->frame_counter = 0;
275 spr->current_frame = 0;
276 spr->frame = ani->frames[0];
277 spr->gfxid = ani->gfxid;
278 spr->anim = sprnum;
279 spr->x = 0;
280 spr->y = 0;
281 spr->w = ani->w;
282 spr->h = ani->h;
283 //spr->vx = 0;
284 //spr->vy = 0;
285 //spr->update = NULL;
286 //spr->userdata = NULL;
288 sprites[sprite_count++] = spr;
289 return spr;
292 void disable_sprite(sprite* spr){
293 sprite* tmp = sprites[spr->number];
294 sprites[spr->number] = sprites[sprite_count--];
295 free(tmp);
298 sprite* copy_sprite(sprite* spr){
299 if(sprite_count == MAX_SPRITES){
300 /* need way to make important sprites when full */
301 return NULL;
303 sprite* copy = xmalloc(sizeof(sprite));
304 *copy = *spr;
305 sprites[sprite_count++] = copy;
306 return copy;
311 void enable_stage(int yn){
312 stage_enabled = yn;
317 int load_bitmap(char* filename){
318 int g = load_gfx(filename);
319 return g;
322 void draw_bitmap(int id, int x, int y){
323 int W = gfx_width(id);
324 int H = gfx_height(id);
325 draw_gfx(id, x, y, 0, 0, W, H);