puzzle.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:19k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * puzzle.c : Puzzle game
  3.  *****************************************************************************
  4.  * Copyright (C) 2005-2006 the VideoLAN team
  5.  * $Id: a9520c47709783eb1d5779463237b1b1ab167487 $
  6.  *
  7.  * Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <vlc_plugin.h>
  31. #include <vlc_vout.h>
  32. #include <math.h>
  33. #include "filter_common.h"
  34. #include "vlc_image.h"
  35. #include "vlc_input.h"
  36. #include "vlc_playlist.h"
  37. /*****************************************************************************
  38.  * Local prototypes
  39.  *****************************************************************************/
  40. static int  Create    ( vlc_object_t * );
  41. static void Destroy   ( vlc_object_t * );
  42. static int  Init      ( vout_thread_t * );
  43. static void End       ( vout_thread_t * );
  44. static void Render    ( vout_thread_t *, picture_t * );
  45. static int  MouseEvent   ( vlc_object_t *, char const *,
  46.                            vlc_value_t, vlc_value_t, void * );
  47. static int PuzzleCallback( vlc_object_t *, char const *,
  48.                            vlc_value_t, vlc_value_t, void * );
  49. /*****************************************************************************
  50.  * Module descriptor
  51.  *****************************************************************************/
  52. #define ROWS_TEXT N_("Number of puzzle rows")
  53. #define ROWS_LONGTEXT N_("Number of puzzle rows")
  54. #define COLS_TEXT N_("Number of puzzle columns")
  55. #define COLS_LONGTEXT N_("Number of puzzle columns")
  56. #define BLACKSLOT_TEXT N_("Make one tile a black slot")
  57. #define BLACKSLOT_LONGTEXT N_("Make one slot black. Other tiles can only be swapped with the black slot.")
  58. #define CFG_PREFIX "puzzle-"
  59. vlc_module_begin ()
  60.     set_description( N_("Puzzle interactive game video filter") )
  61.     set_shortname( N_( "Puzzle" ))
  62.     set_capability( "video filter", 0 )
  63.     set_category( CAT_VIDEO )
  64.     set_subcategory( SUBCAT_VIDEO_VFILTER )
  65.     add_integer_with_range( CFG_PREFIX "rows", 4, 1, 128, NULL,
  66.                             ROWS_TEXT, ROWS_LONGTEXT, false )
  67.     add_integer_with_range( CFG_PREFIX "cols", 4, 1, 128, NULL,
  68.                             COLS_TEXT, COLS_LONGTEXT, false )
  69.     add_bool( CFG_PREFIX "black-slot", 0, NULL,
  70.               BLACKSLOT_TEXT, BLACKSLOT_LONGTEXT, false )
  71.     set_callbacks( Create, Destroy )
  72. vlc_module_end ()
  73. static const char *const ppsz_filter_options[] = {
  74.     "rows", "cols", "black-slot", NULL
  75. };
  76. /*****************************************************************************
  77.  * vout_sys_t: Magnify video output method descriptor
  78.  *****************************************************************************/
  79. struct vout_sys_t
  80. {
  81.     vout_thread_t *p_vout;
  82.     image_handler_t *p_image;
  83.     int i_cols;
  84.     int i_rows;
  85.     int *pi_order;
  86.     int i_selected;
  87.     bool b_finished;
  88.     bool b_blackslot;
  89. };
  90. /*****************************************************************************
  91.  * Control: control facility for the vout (forwards to child vout)
  92.  *****************************************************************************/
  93. static int Control( vout_thread_t *p_vout, int i_query, va_list args )
  94. {
  95.     return vout_vaControl( p_vout->p_sys->p_vout, i_query, args );
  96. }
  97. /*****************************************************************************
  98.  * Misc stuff...
  99.  *****************************************************************************/
  100. static bool finished( vout_sys_t *p_sys )
  101. {
  102.     int i;
  103.     for( i = 0; i < p_sys->i_cols * p_sys->i_rows; i++ )
  104.     {
  105.         if( i != p_sys->pi_order[i] ) return false;
  106.     }
  107.     return true;
  108. }
  109. static bool is_valid( vout_sys_t *p_sys )
  110. {
  111.     int i, j, d=0;
  112.     if( p_sys->b_blackslot == false ) return true;
  113.     for( i = 0; i < p_sys->i_cols * p_sys->i_rows; i++ )
  114.     {
  115.         if( p_sys->pi_order[i] == p_sys->i_cols * p_sys->i_rows - 1 )
  116.         {
  117.             d += i / p_sys->i_cols + 1;
  118.             continue;
  119.         }
  120.         for( j = i+1; j < p_sys->i_cols * p_sys->i_rows; j++ )
  121.         {
  122.             if( p_sys->pi_order[j] == p_sys->i_cols * p_sys->i_rows - 1 )
  123.                 continue;
  124.             if( p_sys->pi_order[i] > p_sys->pi_order[j] ) d++;
  125.         }
  126.     }
  127.     if( d%2!=0 ) return false;
  128.     else return true;
  129. }
  130. static void shuffle( vout_sys_t *p_sys )
  131. {
  132.     int i, c;
  133.     free( p_sys->pi_order );
  134.     p_sys->pi_order = malloc( p_sys->i_cols * p_sys->i_rows * sizeof( int ) );
  135.     do
  136.     {
  137.         for( i = 0; i < p_sys->i_cols * p_sys->i_rows; i++ )
  138.         {
  139.             p_sys->pi_order[i] = -1;
  140.         }
  141.         i = 0;
  142.         for( c = 0; c < p_sys->i_cols * p_sys->i_rows; )
  143.         {
  144.             i = rand()%( p_sys->i_cols * p_sys->i_rows );
  145.             if( p_sys->pi_order[i] == -1 )
  146.             {
  147.                 p_sys->pi_order[i] = c;
  148.                 c++;
  149.             }
  150.         }
  151.         p_sys->b_finished = finished( p_sys );
  152.     } while(    p_sys->b_finished == true
  153.              || is_valid( p_sys ) == false );
  154.     if( p_sys->b_blackslot == true )
  155.     {
  156.         for( i = 0; i < p_sys->i_cols * p_sys->i_rows; i++ )
  157.         {
  158.             if( p_sys->pi_order[i] ==
  159.                 p_sys->i_cols * p_sys->i_rows - 1 )
  160.             {
  161.                 p_sys->i_selected = i;
  162.                 break;
  163.             }
  164.         }
  165.     }
  166.     else
  167.     {
  168.         p_sys->i_selected = -1;
  169.     }
  170. }
  171. /*****************************************************************************
  172.  * Create: allocates Magnify video thread output method
  173.  *****************************************************************************/
  174. static int Create( vlc_object_t *p_this )
  175. {
  176.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  177.     /* Allocate structure */
  178.     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
  179.     if( p_vout->p_sys == NULL )
  180.         return VLC_ENOMEM;
  181.     p_vout->p_sys->p_image = image_HandlerCreate( p_vout );
  182.     config_ChainParse( p_vout, CFG_PREFIX, ppsz_filter_options,
  183.                        p_vout->p_cfg );
  184.     p_vout->p_sys->i_rows =
  185.         var_CreateGetIntegerCommand( p_vout, CFG_PREFIX "rows" );
  186.     p_vout->p_sys->i_cols =
  187.         var_CreateGetIntegerCommand( p_vout, CFG_PREFIX "cols" );
  188.     p_vout->p_sys->b_blackslot =
  189.         var_CreateGetBoolCommand( p_vout, CFG_PREFIX "black-slot" );
  190.     var_AddCallback( p_vout, CFG_PREFIX "rows",
  191.                      PuzzleCallback, p_vout->p_sys );
  192.     var_AddCallback( p_vout, CFG_PREFIX "cols",
  193.                      PuzzleCallback, p_vout->p_sys );
  194.     var_AddCallback( p_vout, CFG_PREFIX "black-slot",
  195.                      PuzzleCallback, p_vout->p_sys );
  196.     p_vout->p_sys->pi_order = NULL;
  197.     shuffle( p_vout->p_sys );
  198.     p_vout->pf_init = Init;
  199.     p_vout->pf_end = End;
  200.     p_vout->pf_manage = NULL;
  201.     p_vout->pf_render = Render;
  202.     p_vout->pf_display = NULL;
  203.     p_vout->pf_control = Control;
  204.     return VLC_SUCCESS;
  205. }
  206. /*****************************************************************************
  207.  * Init: initialize Magnify video thread output method
  208.  *****************************************************************************/
  209. static int Init( vout_thread_t *p_vout )
  210. {
  211.     video_format_t fmt;
  212.     memset( &fmt, 0, sizeof( video_format_t ) );
  213.     I_OUTPUTPICTURES = 0;
  214.     /* Initialize the output structure */
  215.     p_vout->output.i_chroma = p_vout->render.i_chroma;
  216.     p_vout->output.i_width  = p_vout->render.i_width;
  217.     p_vout->output.i_height = p_vout->render.i_height;
  218.     p_vout->output.i_aspect = p_vout->render.i_aspect;
  219.     p_vout->fmt_out = p_vout->fmt_in;
  220.     fmt = p_vout->fmt_out;
  221.     /* Try to open the real video output */
  222.     msg_Dbg( p_vout, "spawning the real video output" );
  223.     p_vout->p_sys->p_vout = vout_Create( p_vout, &fmt );
  224.     /* Everything failed */
  225.     if( p_vout->p_sys->p_vout == NULL )
  226.     {
  227.         msg_Err( p_vout, "cannot open vout, aborting" );
  228.         return VLC_EGENERIC;
  229.     }
  230.     vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
  231.     vout_filter_AddChild( p_vout, p_vout->p_sys->p_vout, MouseEvent );
  232.     return VLC_SUCCESS;
  233. }
  234. /*****************************************************************************
  235.  * End: terminate Magnify video thread output method
  236.  *****************************************************************************/
  237. static void End( vout_thread_t *p_vout )
  238. {
  239.     vout_sys_t *p_sys = p_vout->p_sys;
  240.     var_DelCallback( p_vout, CFG_PREFIX "rows",
  241.                      PuzzleCallback, p_vout->p_sys );
  242.     var_DelCallback( p_vout, CFG_PREFIX "cols",
  243.                      PuzzleCallback, p_vout->p_sys );
  244.     var_DelCallback( p_vout, CFG_PREFIX "black-slot",
  245.                      PuzzleCallback, p_vout->p_sys );
  246.     vout_filter_DelChild( p_vout, p_sys->p_vout, MouseEvent );
  247.     vout_CloseAndRelease( p_sys->p_vout );
  248.     vout_filter_ReleaseDirectBuffers( p_vout );
  249. }
  250. #define SHUFFLE_WIDTH 81
  251. #define SHUFFLE_HEIGHT 13
  252. static const char *shuffle_button[] =
  253. {
  254. ".................................................................................",
  255. "..............  ............................   ........   ......  ...............",
  256. "..............  ...........................  .........  ........  ...............",
  257. "..............  ...........................  .........  ........  ...............",
  258. "..     .......  .    .......  ....  ......     ......     ......  ........    ...",
  259. ".  .... ......   ...  ......  ....  .......  .........  ........  .......  ..  ..",
  260. ".  ...........  ....  ......  ....  .......  .........  ........  ......  ....  .",
  261. ".      .......  ....  ......  ....  .......  .........  ........  ......        .",
  262. "..      ......  ....  ......  ....  .......  .........  ........  ......  .......",
  263. "......  ......  ....  ......  ....  .......  .........  ........  ......  .......",
  264. ". ....  ......  ....  ......  ...   .......  .........  ........  .......  .... .",
  265. "..     .......  ....  .......    .  .......  .........  ........  ........     ..",
  266. "................................................................................."};
  267. /*****************************************************************************
  268.  * Destroy: destroy Magnify video thread output method
  269.  *****************************************************************************/
  270. static void Destroy( vlc_object_t *p_this )
  271. {
  272.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  273.     image_HandlerDelete( p_vout->p_sys->p_image );
  274.     free( p_vout->p_sys->pi_order );
  275.     free( p_vout->p_sys );
  276. }
  277. /*****************************************************************************
  278.  * Render: displays previously rendered output
  279.  *****************************************************************************/
  280. static void Render( vout_thread_t *p_vout, picture_t *p_pic )
  281. {
  282.     picture_t *p_outpic;
  283.     //video_format_t fmt_out;
  284.     // memset( &fmt_out, 0, sizeof(video_format_t) );
  285.     //picture_t *p_converted;
  286.     int i_plane;
  287.     int i_rows = p_vout->p_sys->i_rows;
  288.     int i_cols = p_vout->p_sys->i_cols;
  289.     /* This is a new frame. Get a structure from the video_output. */
  290.     while( ( p_outpic = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) )
  291.               == NULL )
  292.     {
  293.         if( !vlc_object_alive (p_vout) || p_vout->b_error )
  294.         {
  295.             return;
  296.         }
  297.         msleep( VOUT_OUTMEM_SLEEP );
  298.     }
  299.     p_outpic->date = p_pic->date;
  300.     for( i_plane = 0; i_plane < p_outpic->i_planes; i_plane++ )
  301.     {
  302.         plane_t *p_in = p_pic->p+i_plane;
  303.         plane_t *p_out = p_outpic->p+i_plane;
  304.         int i_pitch = p_in->i_pitch;
  305.         int i;
  306.         for( i = 0; i < i_cols * i_rows; i++ )
  307.         {
  308.             int i_col = i % i_cols;
  309.             int i_row = i / i_cols;
  310.             int i_ocol = p_vout->p_sys->pi_order[i] % i_cols;
  311.             int i_orow = p_vout->p_sys->pi_order[i] / i_cols;
  312.             int i_last_row = i_row + 1;
  313.             i_orow *= p_in->i_lines / i_rows;
  314.             i_row *= p_in->i_lines / i_rows;
  315.             i_last_row *= p_in->i_lines / i_rows;
  316.             if( p_vout->p_sys->b_blackslot == true
  317.                 && p_vout->p_sys->b_finished == false
  318.                 && i == p_vout->p_sys->i_selected )
  319.             {
  320.                 uint8_t color = ( i_plane == Y_PLANE ? 0x0 : 0x80 );
  321.                 for( ; i_row < i_last_row; i_row++, i_orow++ )
  322.                 {
  323.                     vlc_memset( p_out->p_pixels + i_row * i_pitch
  324.                                                + i_col * i_pitch / i_cols,
  325.                                color, i_pitch / i_cols );
  326.                 }
  327.             }
  328.             else
  329.             {
  330.                 for( ; i_row < i_last_row; i_row++, i_orow++ )
  331.                 {
  332.                     vlc_memcpy( p_out->p_pixels + i_row * i_pitch
  333.                                                + i_col * i_pitch / i_cols,
  334.                                p_in->p_pixels + i_orow * i_pitch
  335.                                               + i_ocol * i_pitch / i_cols,
  336.                                i_pitch / i_cols );
  337.                 }
  338.             }
  339.         }
  340.     }
  341.     if(    p_vout->p_sys->i_selected != -1
  342.         && p_vout->p_sys->b_blackslot == false )
  343.     {
  344.         plane_t *p_in = p_pic->p+Y_PLANE;
  345.         plane_t *p_out = p_outpic->p+Y_PLANE;
  346.         int i_pitch = p_in->i_pitch;
  347.         int i_col = p_vout->p_sys->i_selected % i_cols;
  348.         int i_row = p_vout->p_sys->i_selected / i_cols;
  349.         int i_last_row = i_row + 1;
  350.         i_row *= p_in->i_lines / i_rows;
  351.         i_last_row *= p_in->i_lines / i_rows;
  352.         vlc_memset( p_out->p_pixels + i_row * i_pitch
  353.                                    + i_col * i_pitch / i_cols,
  354.                    0xff, i_pitch / i_cols );
  355.         for( ; i_row < i_last_row; i_row++ )
  356.         {
  357.             p_out->p_pixels[   i_row * i_pitch
  358.                              + i_col * i_pitch / i_cols ] = 0xff;
  359.             p_out->p_pixels[ i_row * i_pitch
  360.                              + (i_col+1) * i_pitch / i_cols - 1 ] = 0xff;
  361.         }
  362.         i_row--;
  363.         vlc_memset( p_out->p_pixels + i_row * i_pitch
  364.                                    + i_col * i_pitch / i_cols,
  365.                    0xff, i_pitch / i_cols );
  366.     }
  367.     if( p_vout->p_sys->b_finished == true )
  368.     {
  369.         int i, j;
  370.         plane_t *p_out = p_outpic->p+Y_PLANE;
  371.         int i_pitch = p_out->i_pitch;
  372.         for( i = 0; i < SHUFFLE_HEIGHT; i++ )
  373.         {
  374.             for( j = 0; j < SHUFFLE_WIDTH; j++ )
  375.             {
  376.                 if( shuffle_button[i][j] == '.' )
  377.                    p_out->p_pixels[ i * i_pitch + j ] = 0xff;
  378.             }
  379.         }
  380.     }
  381.     vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
  382. }
  383. /*****************************************************************************
  384.  * MouseEvent: callback for mouse events
  385.  *****************************************************************************/
  386. static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
  387.                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
  388. {
  389.     vout_thread_t *p_vout = p_data;
  390.     VLC_UNUSED(p_this); VLC_UNUSED(oldval);
  391.     int i_x, i_y;
  392.     int i_v;
  393.     /* FIXME missing lock */
  394. #define MOUSE_DOWN    1
  395. #define MOUSE_CLICKED 2
  396. #define MOUSE_MOVE_X  4
  397. #define MOUSE_MOVE_Y  8
  398. #define MOUSE_MOVE    12
  399.     uint8_t mouse= 0;
  400.     int v_h = p_vout->output.i_height;
  401.     int v_w = p_vout->output.i_width;
  402.     int i_pos;
  403.     if( psz_var[6] == 'x' ) mouse |= MOUSE_MOVE_X;
  404.     if( psz_var[6] == 'y' ) mouse |= MOUSE_MOVE_Y;
  405.     if( psz_var[6] == 'c' ) mouse |= MOUSE_CLICKED;
  406.     i_v = var_GetInteger( p_vout->p_sys->p_vout, "mouse-button-down" );
  407.     if( i_v & 0x1 ) mouse |= MOUSE_DOWN;
  408.     i_y = var_GetInteger( p_vout->p_sys->p_vout, "mouse-y" );
  409.     i_x = var_GetInteger( p_vout->p_sys->p_vout, "mouse-x" );
  410.     if( i_y < 0 || i_x < 0 || i_y >= v_h || i_x >= v_w )
  411.         return VLC_SUCCESS;
  412.     if( mouse & MOUSE_CLICKED )
  413.     {
  414.         i_pos = p_vout->p_sys->i_cols * ( ( p_vout->p_sys->i_rows * i_y ) / v_h ) + (p_vout->p_sys->i_cols * i_x ) / v_w;
  415.         if( p_vout->p_sys->b_finished == true
  416.             && i_x < SHUFFLE_WIDTH && i_y < SHUFFLE_HEIGHT )
  417.         {
  418.             shuffle( p_vout->p_sys );
  419.         }
  420.         else if( p_vout->p_sys->i_selected == -1 )
  421.         {
  422.             p_vout->p_sys->i_selected = i_pos;
  423.         }
  424.         else if( p_vout->p_sys->i_selected == i_pos
  425.                  && p_vout->p_sys->b_blackslot == false )
  426.         {
  427.             p_vout->p_sys->i_selected = -1;
  428.         }
  429.         else if(    ( p_vout->p_sys->i_selected == i_pos + 1
  430.                       && p_vout->p_sys->i_selected%p_vout->p_sys->i_cols != 0 )
  431.                  || ( p_vout->p_sys->i_selected == i_pos - 1
  432.                       && i_pos % p_vout->p_sys->i_cols != 0 )
  433.                  || p_vout->p_sys->i_selected == i_pos + p_vout->p_sys->i_cols
  434.                  || p_vout->p_sys->i_selected == i_pos - p_vout->p_sys->i_cols )
  435.         {
  436.             int a = p_vout->p_sys->pi_order[ p_vout->p_sys->i_selected ];
  437.             p_vout->p_sys->pi_order[ p_vout->p_sys->i_selected ] =
  438.                 p_vout->p_sys->pi_order[ i_pos ];
  439.             p_vout->p_sys->pi_order[ i_pos ] = a;
  440.             if( p_vout->p_sys->b_blackslot == true )
  441.                 p_vout->p_sys->i_selected = i_pos;
  442.             else
  443.                 p_vout->p_sys->i_selected = -1;
  444.             p_vout->p_sys->b_finished = finished( p_vout->p_sys );
  445.         }
  446.     }
  447.     /* FIXME do we want to forward it or not ? */
  448.     var_Set( p_vout, psz_var, newval );
  449.     return VLC_SUCCESS;
  450. }
  451. static int PuzzleCallback( vlc_object_t *p_this, char const *psz_var,
  452.                            vlc_value_t oldval, vlc_value_t newval,
  453.                            void *p_data )
  454. {
  455.     VLC_UNUSED(p_this); VLC_UNUSED(oldval);
  456.     vout_sys_t *p_sys = (vout_sys_t *)p_data;
  457.     /* FIXME: thread safety */
  458.     if( !strcmp( psz_var, CFG_PREFIX "rows" ) )
  459.     {
  460.         p_sys->i_rows = __MAX( 1, newval.i_int );
  461.     }
  462.     else if( !strcmp( psz_var, CFG_PREFIX "cols" ) )
  463.     {
  464.         p_sys->i_cols = __MAX( 1, newval.i_int );
  465.     }
  466.     else if( !strcmp( psz_var, CFG_PREFIX "black-slot" ) )
  467.     {
  468.         p_sys->b_blackslot = newval.b_bool;
  469.     }
  470.     shuffle( p_sys );
  471.     return VLC_SUCCESS;
  472. }