铁血丹心

 找回密码
 我要成为铁血侠客
搜索
查看: 1827|回复: 5

绘制垂直string函数

[复制链接]
发表于 2013-5-21 11:02 | 显示全部楼层 |阅读模式

马上注册,结交更多侠友!

您需要 登录 才可以下载或查看,没有账号?我要成为铁血侠客

x
提供一点新思路,不要总是画横着的string了。
  1. function DrawVerticalStr(x,y,s,c,f,t)
  2.         local l=0;
  3.         for i=1,string.len(s),2 do
  4.                 DrawString(x,y+l*f,string.sub(s,i,i+1),c,f,t);
  5.                 l=l+1;
  6.         end
  7. end
复制代码
主要是看到diy专区都没讨论技术的了。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-21 12:06 | 显示全部楼层
前排支持……
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-21 15:11 | 显示全部楼层
一般来说尽量不要频繁地穿越C/Lua边界,效率会掉很多。
这个功能其实最好在c源码中实现,似乎也不是特别麻烦。

  1. // 写竖立字符串
  2. // x,y 坐标
  3. // str 字符串
  4. // color 颜色
  5. // size 字体大小,字形为宋体。
  6. // fontname 字体名
  7. // charset 字符集 0 GBK 1 big5
  8. // OScharset 0 简体显示 1 繁体显示
  9. int JY_DrawVerticalStr(int x, int y, const char *str,int color,int size,const char *fontname,
  10.                            int charset, int OScharset)
  11. {
  12.     SDL_Color c,c2;   
  13.         SDL_Surface *fontSurface=NULL;
  14.         int w,h;
  15.         SDL_Rect rect1,rect2,rect_dest;
  16.         SDL_Rect rect;
  17.         char tmp1[256],tmp2[256];
  18.         Uint16 tmp3[2];
  19.     TTF_Font *myfont;
  20.         SDL_Surface *tempSurface;
  21.         SDL_Surface *OriSurface = NULL;
  22.         int i ;
  23.         if(strlen(str)>127){
  24.                 JY_Error("JY_DrawStr: string length more than 127: %s",str);
  25.             return 0;
  26.         }

  27.     myfont=GetFont(fontname,size);
  28.         if(myfont==NULL)
  29.                 return 1;

  30.     c.r=(Uint8) ((color & 0xff0000) >>16);
  31.         c.g=(Uint8) ((color & 0xff00)>>8);
  32.         c.b=(Uint8) ((color & 0xff));

  33.         c2.r=c.r>>1;   //阴影色
  34.         c2.b=c.b>>1;
  35.         c2.g=c.g>>1;


  36.     if(charset==0 &&  OScharset==0){//GBK -->unicode简体
  37.          JY_CharSet(str,tmp2,3);      
  38.         }
  39.         else if(charset==0 &&  OScharset==1){//GBK -->unicode繁体
  40.         JY_CharSet(str,tmp1,1);
  41.         JY_CharSet(tmp1,tmp2,2);
  42.         }
  43.     else if(charset==1 &&  OScharset==0){ //big5-->unicode简体
  44.         JY_CharSet(str,tmp1,0);
  45.         JY_CharSet(tmp1,tmp2,3);
  46.         }
  47.         else if(charset==1 &&  OScharset==1){  ////big5-->unicode繁体
  48.         JY_CharSet(str,tmp2,2);
  49.         }
  50.         else{
  51.         strcpy(tmp2,str);
  52.         }
  53.         //增加\n
  54.         tmp3[1] = 0;
  55.         for(i=0;i<256;i+=2){
  56.                 *tmp3  = *(Uint16 *)(tmp2 + i);
  57.                 if(tmp3[0] == 0)break;
  58.                 if(g_Rotate==0){
  59.                         rect=g_Surface->clip_rect;
  60.                 }
  61.                 else{
  62.                         rect=RotateReverseRect(&g_Surface->clip_rect);
  63.                 }

  64.                 TTF_SizeUNICODE(myfont, (Uint16 *)tmp3, &w, &h);
  65.                 if( (x>=rect.x+rect.w) || (x+w+1) <=rect.x ||
  66.                         (y>=rect.y+rect.h) || (y+h+1) <=rect.y){      // 超出裁剪范围则不显示
  67.                         return 1;
  68.                 }
  69.                 fontSurface=TTF_RenderUNICODE_Blended(myfont,(Uint16 *)tmp3, c);  //生成表面
  70.                 if(fontSurface==NULL)
  71.                         return 1;
  72.    
  73.                 rect1.x=(Sint16)x;
  74.                 rect1.y=(Sint16)(y + (i / 2) * fontSurface->h);
  75.                 rect1.w=(Uint16)fontSurface->w;
  76.                 rect1.h=(Uint16)fontSurface->h;
  77.         //JY_ShowSurface(0);
  78.                 if(g_Rotate==0){
  79.                         rect2=rect1;

  80.                 //rect_dest.x=rect2.x+1;
  81.                 //rect_dest.y=rect2.y+1;
  82.                 //SDL_SetColors(fontSurface,&c2,1,1);
  83.                 //SDL_BlitSurface(fontSurface, NULL, g_Surface, &rect_dest);    //表面写到游戏表面--阴影色

  84.                         rect_dest.x=rect2.x;
  85.                         rect_dest.y=rect2.y;
  86.                         SDL_SetColors(fontSurface,&c,1,1);
  87.                 //SDL_BlitSurface(fontSurface, NULL, OriSurface, &rect_dest);    //表面写到ori表面
  88.                         SDL_BlitSurface(fontSurface, NULL, g_Surface, &rect_dest);    //表面写到ori表面

  89.                         }
  90.                 else if(g_Rotate==1){
  91.                         tempSurface=RotateSurface(fontSurface);
  92.                         SDL_FreeSurface(fontSurface);
  93.                         fontSurface=tempSurface;
  94.                         rect2=RotateRect(&rect1);

  95.                 //rect_dest.x=rect2.x-1;
  96.                 //rect_dest.y=rect2.y+1;
  97.                 //SDL_SetColors(fontSurface,&c2,1,1);
  98.                 //SDL_BlitSurface(fontSurface, NULL, g_Surface, &rect_dest);    //表面写到游戏表面 --阴影色

  99.                         rect_dest.x=rect2.x;
  100.                         rect_dest.y=rect2.y;
  101.                         SDL_SetColors(fontSurface,&c,1,1);
  102.                 //SDL_BlitSurface(fontSurface, NULL, OriSurface, &rect_dest);    //表面写到ori表面
  103.                         SDL_BlitSurface(fontSurface, NULL, g_Surface, &rect_dest);    //表面写到ori表面
  104.                        
  105.                 }

  106.                 SDL_FreeSurface(fontSurface);   //释放表面
  107.                 SDL_FreeSurface(OriSurface);   //释放表面
  108.         }
  109.         //free(tmp3);
  110.     return 0;
  111. }
复制代码
随后在边界函数处改成这样,给drawstr增加一个隐藏参数Vertical,倘若被赋值则执行竖排绘制字符串

  1. int HAPI_DrawStr(lua_State *pL)
  2. {
  3.     int x=(int)lua_tonumber(pL,1);
  4.         int y=(int)lua_tonumber(pL,2);
  5.         const char *str=lua_tostring(pL,3);
  6.         int color=(int)lua_tonumber(pL,4);
  7.         int size=(int)lua_tonumber(pL,5);
  8.         const char *fontname=lua_tostring(pL,6);
  9.         int charset=(int)lua_tonumber(pL,7);
  10.         int OScharset=(int)lua_tonumber(pL,8);
  11.         if(lua_isnoneornil(pL,9)==0 ){
  12.                 JY_DrawVerticalStr(x, y, str,color,size,fontname,charset,OScharset);
  13.         }
  14.         else
  15.         {
  16.                 JY_DrawStr(x, y, str,color,size,fontname,charset,OScharset);
  17.         }
复制代码
lua的边界接口函数也只需稍微处理一下即可

  1. function DrawString(x,y,str,color,size,vert)         --显示阴影字符串,增加竖排绘制
  2. --    local r,g,b=GetRGB(color);
  3. --    lib.DrawStr(x+1,y+1,str,RGB(math.modf(r/2),math.modf(g/2),math.modf(b/2)),size,CC.FontName,CC.SrcCharSet,CC.OSCharSet);
  4.     lib.DrawStr(x,y,str,color,size,CC.FontName,CC.SrcCharSet,CC.OSCharSet,vert);
  5. end
复制代码
PS:我这里将阴影字符串注释掉了,如果有人想移植的话需要更改部分内容。
基本上改好,整个代码只穿过一次边界,效率应该比每次都要穿越一次边界的lua法来的高些。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-21 15:50 | 显示全部楼层
本帖最后由 蓝烟清 于 2013-5-21 15:55 编辑

回复 扯淡天王 的帖子

扯淡天王,您好
fontSurface=TTF_RenderUNICODE_Blended(myfont,(Uint16 *)tmp3, c);
这个函数是相当消耗时间的,其实只需要调用一次就可以了,一次渲染所有的字串


SDL_BlitSurface(fontSurface, NULL, g_Surface, &rect_dest);函数做文章


rect_dest可以设置x, y, w, h

  1. //判断字符串的长度,不过只支持中文是真的
  2. int len = strlen(str);

  3. for(i=0;i<len;i+=2){

  4. rect_dest.x = (Sint16)x;

  5. rect_dest.y = (Sint16)(y + (i / 2) * size);

  6. rect_dest.w = (Uint16)size;

  7. rect_dest.h = (Uint16)fontSurface->h;



  8. rect1.x = (Sint16)(i/2)*size;

  9. rect1.y = 0;

  10. rect1.w = (Uint16)size;

  11. rect1.h = (Uint16)fontSurface->h;

  12. SDL_BlitSurface(fontSurface, &rect1, g_Surface, &rect_dest);
  13. }
复制代码




可能还需要增加文字间隔的参数。


点评

这个着实不知道,但是目测应该是有关系的  发表于 2013-5-21 16:20
TTF_RenderUNICODE_Blended 这个函数的耗时与字串长度有没有关系?  发表于 2013-5-21 16:08
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-21 16:13 | 显示全部楼层
好主意,吹捧蓝大大。
字数字数字数。
蓝大大威武。

点评

我随便写个函数引来一堆大神。。。  发表于 2013-5-21 20:11
BS  发表于 2013-5-21 17:00
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-5-21 23:51 | 显示全部楼层
本帖最后由 weyl 于 2013-5-21 23:55 编辑

lua版本身用c和lua混合编程,互相穿越的情况极多,其实不差这点。
我觉得这个函数在字串上显示的不足之处在于并没有考虑中英文混合的情况。在竖排的时候,英文和数字经常是旋转90°的,是否要用到gfx进行旋转?如果英文和数字直接使用简单横排,那么由于宽度的问题,英文字符可能需要增加一个偏移,或者将半角的英文数字转为全角。如果所用的英文字体是非等宽的,那么又是一个头痛的问题。

点评

我也写了一个半符转全符的的函数,但是替换的字符都是手写的很不可靠的感觉。  发表于 2013-5-22 02:59
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。

本版积分规则

小黑屋|手机版|铁血丹心

GMT+8, 2024-5-4 10:36

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表