📄 sdl.c
字号:
/*************************************************************************** sdl.c - description ------------------- begin : Thu Apr 20 2000 copyright : (C) 2000 by Michael Speck email : kulkanie@gmx.net ***************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/#include <SDL.h>#include <stdlib.h>#include <string.h>#include "sdl.h"#ifdef USE_PNG#include <png.h>#endifextern int term_game;Sdl sdl;SDL_Cursor *empty_cursor = 0;SDL_Cursor *std_cursor = 0;/*====================================================================Default video modes. The first value is the id and indicatesif a mode is a standard video mode. If the mode was created bydirectly by video_mode() this id is set to -1. The very lastvalue indicates if this is a valid mode and is checked byinit_sdl(). Init_sdl sets the available desktop bit depth.====================================================================*/int const mode_count = 2;Video_Mode modes[] = { { 0, "640x480x16 Window", 640, 480, BITDEPTH, SDL_SWSURFACE, 0 }, { 1, "640x480x16 Fullscreen", 640, 480, BITDEPTH, SDL_SWSURFACE | SDL_FULLSCREEN, 0 },};Video_Mode *def_mode = &modes[0]; /* default resolution */Video_Mode cur_mode; /* current video mode set in set_video_mode *//* timer */int cur_time, last_time;/* sdl surface */#ifdef USE_PNG/* loads an image from png file and returns surface * or NULL in case of error; * you can get additional information with SDL_GetError * * stolen from SDL_image: * * Copyright (C) 1999 Sam Lantinga * * Sam Lantinga * 5635-34 Springhouse Dr. * Pleasanton, CA 94588 (USA) * slouken@devolution.com */SDL_Surface *load_png( const char *file ){ FILE *volatile fp = NULL; SDL_Surface *volatile surface = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_bytep *volatile row_pointers = NULL; png_uint_32 width, height; int bit_depth, color_type, interlace_type; Uint32 Rmask; Uint32 Gmask; Uint32 Bmask; Uint32 Amask; SDL_Palette *palette; int row, i; volatile int ckey = -1; png_color_16 *transv; /* create the PNG loading context structure */ png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); if( png_ptr == NULL ) { SDL_SetError( "Couldn't allocate memory for PNG file" ); goto done; } /* allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct( png_ptr ); if( info_ptr == NULL ) { SDL_SetError( "Couldn't create image information for PNG file" ); goto done; } /* set error handling if you are using setjmp/longjmp method (this is * the normal method of doing things with libpng). REQUIRED unless you * set up your own error handlers in png_create_read_struct() earlier. */ if( setjmp( png_ptr->jmpbuf ) ) { SDL_SetError( "Error reading the PNG file." ); goto done; } /* open file */ fp = fopen( file, "r" ); if( fp == NULL ) { SDL_SetError( "Could not open png file." ); goto done; } png_init_io( png_ptr, fp ); /* read PNG header info */ png_read_info( png_ptr, info_ptr ); png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL ); /* tell libpng to strip 16 bit/color files down to 8 bits/color */ png_set_strip_16( png_ptr ); /* extract multiple pixels with bit depths of 1, 2, and 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ png_set_packing( png_ptr ); /* scale greyscale values to the range 0..255 */ if( color_type == PNG_COLOR_TYPE_GRAY ) png_set_expand( png_ptr ); /* for images with a single "transparent colour", set colour key; if more than one index has transparency, use full alpha channel */ if( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) ) { int num_trans; Uint8 *trans; png_get_tRNS( png_ptr, info_ptr, &trans, &num_trans, &transv ); if( color_type == PNG_COLOR_TYPE_PALETTE ) { if( num_trans == 1 ) { /* exactly one transparent value: set colour key */ ckey = trans[0]; } else png_set_expand( png_ptr ); } else ckey = 0; /* actual value will be set later */ } if( color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) png_set_gray_to_rgb( png_ptr ); png_read_update_info( png_ptr, info_ptr ); png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL ); /* allocate the SDL surface to hold the image */ Rmask = Gmask = Bmask = Amask = 0 ; if( color_type != PNG_COLOR_TYPE_PALETTE ) { if( SDL_BYTEORDER == SDL_LIL_ENDIAN ) { Rmask = 0x000000FF; Gmask = 0x0000FF00; Bmask = 0x00FF0000; Amask = (info_ptr->channels == 4) ? 0xFF000000 : 0; } else { int s = (info_ptr->channels == 4) ? 0 : 8; Rmask = 0xFF000000 >> s; Gmask = 0x00FF0000 >> s; Bmask = 0x0000FF00 >> s; Amask = 0x000000FF >> s; } } surface = SDL_AllocSurface( SDL_SWSURFACE, width, height, bit_depth * info_ptr->channels, Rmask, Gmask, Bmask, Amask ); if( surface == NULL ) { SDL_SetError( "Out of memory" ); goto done; } if( ckey != -1 ) { if( color_type != PNG_COLOR_TYPE_PALETTE ) /* FIXME: should these be truncated or shifted down? */ ckey = SDL_MapRGB( surface->format, (Uint8)transv->red, (Uint8)transv->green, (Uint8)transv->blue ); SDL_SetColorKey( surface, SDL_SRCCOLORKEY, ckey ); } /* create the array of pointers to image data */ row_pointers = (png_bytep*)malloc( sizeof( png_bytep ) * height ); if( ( row_pointers == NULL ) ) { SDL_SetError( "Out of memory" ); SDL_FreeSurface( surface ); surface = NULL; goto done; } for( row = 0; row < (int)height; row++ ) { row_pointers[row] = (png_bytep) (Uint8*)surface->pixels + row * surface->pitch; } /* read the entire image in one go */ png_read_image( png_ptr, row_pointers ); /* read rest of file, get additional chunks in info_ptr - REQUIRED */ png_read_end( png_ptr, info_ptr ); /* load the palette, if any */ palette = surface->format->palette; if( palette ) { if( color_type == PNG_COLOR_TYPE_GRAY ) { palette->ncolors = 256; for( i = 0; i < 256; i++ ) { palette->colors[i].r = i; palette->colors[i].g = i; palette->colors[i].b = i; } } else if( info_ptr->num_palette > 0 ) { palette->ncolors = info_ptr->num_palette; for( i = 0; i < info_ptr->num_palette; ++i ) { palette->colors[i].b = info_ptr->palette[i].blue; palette->colors[i].g = info_ptr->palette[i].green; palette->colors[i].r = info_ptr->palette[i].red; } } }done: /* clean up and return */ png_destroy_read_struct( &png_ptr, info_ptr ? &info_ptr : (png_infopp)0, (png_infopp)0 ); if( row_pointers ) free( row_pointers ); if( fp ) fclose( fp ); return surface;}#endif/* return full path of bitmap */inline void get_full_bmp_path( char *full_path, char *file_name ){ sprintf(full_path, "%s/gfx/%s", SRC_DIR, file_name );}/* load a surface from file putting it in soft or hardware mem*/SDL_Surface* load_surf(char *fname, int f){ SDL_Surface *buf; SDL_Surface *new_sur; char path[ 512 ]; SDL_PixelFormat *spf;#ifdef USE_PNG char png_name[32];#endif#ifdef USE_PNG /* override file name as all graphics were changed from bitmap to png so the extension must be corrected */ memset( png_name, 0, sizeof( png_name ) ); strncpy( png_name, fname, strlen( fname ) - 4 ); strcat( png_name, ".png" ); get_full_bmp_path( path, png_name ); buf = load_png( path );#else get_full_bmp_path( path, fname ); buf = SDL_LoadBMP( path );#endif if ( buf == 0 ) { fprintf( stderr, "load_surf: file '%s' not found or not enough memory\n", path ); if ( f & SDL_NONFATAL ) return 0; else exit( 1 ); }/* if ( !(f & SDL_HWSURFACE) ) { SDL_SetColorKey( buf, SDL_SRCCOLORKEY, 0x0 ); return buf; } new_sur = create_surf(buf->w, buf->h, f); SDL_BlitSurface(buf, 0, new_sur, 0); SDL_FreeSurface(buf);*/ spf = SDL_GetVideoSurface()->format; new_sur = SDL_ConvertSurface( buf, spf, f ); SDL_FreeSurface( buf ); SDL_SetColorKey( new_sur, SDL_SRCCOLORKEY, 0x0 ); SDL_SetAlpha( new_sur, 0, 0 ); /* no alpha */ return new_sur;}/* create an surface MUST NOT BE USED IF NO SDLSCREEN IS SET*/SDL_Surface* create_surf(int w, int h, int f){ SDL_Surface *sur; SDL_PixelFormat *spf = SDL_GetVideoSurface()->format; if ((sur = SDL_CreateRGBSurface(f, w, h, spf->BitsPerPixel, spf->Rmask, spf->Gmask, spf->Bmask, spf->Amask)) == 0) { fprintf(stderr, "create_surf: not enough memory to create surface...\n"); exit(1); }/* if (f & SDL_HWSURFACE && !(sur->flags & SDL_HWSURFACE)) fprintf(stderr, "unable to create surface (%ix%ix%i) in hardware memory...\n", w, h, spf->BitsPerPixel);*/ SDL_SetColorKey(sur, SDL_SRCCOLORKEY, 0x0); SDL_SetAlpha(sur, 0, 0); /* no alpha */ return sur;}/* * Free a surface if != NULL and set pointer to NULL */void free_surf( SDL_Surface **surf ){ if ( *surf ) SDL_FreeSurface( *surf ); *surf = 0;}/* lock surface*/inline void lock_surf(SDL_Surface *sur){ if (SDL_MUSTLOCK(sur)) SDL_LockSurface(sur);}/* unlock surface*/inline void unlock_surf(SDL_Surface *sur){ if (SDL_MUSTLOCK(sur)) SDL_UnlockSurface(sur);}/* blit surface with destination DEST and source SOURCE using it's actual alpha and color key settings*/void blit_surf(void){#ifdef SDL_1_1_5 if (sdl.s.s->flags & SDL_SRCALPHA) SDL_SetAlpha(sdl.s.s, SDL_SRCALPHA, 255 - sdl.s.s->format->alpha);#endif SDL_BlitSurface(sdl.s.s, &sdl.s.r, sdl.d.s, &sdl.d.r);#ifdef SDL_1_1_5 if (sdl.s.s->flags & SDL_SRCALPHA) SDL_SetAlpha(sdl.s.s, SDL_SRCALPHA, 255 - sdl.s.s->format->alpha);#endif}/* do an alpha blit*/void alpha_blit_surf(int alpha){ #ifdef SDL_1_1_5 SDL_SetAlpha(sdl.s.s, SDL_SRCALPHA, 255 - alpha);#else SDL_SetAlpha(sdl.s.s, SDL_SRCALPHA, alpha);#endif SDL_BlitSurface(sdl.s.s, &sdl.s.r, sdl.d.s, &sdl.d.r); SDL_SetAlpha(sdl.s.s, 0, 0);}/* fill surface with color c*/void fill_surf(int c){ SDL_FillRect(sdl.d.s, &sdl.d.r, SDL_MapRGB(sdl.d.s->format, c >> 16, (c >> 8) & 0xFF, c & 0xFF));}/* set clipping rect */void set_surf_clip( SDL_Surface *surf, int x, int y, int w, int h ){#ifdef SDL_1_1_5 SDL_Rect rect = { x, y, w, h }; if ( w == h || h == 0 ) SDL_SetClipRect( surf, 0 ); else SDL_SetClipRect( surf, &rect );#else SDL_SetClipping( surf, x, y, w, h );#endif}/* set pixel */Uint32 set_pixel( SDL_Surface *surf, int x, int y, int pixel ){ int pos = 0; pos = y * surf->pitch + x * surf->format->BytesPerPixel; memcpy( surf->pixels + pos, &pixel, surf->format->BytesPerPixel );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -