list.c merge sort.
[cantaveria.git] / graphics.c
blobd42a4650634e5bebf863f4e98048a0d76d4e25f7
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>
41 #include <game.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_screen(zone* z, int si, int sj){
147 struct screen* scr = ZONE_LOOKUP(z,si,sj);
148 if(!scr) return;
149 int G = z->tileset_gfx;
150 int x = si*20*16 - camera.x;
151 int y = sj*15*16 - camera.y;
152 int i,j;
154 for(j=0; j < 15; j++){
155 for(i=0; i < 20; i++){
156 int id = scr->tiles[i][j];
157 if(id != 0){
158 int X = (id&0xf)<<4;
159 int Y = (id>>4)<<4;
160 draw_gfx(G, x, y, X, Y, 16, 16);
162 else{
163 int X = x+camera.x/2;
164 const int WW = 512;
165 if((X%WW)+16 >= WW){
166 int W = WW - (X%WW);
168 draw_gfx(
169 z->bg_gfx,
170 x, y,
171 X, y,
172 W, 16
175 X %= WW;
176 draw_gfx(
177 z->bg_gfx,
178 x+W, y,
179 0, y,
180 16-W, 16
183 else {
184 X %= WW;
185 draw_gfx(
186 z->bg_gfx,
187 x, y,
188 X, y,
189 16, 16
195 x += 16;
197 x -= 320;
198 y += 16;
203 void draw_stage(){
204 int i;
205 zone* z = game.current_zone;
206 int si = game.si;
207 int sj = game.sj;
209 int table[8][2] = {
210 { 1,0},{ 1, 1},{0, 1},{-1, 1},
211 {-1,0},{-1,-1},{0,-1},{ 1,-1}
214 draw_screen(z, si, sj);
215 for(i=0; i<8; i++){
216 draw_screen(z, si+table[i][0], sj+table[i][1]);
220 void draw_sprites(){
221 int i;
222 for(i=0; i<sprite_count; i++){
223 draw_sprite(sprites[i]);
227 void draw_final(){
228 fps_draw();
229 console_draw();
230 update_video();
231 clear_video();
237 void point_camera(int x, int y){
238 camera.x = x;
239 camera.y = y;
244 void animate_sprite(int i){
245 sprite* spr = sprites[i];
247 // spr->frame_counter += dt;
248 animation* ani = animations[spr->anim];
251 while(spr->frame_counter > ani->frame_lens[spr->current_frame]){
252 spr->frame_counter -= ani->frame_lens[spr->current_frame];
253 spr->current_frame++;
254 if(spr->current_frame == ani->frame_count){
255 spr->current_frame = 0;
257 spr->frame = ani->frames[spr->current_frame];
260 //if(spr->update) spr->update(spr, spr->userdata);
263 void animate_sprites(){
264 int i;
265 for(i=0; i<sprite_count; i++){
266 animate_sprite(i);
273 int load_sprite(char* filename, int id){
274 int i;
276 printf("loading %s\n",filename);
278 char path[1024] = "sprites/";
279 strncat(path, filename, 1023 - strlen(filename));
281 reader* rd = loader_open(path);
282 if(!rd){
283 return -1;
286 animation* ani = xmalloc(sizeof(animation));
288 char str[256];
289 int w, h;
290 int frame_count;
291 int loop_mode;
293 loader_scanline(rd,"%256s",str);
294 loader_scanline(rd,"%d %d %d %d",&w,&h,&loop_mode,&frame_count);
296 ani->frame_lens = xmalloc(frame_count*sizeof(short));
297 ani->frames = xmalloc(frame_count*sizeof(struct frame));
298 ani->frame_count = frame_count;
300 int g = load_gfx(str);
301 if(g < 0)
302 return -1;
304 ani->gfxid = g;
306 //int W = gfx[g].w;
307 //int H = gfx[g].h;
308 int W = gfx_width(g);
309 int H = gfx_height(g);
310 ani->w = w;
311 ani->h = h;
313 for(i=0; i < frame_count; i++){
314 int l, x, y;
315 loader_scanline(rd, "%d %d %d", &l, &x, &y);
316 ani->frame_lens[i] = l;
317 ani->frames[i].x = x;
318 ani->frames[i].y = y;
319 ani->frames[i].x0 = ((double)x)/W;
320 ani->frames[i].y0 = ((double)y)/H;
321 ani->frames[i].x1 = ((double)(x+w))/W;
322 ani->frames[i].y1 = ((double)(y+h))/W;
325 loader_close(rd);
326 animations[id] = ani;
327 return 0;
333 /********************/
334 /* graphics control */
335 /********************/
337 sprite* enable_sprite(int sprnum){
338 if(!animations[sprnum]){
339 fatal_error("enable_sprite: you just tried to enable sprite with type %d, which does not exist\n",sprnum);
341 if(sprite_count == MAX_SPRITES){
342 /* need a priority based way to create important sprites if full */
343 return NULL;
345 sprite* spr = xmalloc(sizeof(sprite));
346 animation* ani = animations[sprnum];
348 spr->number = sprite_count;
349 spr->frame_counter = 0;
350 spr->current_frame = 0;
351 spr->frame = ani->frames[0];
352 spr->gfxid = ani->gfxid;
353 spr->anim = sprnum;
354 spr->x = 0;
355 spr->y = 0;
356 spr->w = ani->w;
357 spr->h = ani->h;
358 //spr->vx = 0;
359 //spr->vy = 0;
360 //spr->update = NULL;
361 //spr->userdata = NULL;
363 sprites[sprite_count++] = spr;
364 return spr;
367 void disable_sprite(sprite* spr){
368 sprite* tmp = sprites[spr->number];
369 sprites[spr->number] = sprites[sprite_count--];
370 free(tmp);
373 sprite* copy_sprite(sprite* spr){
374 if(sprite_count == MAX_SPRITES){
375 /* need way to make important sprites when full */
376 return NULL;
378 sprite* copy = xmalloc(sizeof(sprite));
379 *copy = *spr;
380 sprites[sprite_count++] = copy;
381 return copy;
386 void enable_stage(int yn){
387 stage_enabled = yn;
392 int load_bitmap(char* filename){
393 int g = load_gfx(filename);
394 return g;
397 void draw_bitmap(int id, int x, int y){
398 int W = gfx_width(id);
399 int H = gfx_height(id);
400 draw_gfx(id, x, y, 0, 0, W, H);