网页功能: 加入收藏 设为首页 网站搜索  
在游戏中显示GBK点阵汉字
发表日期:2007-01-16作者:[转贴] 出处:  


  大家注意到没有,RA2的中文版本使用的是GBK点阵字库,这样做有一个好处:不管玩家是用的简体还是繁体都能识别显示的文字。 

  GBK的意思大概是“国家标准汉字扩展字符集”吧,记不清了。但它的确是个好东东,比GB2312、BIG5什么的强多了。因为它包括GB2312、GBK的所有字符而且还补充了很多字,另外,还包括日文、朝鲜文以及大量的符号字符。 

  我在UCDOS for win版本里面找到了GBK的点阵字库(HZK12.GBK、HZK14.GBK、HZK16.GBK)。分析了一下,知道了结构。这里是我写的一个演示程序,程序编译需要有sdl库。遵循“惯例”,按F4切换全屏/窗口状态,Esc退出。程序把标准输出和标准错误重定向到"stdout.txt"和"stderr.txt"中。 


#include <time.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <windows.h> 

#include "sdl.h" 
#include "SDL_image.h" 
#include "sfont.h" 

//--------------------------------------------------------------------------- 
#define STDOUT_FILE "stdout.txt" 
#define STDERR_FILE "stderr.txt" 

SDL_Surface *screen; 
Uint32 fps; 
Uint32 AppStartTime = 0; 
Uint32 frame_count = 0; 
static Uint32 frames; 

SDL_Event event; 
SDL_Surface * SetMode( int Width, int Height, int BPP, int Flags ); 
SDL_Surface * LoadBMP( char * filename ); 
void MainLoops( int ( * EventFunc)( ), void ( * DrawFunc )( ), int DelayTime ); 
void Blt( SDL_Surface * image, int x, int y ); 
void TileBlt( SDL_Surface * image, int x, int y ); 
void SetTransparentColor( SDL_Surface * sprite, int R, int G, int B ); 
void IoRedirect( ); 
void cleanup_output( ); 
void initfps(); 

//--------------------------------------------------------------------------- 
Uint8 HZK12[574560]; 
Uint8 HZK14[670320]; 
Uint8 HZK16[766080]; 
BOOL HZ_Init(); 
BOOL HZ_TextOut( SDL_Surface * image, int x, int y, int width, int space, unsigned char * str ); 
//--------------------------------------------------------------------------- 

int ProcessEvent( ); 
void DrawFrame( ); 

SDL_Surface * bg, * font; 
int ix, iy, jx, jy; 
int Width = 640; 
int Height = 480; 
int bpp = 16; 
int ScreenMode = 0; 

WINAPI WinMain(HINSTANCE hInstPre, HINSTANCE hInstance, LPSTR cmd, int xxx ) 

    char TimeString[256]; 
    time_t timer; 
    struct tm *tblock; 

    HZ_Init(); 
    IoRedirect( ); 
    frames = 0; 
    timer = time(NULL); 
    tblock = localtime(&timer); 
    strftime( TimeString, 256, "Time=%Z: %Y-%m-%d %a %H:%M:%S", tblock ); 
    printf( "%s\n", TimeString ); 

    SetMode( Width, Height, bpp, SDL_SWSURFACE|ScreenMode ); 
    SDL_ShowCursor(0); 
    SDL_WM_SetCaption( "demo", "demo" ); 

    bg = IMG_Load( ".\\2k_bg.gif" ); 
    font = IMG_Load( ".\\small.gif" ); 

    InitFont(font); 
    SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 127 ); 

    ix=iy=0; 
    jx=jy= Height>>1; 
    srand( (Uint32)timer ); 

    MainLoops( ProcessEvent, DrawFrame, 0 ); 

    printf( "ScreenMode=%d*%d*%d\nFPS=%u", Width, Height, bpp, fps ); 

    return 0; 


int ProcessEvent( ) 

    Uint8 *keystate; 

    keystate = SDL_GetKeyState( NULL ); 
    if ( ( keystate[SDLK_ESCAPE] ) || ( keystate[SDLK_q] ) ) 
        return 0; 
    if ( keystate[SDLK_F4] ) 
    { 
        if ( ScreenMode )
            ScreenMode = 0; 
        else
            ScreenMode = SDL_FULLSCREEN;

        SetMode( Width, Height, bpp, SDL_SWSURFACE|ScreenMode ); 
        initfps( ); 
    } 

    return 1; 


void DrawFrame( ) 

    char tmp[256]; 
    int step = 4; 

    // 
    sprintf( tmp, "TotalFrame=%u", frames ); 

    TileBlt( bg, 0, 0 ); 

    SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 4 ); 
    PutString( screen, ix % Width - 6, iy % Height - 6, tmp ); 
    SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 8 ); 
    PutString( screen, ix % Width - 5, iy % Height - 5, tmp ); 
    SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 16 ); 
    PutString( screen, ix % Width - 4, iy % Height - 4, tmp ); 
    SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 32 ); 
    PutString( screen, ix % Width - 3, iy % Height - 3, tmp ); 
    SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 64 ); 
    PutString( screen, ix % Width - 2, iy % Height - 2, tmp ); 
    SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 128 ); 
    PutString( screen, ix % Width - 1, iy % Height - 1, tmp ); 
    SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 192 ); 
    PutString( screen, ix % Width, iy % Height, tmp ); 

    PutString( screen, ix % Width, iy % Height + 40, tmp ); 

    if ( rand( ) % 400 < 2 ) 
    { 
        jx = rand( ) % ( Width - 10 ); 
        jy = rand( ) % ( Height - 10 ); 
    } 

    sprintf( tmp, "FPS=%d", fps ); 
    PutString( screen, 7, 7, tmp ); 
    //聞波,2000  
    HZ_TextOut( screen, 10, 300, 16, 0, "十步殺一人,千里不留行"); 
    HZ_TextOut( screen, 10, 318, 14, 0, "十步殺一人,千里不留行" ); 
    HZ_TextOut( screen, 10, 334, 12, 0, "十步殺一人,千里不留行" ); 
    ix += step; 
    iy += step; 

//--------------------------------------------------------------------------- 

//--------------------------------------------------------------------------- 
SDL_Surface * SetMode( int Width, int Height, int BPP, int Flags ) 

    /* Initialize the SDL library */ 
    if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) 
    { 
        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError( ) ); 
        return NULL; 
    } 

    /* Clean up on exit */ 
    atexit(SDL_Quit); 

    /* Initialize the display in a 640x480 8-bit palettized mode */ 
    screen = SDL_SetVideoMode( Width, Height, BPP, Flags ); 
    if ( screen == NULL ) 
    { 
        fprintf( stderr, "Couldn't set %dx%dx%d video mode: %s\n", Width, Height, BPP, SDL_GetError( ) ); 
    } 

    return screen; 

//--------------------------------------------------------------------------- 

void initfps( ) 

    AppStartTime = SDL_GetTicks(); 
    frame_count = 0; 

//--------------------------------------------------------------------------- 

void MainLoops( int ( * EventFunc)( ), void ( * DrawFunc)( ), int DelayTime ) 

    if ( EventFunc&&DrawFunc ) 
    { 
        memset( &event, 0, sizeof( SDL_Event ) ); 
        initfps( ); 

        while( EventFunc( ) ) 
        { 
            SDL_PollEvent(&event); 
            if ( event.type == SDL_ACTIVEEVENT ) 
            { 
                if ( ( ( event.active.state & SDL_APPACTIVE ) == FALSE ) ||
( event.active.gain == FALSE ) ) 
                    initfps( ); 
            } 
            SDL_PumpEvents(); 
            DrawFunc( ); 
            SDL_UpdateRect(screen,0, 0, 0, 0); 
            frame_count ++; 
            frames ++; 
            fps = frame_count * 1000 / ( SDL_GetTicks( ) - AppStartTime ); 
            if ( DelayTime ) SDL_Delay( DelayTime ); 
        } 
    } 

//--------------------------------------------------------------------------- 

SDL_Surface * LoadBMP( char * filename ) 

    SDL_Surface * imagebmp, * image; 

    imagebmp = SDL_LoadBMP( filename ); 
    if ( imagebmp == NULL ) 
        return NULL; 

    if ( imagebmp->format->palette != NULL ) 
    { 
        SDL_SetColors( screen, imagebmp->format->palette->colors, 0, imagebmp->format->palette->ncolors ); 
    } 

    /* Convert the image to the video format (maps colors) */ 
    image = SDL_DisplayFormat( imagebmp ); 
    SDL_FreeSurface( imagebmp ); 

    return image; 

//--------------------------------------------------------------------------- 

void Blt( SDL_Surface * image, int x, int y ) 

    int Row, Col, r, c, shiftx, shifty; 
    SDL_Rect dest, src; 

    /* out of screen */ 
    if ( ( x > screen->w ) || ( y > screen->h ) ||
( x + image->w < 1 ) || ( y + image->h < 1 ) ) 
        return; 

    src.x = 0; 
    src.y = 0; 
    src.w = image->w; 
    src.h = image->h; 
    dest.x = x; 
    dest.y = y; 
    dest.w = src.w; 
    if ( y < 0 ) 
    { 
        src.y = 0 - y; 
        src.h = image->h + src.y; 
        dest.y = 0; 
    } 
    dest.h = src.h; 

    SDL_BlitSurface( image, &src, screen, &dest ); 

//--------------------------------------------------------------------------- 

void TileBlt( SDL_Surface * image, int x, int y ) 

    int Row, Col, r, c, shiftx, shifty; 
    SDL_Rect dest, src; 

    shiftx = x % image->w; 
    shifty = y % image->h; 

    if ( shiftx >0 ) shiftx -= image->w; 
    if ( shifty >0 ) shifty -= image->h; 

    Row = screen->h / image->h + 2; 
    Col = screen->w / image->w + 2; 

    dest.x = 0; 
    dest.y = 0; 
    dest.w = image->w; 
    dest.h = image->h; 
    src.x = 0; 
    src.y = 0; 
    src.w = image->w; 
    src.h = image->h; 

    for ( r = 0; r < Row; r ++ ) 
    { 
        if ( r ) 
        { 
            src.y = 0; 
            src.h = image->h; 
            dest.h = image->h; 
            dest.y = image->h * r + shifty; 
        } 
        else 
        { /* first line ? */ 
            src.y = 0 - shifty; 
            src.h = image->h; 
            dest.h = image->h + shifty; 
            dest.y = 0; 
        } 

        for ( c = 0; c < Col; c ++ ) 
        { 
            dest.x = image->w * c + shiftx; 
            SDL_BlitSurface( image, &src, screen, &dest ); 
        } 
    } 

//--------------------------------------------------------------------------- 

void SetTransparentColor( SDL_Surface * sprite, int R, int G, int B ) 

    SDL_SetColorKey( sprite, SDL_SRCCOLORKEY|SDL_RLEACCEL, SDL_MapRGB( sprite->format, R, G, B ) ); 

//--------------------------------------------------------------------------- 

/* Remove the output files if there was no output written */ 
static void cleanup_output( ) 

    FILE *file; 
    int empty; 

    /* Flush the output in case anything is queued */ 
    fclose(stdout); 
    fclose(stderr); 

    /* See if the files have any output in them */ 
    file = fopen(STDOUT_FILE, "rb"); 
    if ( file ) 
    { 
        empty = (fgetc(file) == EOF) ? 1 : 0; 
        fclose(file); 
        if ( empty )
            remove(STDOUT_FILE); 
    } 
    file = fopen(STDERR_FILE, "rb"); 
    if ( file ) 
    { 
        empty = (fgetc(file) == EOF) ? 1 : 0; 
        fclose(file); 
        if ( empty )
            remove(STDERR_FILE); 
    } 

//--------------------------------------------------------------------------- 

void IoRedirect( ) 

    FILE *newfp; 

    /* Redirect standard standard output */ 
    newfp = freopen(STDOUT_FILE, "w", stdout); 
    if ( newfp == NULL ) 
    { /* This happens on NT */ 
#if !defined(stdout) 
        stdout = fopen(STDOUT_FILE, "w"); 
#else 
        newfp = fopen(STDOUT_FILE, "w"); 
        if ( newfp ) *stdout = *newfp; 
#endif 
    } 

    /* Redirect standard standard error */ 
    newfp = freopen(STDERR_FILE, "w", stderr); 
    if ( newfp == NULL ) 
    { /* This happens on NT */ 
#if !defined(stderr) 
        stderr = fopen(STDERR_FILE, "w"); 
#else 
        newfp = fopen(STDERR_FILE, "w"); 
        if ( newfp ) *stderr = *newfp; 
#endif 
    } 

    setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* Line buffered */ 
    setbuf(stderr, NULL); /* No buffering */ 
    atexit(cleanup_output); 

//--------------------------------------------------------------------------- 

BOOL HZ_Init() 

    FILE * file; 

    file = fopen( ".\\HZK16.GBK", "rb" ); 
    fread( HZK16, 32, 0x5d84, file ); 
    fclose( file ); 
    file = fopen( ".\\HZK14.GBK", "rb" ); 
    fread( HZK14, 28, 0x5d84, file ); 
    fclose( file ); 
    file = fopen( ".\\HZK12.GBK", "rb" ); 
    fread( HZK12, 24, 0x5d84, file ); 
    fclose( file ); 

    return TRUE; 

//--------------------------------------------------------------------------- 

BOOL HZ_TextOut( SDL_Surface * image, int x, int y, int width, int space, unsigned char * str ) 

    Uint8 * bufptr; 
    Uint8 * HZK; 
    Uint16 Bits[16]; 
    int i,j,k, m, offset = 0; 
    unsigned char q; 
    unsigned char w; 

    switch ( width ) 
    { 
    case 12: 
        HZK = HZK12; 
        break; 
    case 14: 
        HZK = HZK14; 
        break; 
    case 16: 
        HZK = HZK16; 
        break; 
    default: 
        return FALSE; 
    } 
    bufptr = (unsigned char*)image->pixels; 

    m = strlen( str ); 
    for ( k = 0; k < m; k +=2 ) 
    { 
        Uint32 X, Y, Z, M; 
        q = str[k]; 
        w = str[k+1]; 

        if ( w > 0xa0 ) 
        { 
            M = 0x5e; 
            Y = w - 0xa1; 
            if ( q > 0xa0 ) 
            { 
                X = q - 0xa1; 
                Z = 0; 
            } 
            else 
            { 
                X = q - 0x81; 
                Z = 0x2284; 
            } 
        } 
        else 
        { 
            M = 0x60; 
            if ( w > 0x7f ) Y = w - 0x41; 
            else Y = w - 0x40; 

            if ( q > 0xa0 ) 
            { 
                X = q - 0xa1; 
                Z = 0x3a44; 
            } 
            else 
            { 
                X = q - 0x81; 
                Z = 0x2e44; 
            } 
        } 
        memcpy( Bits, HZK + ( X * M + Y + Z ) * width * 2, width * 2 ); 

        for ( i = 0; i < width; i ++ ) // row 
        { 
Uint16 line; 

            line = Bits[ i ]; 
            line = ( line >> 8 ) + ( line << 8 ); 

            for ( j = 0; j < 16 ; j ++ ) //col 
            { 
                int index; 
                int mask = 1; 

                index = offset + x + 16 - j - 1 + ( y + i ) * image->pitch / image->format->BytesPerPixel; 
                mask <<= j; 
                if ( mask & line ) 
                { 
                    bufptr[ index * 2 ] = 0xff; 
                    bufptr[ index * 2 + 1 ] = 0xff; 
                } 
            } 
        } 
        offset += width + space; 
    } 
    return TRUE; 

//--------------------------------------------------------------------------- 

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 在游戏中显示GBK点阵汉字
本类热点文章
  如何用D3D/OpenGL在制作2D游戏中高效地..
  自己绘制True type font字体
  使用CPU时间戳进行高精度计时
  阵汉字显示
  程序员的超强外挂——Visual Assist .N..
  用VC++实现console程序显示彩色文本 wx..
  制做自己的点阵字库的方法和程序
  “变速齿轮”再研究
  一个简单的线程管理机制
  VC编程中常用快捷键
  Delpih中的Windows API编程初步
  BIG5到GB的转换技术
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00376