2 Cantaveria - action adventure platform game
3 Copyright (C) 2009 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
26 #include <SDL/SDL_opengl.h>
40 struct handler handler
;
43 void set_handler(struct handler h
){
56 int now
= SDL_GetTicks();
57 int diff
= now
- last
;
68 int butmap
[MAX_PLAYERS
][8];
69 int joymap
[MAX_PLAYERS
];
70 int alphanum_enable
= 0;
76 int butnum(int joy
, int name
){
77 return butmap
[joy
][name
];
82 int joy2player(int joy
){
83 for(int i
=0; i
<MAX_PLAYERS
; i
++){
84 if(joymap
[i
] == joy
) return i
;
89 int key2name(int sym
){
90 for(int i
=0; i
<14; i
++){
91 if(keymap
[i
] == sym
) return i
;
96 int button2name(int player
, int but
){
97 if(player
< 0) return -1;
98 for(int i
=0; i
<8; i
++){
99 if(butmap
[i
][player
] == but
) return i
;
108 printf("sdl: quit\n");
118 void enable_alphanum(int yn
){
119 SDL_EnableUNICODE(yn
);
120 alphanum_enable
= yn
;
130 while(SDL_PollEvent(&e
) != 0){
133 uni16
= e
.key
.keysym
.unicode
;
134 if(uni16
!= 0 && alphanum_enable
){
138 name
= key2name(e
.key
.keysym
.sym
);
139 if(name
> -1) handler
.keydown(name
);
143 name
= key2name(e
.key
.keysym
.sym
);
144 if(name
> -1) handler
.keyup(name
);
146 case SDL_JOYBUTTONDOWN
:
147 player
= joy2player(e
.jbutton
.which
);
148 name
= button2name(player
, e
.jbutton
.button
);
149 if(name
> -1) handler
.joypress(player
, name
);
151 case SDL_JOYBUTTONUP
:
152 player
= joy2player(e
.jbutton
.which
);
153 name
= button2name(player
, e
.jbutton
.button
);
154 if(name
> -1) handler
.joyrelease(e
.jbutton
.which
, name
);
156 case SDL_JOYAXISMOTION
:
157 player
= joy2player(e
.jaxis
.which
);
158 if(player
< 0) break;
159 if(e
.jaxis
.axis
== 0){
160 handler
.joymovex(player
, e
.jaxis
.value
);
162 else if(e
.jaxis
.axis
== 1){
163 handler
.joymovey(player
, e
.jaxis
.value
);
173 void control(int type
, int par1
, int par2
){
177 handler
.keydown(par1
);
183 handler
.joymovex(par1
, par2
);
186 handler
.joymovey(par1
, par2
);
189 handler
.joypress(par1
, par2
);
192 handler
.joyrelease(par1
, par2
);
209 int screen_offset_x
= 0;
210 int screen_offset_y
= 0;
215 /********************/
216 /* drawing routines */
217 /********************/
219 void draw_gfx_raw(int gfxid
, int x
, int y
, int X
, int Y
, int W
, int H
){
220 if(x
> screen_w
|| y
> screen_h
|| x
+W
< 0 || y
+H
< 0) return;
222 SDL_Surface
* surf
= gfx
[gfxid
].surf
;
223 SDL_Rect r1
= {X
,Y
,W
,H
};
224 SDL_Rect r2
= {x
,y
,W
,H
};
225 SDL_BlitSurface(surf
,&r1
,video
,&r2
);
228 double w
= gfx
[gfxid
].w
;
229 double h
= gfx
[gfxid
].h
;
230 double X0
= ((double)X
)/w
;
231 double X1
= X0
+ ((double)W
)/w
;
232 double Y0
= ((double)Y
)/h
;
233 double Y1
= Y0
+ ((double)H
)/h
;
235 glBindTexture( GL_TEXTURE_2D
, gfx
[gfxid
].texture
);
244 glVertex3f(x
+W
,y
+H
,0);
252 void draw_gfx(int gfxid
, int x
, int y
, int X
, int Y
, int W
, int H
){
253 draw_gfx_raw(gfxid
, x
+screen_offset_x
, y
+screen_offset_y
, X
, Y
, W
, H
);
258 SDL_FillRect(video
, 0, 0);
261 glClearColor(0.0,0.0,0.0,0.0);
262 glClear( GL_COLOR_BUFFER_BIT
);
268 SDL_UpdateRect(video
,0,0,0,0);
271 SDL_GL_SwapBuffers();
278 /********************/
279 /* graphics loading */
280 /********************/
282 SDL_Surface
* SDL_NewSurface(int w
, int h
){
283 char prefix
[32] = "SDL_NewSurface";
284 SDL_Surface
* tmp
= SDL_CreateRGBSurface(SDL_SRCCOLORKEY
,w
,h
,32,0,0,0,0);
286 out_of_memory(prefix
);
289 SDL_Surface
* surf
= SDL_DisplayFormat(tmp
);
291 out_of_memory(prefix
);
294 SDL_FreeSurface(tmp
);
296 SDL_FillRect(surf
,0,0x00ffffff);
301 SDL_Surface
* load_pixmap(char* filename
){
302 char path
[256] = "gfx/";
303 strmcat(path
, filename
, 256);
305 reader
* rd
= loader_open(path
);
310 unsigned char header
[18];
311 loader_read(rd
, header
, 18);
313 int w
= header
[12] + (header
[13]<<8);
314 int h
= header
[14] + (header
[15]<<8);
315 int bpp
= header
[16];
316 printf("load_pixmap: %s has bpp=%d\n",filename
, bpp
);
317 SDL_Surface
* surf
= SDL_CreateRGBSurface(0,w
,h
,bpp
,
318 0x00ff0000,0x0000ff00,0x000000ff,0xff000000);
320 out_of_memory("load_pixmap");
322 loader_read(rd
, surf
->pixels
, w
*(bpp
/8)*h
);
328 int load_gfx(char* filename
){
329 if(gfx_count
== MAX_GFX
){
330 fatal_error("load_gfx: cannot load any more than %d graphics\n",MAX_GFX
);
333 printf("loading %s\n",filename
);
336 for(int i
=0; i
<gfx_count
; i
++){/*check for already loaded gfx*/
337 if(strcmp(gfx
[i
].filename
, filename
)==0){
342 SDL_Surface
* src
= load_pixmap(filename
);
344 fatal_error("load_gfx: failed to load %s\n",filename
);
348 SDL_Surface
* surf
= SDL_DisplayFormatAlpha(src
);
349 SDL_SetAlpha(surf
, 0, 0);
351 Uint32 key
= SDL_MapRGB(surf
->format
, (COLOR_KEY
&0xff0000)>>16,
352 (COLOR_KEY
&0x00ff00)>>8,
353 (COLOR_KEY
&0x0000ff)>>0);
354 SDL_SetColorKey(surf
, SDL_SRCCOLORKEY
, key
);
356 SDL_FreeSurface(src
);
359 gfx
[gfx_count
].filename
= strxcpy(filename
);
360 gfx
[gfx_count
].surf
= surf
;
361 gfx
[gfx_count
].w
= surf
->w
;
362 gfx
[gfx_count
].h
= surf
->h
;
367 //SDL_Surface* conv = SDL_CreateRGBSurface(0, src->w, src->h, 32,
368 // 0xff<<16,0xff<<8,0xff<<0,0);
370 SDL_Surface
* conv
= SDL_DisplayFormatAlpha(src
);
371 //SDL_SetAlpha(conv, 0, 0);
372 //SDL_BlitSurface(src, NULL, conv, NULL);
373 //printf("bpp = %d\n",conv->format->BitsPerPixel);
376 Uint8
* conv_bytes
= conv
->pixels
;
377 Uint32 key
= SDL_MapRGB(src
->format
,(COLOR_KEY
&0xff0000)>>16,
378 (COLOR_KEY
&0x00ff00)>>8,
379 (COLOR_KEY
&0x0000ff)>>0);
380 for(int i
=0; i
<src
->w
; i
++){
381 for(int j
=0; j
<src
->h
; j
++){
383 //if(1){printf("M==%d totalbytes=%d\n",M,src->w*src->h*4);}
385 Uint32 pixel
= *((Uint32
*)(src
->pixels
+N
));
386 conv_bytes
[M
] = pixel
==key
? SDL_ALPHA_TRANSPARENT
: SDL_ALPHA_OPAQUE
;
387 N
+= src
->format
->BytesPerPixel
;
392 glGenTextures( 1, &texture
);
393 glBindTexture( GL_TEXTURE_2D
, texture
);
395 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
396 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
397 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
398 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
400 glTexImage2D( GL_TEXTURE_2D
, 0, 4, conv
->w
, conv
->h
, 0,
401 GL_BGRA
, GL_UNSIGNED_BYTE
, conv
->pixels
);
403 gfx
[gfx_count
].filename
= strxcpy(filename
);
404 gfx
[gfx_count
].texture
= texture
;
405 gfx
[gfx_count
].w
= src
->w
;
406 gfx
[gfx_count
].h
= src
->h
;
408 SDL_FreeSurface(conv
);
409 SDL_FreeSurface(src
);
415 int gfx_width(int gfxid
){
419 int gfx_height(int gfxid
){
429 extern void process_audio(float lout
[], float rout
[], int len
);
431 void audio_callback(void *userdata
, Uint8
*stream
, int len
){
432 Sint16
* out
= (Sint16
*)stream
;
434 process_audio(lout
, rout
, buffer_size
);
436 for(int i
=0; i
<buffer_size
; i
++){
437 out
[i
*2 ] = (Sint16
)(lout
[i
]*32767);
438 out
[i
*2 + 1] = (Sint16
)(rout
[i
]*32767);
450 if(SDL_Init(SDL_INIT_VIDEO
| SDL_INIT_AUDIO
| SDL_INIT_JOYSTICK
)==-1){
451 report_error("sdl: %s\n",SDL_GetError());
456 void parse_options(int argc
, char* argv
[], int* fullscreen
, int* gl_flag
){
458 for(int i
=0; i
<argc
; i
++){
459 if(!strcmp(argv
[i
], "-gl")){
463 if(!strcmp(argv
[i
], "-f")){
466 if(!strcmp(argv
[i
], "-h") || !strcmp(argv
[i
], "--help")){
467 printf("options:\n");
468 printf(" -gl use opengl video mode\n");
469 printf(" -f use fullscreen video mode\n");
470 printf(" -h print this help\n");
471 printf(" -v print version info\n");
474 if(!strcmp(argv
[i
], "-v")){
475 printf("cantaveria (v%d.%d)\n",VERSION_MAJOR
,VERSION_MINOR
);
476 printf("Copyright 2009 Evan Rinehart\n\n");
478 printf("This program is distributed under the terms of the GNU General\n"
479 "Public License (v2) and comes with ABSOLUTELY NO WARRANTY.\n\n");
481 printf("Send questions, comments, and bugs to evanrinehart@gmail.com\n\n");
483 printf("Send money to:\n");
484 printf("1850 Claiborne St\n");
485 printf("Mandeville, LA 70448\n");
486 printf("United States of America\n\n");
488 printf("Thanks! :)\n");
496 keymap[ESCAPE_KEY] = SDLK_ESCAPE;
497 keymap[PAUSE_KEY] = SDLK_PAUSE;
499 keymap[LEFT_KEY] = SDLK_LEFT;
500 keymap[RIGHT_KEY] = SDLK_RIGHT;
501 keymap[UP_KEY] = SDLK_UP;
502 keymap[DOWN_KEY] = SDLK_DOWN;
504 keymap[FIRE_KEY] = SDLK_z;
505 keymap[JUMP_KEY] = SDLK_x;
506 keymap[INVENTORY_KEY] = SDLK_a;
507 keymap[SPECIAL_KEY] = SDLK_s;
509 keymap[L_KEY] = SDLK_q;
510 keymap[R_KEY] = SDLK_w;
511 keymap[START_KEY] = SDLK_RETURN;
512 keymap[SELECT_KEY] = SDLK_TAB;
515 keymap
[ESCAPE_KEY
] = SDLK_ESCAPE
;
516 keymap
[PAUSE_KEY
] = SDLK_PAUSE
;
518 keymap
[LEFT_KEY
] = SDLK_a
;
519 keymap
[RIGHT_KEY
] = SDLK_d
;
520 keymap
[UP_KEY
] = SDLK_w
;
521 keymap
[DOWN_KEY
] = SDLK_s
;
523 keymap
[FIRE_KEY
] = SDLK_j
;
524 keymap
[JUMP_KEY
] = SDLK_k
;
525 keymap
[INVENTORY_KEY
] = SDLK_i
;
526 keymap
[SPECIAL_KEY
] = SDLK_l
;
528 keymap
[L_KEY
] = SDLK_q
;
529 keymap
[R_KEY
] = SDLK_e
;
530 keymap
[START_KEY
] = SDLK_u
;
531 keymap
[SELECT_KEY
] = SDLK_o
;
534 void setup_joysticks(){
535 int N
= SDL_NumJoysticks();
536 printf("sdl: detected %d joysticks\n",N
);
537 for(int i
=0; i
<N
; i
++){
538 if(SDL_JoystickOpen(i
)){
539 printf(" joy%d: %s\n",i
,SDL_JoystickName(i
));
542 printf(" joy%d: %s (failed to open)\n",i
,SDL_JoystickName(i
));
551 SDL_WM_SetCaption("cantaveria","cantaveria");
552 SDL_ShowCursor(SDL_DISABLE
);
553 const SDL_VideoInfo
* vinfo
= SDL_GetVideoInfo();
556 if(fullscreen
&& gl_flag
){
557 W
= vinfo
->current_w
;
558 H
= vinfo
->current_h
;
578 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER
, 1);
579 //SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
580 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL
, 1);
585 flags
|= SDL_FULLSCREEN
;
590 video
= SDL_SetVideoMode(W
,H
,32,flags
);
592 report_error("sdl: %s\n",SDL_GetError());
599 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
601 glEnable( GL_TEXTURE_2D
);
602 glClearColor( 0.0f
, 0.0f
, 0.0f
, 0.0f
);
604 glViewport( 0, 0, W
, H
);
606 glClear( GL_COLOR_BUFFER_BIT
);
608 glMatrixMode( GL_PROJECTION
);
611 //glOrtho(0.0f, 240*aspect, 240, 0.0f, -1.0f, 1.0f);
612 //glOrtho(0.0f, 1280.0/3, 800.0/3, 0.0f, -1.0f, 1.0f);
615 for(int i
=1; i
<10; i
++){
616 if(abs(H
/i
- 240) < min
){ min
= H
/i
- 240; n
= i
; }
618 double new_w
= ((double)W
)/n
;
619 double new_h
= ((double)H
)/n
;
620 screen_offset_x
= (new_w
-320)/2;
621 screen_offset_y
= (new_h
-240)/2;
622 glOrtho(0.0f
, new_w
, new_h
, 0.0f
, -1.0f
, 1.0f
);
627 glOrtho(0.0f
, 320, 240, 0.0f
, -1.0f
, 1.0f
);
632 glMatrixMode( GL_MODELVIEW
);
641 printf(" resolution: %d x %d %s\n",W
,H
,fullscreen
?"fullscreen":"windowed");
642 printf(" pixel dimensions: %d x %d\n",screen_w
,screen_h
);
643 printf(" aspect ratio: %g\n",((double)W
)/H
);
644 printf(" opengl: %s\n",gl_flag
?"yes":"no");
645 printf(" x-offset: %d\n",screen_offset_x
);
646 printf(" y-offset: %d\n",screen_offset_y
);
647 printf(" video on\n");
654 audio
.freq
= SAMPLE_RATE
;
655 audio
.format
= AUDIO_S16
;
657 audio
.samples
= BUFFER_SIZE
;
658 audio
.callback
= audio_callback
;
660 SDL_AudioSpec gotten
;
662 if(SDL_OpenAudio(&audio
, &gotten
)<0){
663 report_error("sdl: cannot open audio (%s)\n", SDL_GetError());
668 printf(" sample rate = %d\n",gotten
.freq
);
669 printf(" channels = %d\n",gotten
.channels
);
670 printf(" samples = %d\n",gotten
.samples
);
671 printf(" format = %d\n",gotten
.format
);
673 if(gotten
.format
!= AUDIO_S16
){
674 printf(" WARNING: audio format not AUDIO_S16 :(\n");
677 lout
= xmalloc(gotten
.samples
*sizeof(float));
678 rout
= xmalloc(gotten
.samples
*sizeof(float));
679 buffer_size
= gotten
.samples
;
681 printf(" sound on\n");
687 void backend_init(int argc
, char* argv
[]){
690 parse_options(argc
, argv
, &fullscreen
, &gl_flag
);