Advertisement
snake5

SGScript - pixel draw lib. v0.2

May 22nd, 2014
378
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. // Requires the SGS-SDL context
  3.  
  4.  
  5. /*
  6.     Utility functions
  7. */
  8.  
  9. function io_normalize_path( path ){ return string_replace( path, "\\", "/" ); }
  10. function io_dirname( path )
  11. {
  12.     path = string_explode( io_normalize_path( path ), "/" );
  13.     path.pop();
  14.     return string_implode( path, "/" );
  15. }
  16.  
  17. function sgson_eval( text ){ return eval( "return " $ text $ ";" ); }
  18.  
  19.  
  20. /*
  21.     class SS_SpriteSheet
  22.    
  23.     - create( spec, imgroot = "./" )
  24.     - createFromText( sgsontext, imgroot = "./" )
  25.     - createFromFile( sgsonfile, imgroot = dirname(file)$"/" )
  26.     - createGrid( image, hsz, vsz, hsp = 0, vsp = 0, namefunc = (=> %x_%y) )
  27.     - getSprite( name )
  28.     + texture : SS_Texture
  29. */
  30.  
  31. global SS_SpriteSheet = {};
  32.  
  33. function SS_SpriteSheet.create( spec, imgroot )
  34. {
  35.     imgroot ||= "./";
  36.    
  37.     if( !@spec.image )
  38.         WARNING( "expected SPEC.image" );
  39.     if( !is_dict( @spec.sprites ) )
  40.         WARNING( "expected SPEC.sprites as dict" );
  41.    
  42.     texture = SS_CreateTexture( imgroot $ spec.image, "nolerp" );
  43.     if( !texture )
  44.         return;
  45.     tw = texture.width;
  46.     th = texture.height;
  47.    
  48.     sprites = {};
  49.     foreach( spritename, spritespec : spec.sprites )
  50.     {
  51.         tx1 = @spritespec.x1;
  52.         ty1 = @spritespec.y1;
  53.         tx2 = @spritespec.x2;
  54.         ty2 = @spritespec.y2;
  55.         ogx = toint( @spritespec.origin_x );
  56.         ogy = toint( @spritespec.origin_y );
  57.         if( tx1 === null ||
  58.             ty1 === null ||
  59.             tx2 === null ||
  60.             ty2 === null )
  61.             WARNING( "all coords (x1,y1,x2,y2) must be set for each sprite" );
  62.         if( ty1 >= ty2 || tx1 >= tx2 )
  63.             WARNING( "coord 1 is greater than or equal to coord 2" );
  64.         sprites[ spritename ] =
  65.         [
  66.             tx2 - tx1, ty2 - ty1, ogx, ogy,
  67.             tx1 / tw, ty1 / th, tx2 / tw, ty2 / th,
  68.             tx1, ty1, tx2, ty2
  69.         ];
  70.     }
  71.    
  72.     data =
  73.     {
  74.         texture = texture,
  75.         sprites = sprites,
  76.     };
  77.    
  78.     return class( data, SS_SpriteSheet );
  79. }
  80.  
  81. function SS_SpriteSheet.createFromText( sgsontext, imgroot )
  82. {
  83.     spec = sgson_eval( sgsontext );
  84.     if( !spec )
  85.         return;
  86.     return this.create( spec, imgroot );
  87. }
  88.  
  89. function SS_SpriteSheet.createFromFile( sgsonfile, imgroot )
  90. {
  91.     imgroot ||= io_dirname( sgsonfile ) $ "/";
  92.     text = io_file_read( sgsonfile );
  93.     if( text === null )
  94.         return;
  95.     return this.createFromText( text, imgroot );
  96. }
  97.  
  98. function SS_SpriteSheet.createGrid( image, hsz, vsz, hsp, vsp, namefunc )
  99. {
  100.     hsz = toint(hsz);
  101.     vsz = toint(vsz);
  102.     hsp = toint(hsp);
  103.     vsp = toint(vsp);
  104.     namefunc ||= function( x, y, i ){ return x $ "_" $ y; };
  105.    
  106.     texture = SS_CreateTexture( image, "nolerp" );
  107.     if( !texture )
  108.         return;
  109.     tw = texture.width;
  110.     th = texture.height;
  111.    
  112.     sprites = {};
  113.     i = 0;
  114.     ix = 0;
  115.     iy = 0;
  116.     for( y = 0; y < th - vsz; y += vsz + vsp )
  117.     {
  118.         for( x = 0; x < tw - hsz; x += hsz + hsp )
  119.         {
  120.             name = tostring( namefunc( ix, iy, i ) );
  121.             sprites[ name ] =
  122.             [
  123.                 hsz, vsz, 0, 0,
  124.                 x / tw, y / th, ( x + hsz ) / tw, ( y + vsz ) / th,
  125.                 x, y, x + hsz, y + vsz
  126.             ];
  127.             i++;
  128.             ix++;
  129.         }
  130.         iy++;
  131.         ix = 0;
  132.     }
  133.    
  134.     data =
  135.     {
  136.         texture = texture,
  137.         sprites = sprites,
  138.     };
  139.    
  140.     return class( data, SS_SpriteSheet );
  141. }
  142.  
  143. function SS_SpriteSheet.getSprite( name )
  144. {
  145.     return @this.sprites[ name ];
  146. }
  147.  
  148.  
  149. /*
  150.     class SS_SpriteSheetAnim
  151.    
  152.     - create()
  153.     - tick( deltaTime )
  154.     - getSheet()
  155.     - getFrame()
  156.    
  157.     - setAnim( name, spec )
  158.     - play( name, loop = true )
  159.     - stop()
  160. */
  161.  
  162. global SS_SpriteSheetAnim = {};
  163.  
  164. function SS_SpriteSheetAnim.create( sheet )
  165. {
  166.     data =
  167.     {
  168.         sheet = sheet,
  169.         anims = {},
  170.        
  171.         cur_anim = null,
  172.         cur_time = 0.0,
  173.         cur_loop = false,
  174.         cur_fid = 1,
  175.     };
  176.    
  177.     return class( data, SS_SpriteSheetAnim );
  178. }
  179.  
  180. function SS_SpriteSheetAnim.tick( deltaTime )
  181. {
  182.     if( this.cur_anim )
  183.     {
  184.         // advance time
  185.         this.cur_time += deltaTime;
  186.         if( this.cur_loop && this.cur_time >= this.cur_anim[0] )
  187.         {
  188.             this.cur_time -= this.cur_anim[0];
  189.             this.cur_fid = 1;
  190.         }
  191.        
  192.         // advance frame ID
  193.         while( this.cur_fid + 2 < this.cur_anim.size &&
  194.                this.cur_anim[ this.cur_fid + 2 ] < this.cur_time )
  195.             this.cur_fid += 2;
  196.     }
  197. }
  198.  
  199. function SS_SpriteSheetAnim.getSheet()
  200. {
  201.     return this.sheet;
  202. }
  203.  
  204. function SS_SpriteSheetAnim.getFrame()
  205. {
  206.     return if( this.cur_anim, this.cur_anim[ this.cur_fid + 1 ], null );
  207. }
  208.  
  209. function SS_SpriteSheetAnim.setAnim( name, spec )
  210. {
  211.     if( !is_array( spec ) || spec.size < 3 )
  212.         WARNING( "anim.spec must be an array with at least 3 items (length, frame 1 offset, frame 1 name)" );
  213.    
  214.     spec[ 0 ] = toreal( spec[ 0 ] );
  215.     prev = 0.0;
  216.     for( i = 1; i < spec.size; i += 2 )
  217.     {
  218.         sir = parsereal( spec[ i ] );
  219.         if( sir === null )
  220.             WARNING( "item at index " $ i $ " is not a number" );
  221.         spec[ i ] = sir;
  222.         if( spec[ i ] < prev )
  223.             WARNING( "frames are not ordered" );
  224.         prev = spec[ i ];
  225.     }
  226.     this.anims[ name ] = spec;
  227. }
  228.  
  229. function SS_SpriteSheetAnim.play( name, loop )
  230. {
  231.     if( !isset( this.anims, name ) )
  232.         WARNING( "animation '" $ name $ "' was not found" );
  233.     loop = if( loop === null, true, tobool( loop ) );
  234.    
  235.     this.cur_anim = this.anims[ name ];
  236.     this.cur_time = 0.0;
  237.     this.cur_loop = loop;
  238.     this.cur_fid = 1;
  239. }
  240.  
  241. function SS_SpriteSheetAnim.stop()
  242. {
  243.     this.cur_anim = null;
  244. }
  245.  
  246.  
  247. /*
  248.     class SS_PixelDraw
  249.    
  250.     - create()
  251.     - beginDraw()
  252.     - endDraw()
  253.     - setViewOffset( x, y )
  254.     - drawSprite( sheet, name, x, y, col = 1.0 )
  255.    
  256.     - _flush()
  257.     - _prepareState( texture )
  258.     - _updateView()
  259. */
  260.  
  261. global SS_PixelDraw = {};
  262.  
  263. function SS_PixelDraw.create( canvas )
  264. {
  265.     if( !canvas )
  266.         WARNING( "must specify canvas (object with .width/.height)" );
  267.    
  268.     data =
  269.     {
  270.         last_texture = null,
  271.         renderbuffer = SS_CreateRenderBuffer(),
  272.         vertexformat = SS_MakeVertexFormat( "pf2tf2cb4" ),
  273.         viewofs_x = 0,
  274.         viewofs_y = 0,
  275.         drawing = false,
  276.         numverts = 0,
  277.         canvas = canvas,
  278.     };
  279.    
  280.     return class( data, SS_PixelDraw );
  281. }
  282.  
  283. function SS_PixelDraw.beginDraw()
  284. {
  285.     if( this.drawing )
  286.         WARNING( "already drawing" );
  287.    
  288.     this.drawing = true;
  289.     this.renderbuffer.begin();
  290.     this.numverts = 0;
  291.     this._updateView();
  292. }
  293.  
  294. function SS_PixelDraw.endDraw()
  295. {
  296.     if( !this.drawing )
  297.         WARNING( "not drawing" );
  298.    
  299.     this._flush();
  300.     this.drawing = false;
  301. }
  302.  
  303. function SS_PixelDraw.setViewOffset( x, y )
  304. {
  305.     this.viewofs_x = toint(x);
  306.     this.viewofs_y = toint(y);
  307. }
  308.  
  309. function SS_PixelDraw.drawSprite( sheet, name, x, y, flip_x, flip_y, col )
  310. {
  311.     if( !this.drawing )
  312.         WARNING( "not drawing" );
  313.    
  314.     if( !sheet || !name )
  315.         WARNING( "sheet and name must be specified" );
  316.     spr = sheet.getSprite( name );
  317.     if( !spr )
  318.         WARNING( "sprite not found" );
  319.    
  320.     this._prepareState( sheet.texture );
  321.     rb = this.renderbuffer;
  322.    
  323.     cr = if( col, col.r, 1.0 );
  324.     cg = if( col, col.g, 1.0 );
  325.     cb = if( col, col.b, 1.0 );
  326.     ca = if( col, col.a, 1.0 );
  327.    
  328.     x -= spr[2];
  329.     y -= spr[3];
  330.     x2 = x + spr[0];
  331.     y2 = y + spr[1];
  332.     tx1 = spr[4];
  333.     ty1 = spr[5];
  334.     tx2 = spr[6];
  335.     ty2 = spr[7];
  336.     if( flip_x ){ tmp = tx1; tx1 = tx2; tx2 = tmp; }
  337.     if( flip_y ){ tmp = ty1; ty1 = ty2; ty2 = tmp; }
  338.    
  339.     rb.f( x, y, tx1, ty1 ).cf2b( cr, cg, cb, ca );
  340.     rb.f( x2, y, tx2, ty1 ).cf2b( cr, cg, cb, ca );
  341.     rb.f( x2, y2, tx2, ty2 ).cf2b( cr, cg, cb, ca );
  342.    
  343.     rb.f( x2, y2, tx2, ty2 ).cf2b( cr, cg, cb, ca );
  344.     rb.f( x, y2, tx1, ty2 ).cf2b( cr, cg, cb, ca );
  345.     rb.f( x, y, tx1, ty1 ).cf2b( cr, cg, cb, ca );
  346.    
  347.     this.numverts += 6;
  348. }
  349.  
  350. function SS_PixelDraw._flush()
  351. {
  352.     this.renderbuffer.draw( this.last_texture, this.vertexformat, 0, this.numverts, SS_PT_TRIANGLES );
  353.     this.renderbuffer.begin();
  354.     this.numverts = 0;
  355. }
  356.  
  357. function SS_PixelDraw._prepareState( texture )
  358. {
  359.     if( this.last_texture != texture )
  360.     {
  361.         this._flush();
  362.         this.last_texture = texture;
  363.     }
  364. }
  365.  
  366. function SS_PixelDraw._updateView()
  367. {
  368.     x = this.viewofs_x;
  369.     y = this.viewofs_y;
  370.     SS_SetCameraUI( x, x + this.canvas.width, y, y + this.canvas.height );
  371. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement