예제 #1
0
파일: Form1.cs 프로젝트: sglasby/HRAOS
    void OnShown(object sender, EventArgs ee)
    {
        // Note: Events are fired in the order (Load, Activated, Shown),
        //     It is said that using a MessageBox() can perturb the order of these events,
        //     causing Shown to occur before Load.
        //     http://stackoverflow.com/questions/3070163/order-of-form-load-form-shown-and-form-activated-events
        //     It is also said that "depending on the order of events fired" is undesirable / bad style;
        //     so perhaps once I understand what the idiomatic alternative would be,
        //     this should be changed.
        //
        // To call any GL methods (such as setting the GL Viewport, or loading textures)
        // the OpenGL system must be initialized, which occurs upon the 'Load' event
        // firing for a Form which contains a GLControl.
        //     http://www.opentk.com/doc/chapter/2/glcontrol
        //     See also, regarding OpenTK.Graphics.GraphicsContext:
        //         http://www.opentk.com/book/export/html/140
        //
        // For this reason, the GL setup, and GL texture loading (via TileSheet constructor calls)
        // code has been moved here, in a method we set up to be called upon the 'Shown' event
        // (which is fired upon the first display of this Form).

        ts = new TileSheet(16, 16, NEW_OBJID,
            @"media/tiles/U4.B_enhanced-32x32.png");

        f1234 = new TileSheet(4, 9, 32, 32, 1, 1, 1, 1, NEW_OBJID,
            @"media/tiles/example_all_facings.4_frames.intra_1.png");

        f1234_stack = new TileSheet(1, 9, 32, 32, 1, 1, 1, 1, NEW_OBJID,
            @"media/tiles/example_all_facings.stacked/example_all_facings.intra_1.frame_1.png",
            @"media/tiles/example_all_facings.stacked/example_all_facings.intra_1.frame_2.png",
            @"media/tiles/example_all_facings.stacked/example_all_facings.intra_1.frame_3.png",
            @"media/tiles/example_all_facings.stacked/example_all_facings.intra_1.frame_4.png");

        wp_ts = new TileSheet(4, 1, NEW_OBJID,
            @"media/tiles/whirlpool_bright.png");

        wp_stack_ts = new TileSheet(1, 1, NEW_OBJID,
            @"media/tiles/whirlpool.stacked/whirlpool_1.png",
            @"media/tiles/whirlpool.stacked/whirlpool_2.png",
            @"media/tiles/whirlpool.stacked/whirlpool_3.png",
            @"media/tiles/whirlpool.stacked/whirlpool_4.png");

        creatures_stack = new TileSheet(4, 7, NEW_OBJID,
            @"media/tiles/creatures.stacked/creatures.frame_1.png",
            @"media/tiles/creatures.stacked/creatures.frame_2.png",
            @"media/tiles/creatures.stacked/creatures.frame_3.png",
            @"media/tiles/creatures.stacked/creatures.frame_4.png");

        //string[] empty_file_names_list = { };
        //TileSheet null_filenames_ts       = new TileSheet(4, 4, NEW_OBJID, null                 );  // Will throw an exception
        //TileSheet empty_filenames_list_ts = new TileSheet(4, 4, NEW_OBJID, empty_file_names_list);  // Will throw an exception

        TileSprite anim_blue_wiz = new TileSprite(ts, NEW_OBJID, 32, 33);
        TileSprite anim_red_wiz  = new TileSprite(ts, NEW_OBJID, 224, 225, 226, 227);

        // Counters for 3 frames (A,B,C) and for 4 frames (1,2,3,4)
        // This illustrates why the master frame cycle need be the Least Common Multiple of (3,4)
        // (or whatever other set of ITileSprite.num_frames values).
        TileSprite count_ABC     = new TileSprite(ts, NEW_OBJID, 96, 97, 98);  //ts[0, 6], ts[1, 6], ts[2, 6]);
        TileSprite count_1234    = new TileSprite(f1234_stack, NEW_OBJID, 0, 9 + 0, 18 + 0, 27 + 0);  // Same as count_1234, but frames from 4 files

        // TileSprite whirlpool = new TileSprite(wp_ts, NEW_OBJID, 0, 1, 2, 3);
        TileSprite whirlpool = new TileSprite(wp_stack_ts, NEW_OBJID, 0, 1, 2, 3);  // Save as from wp_ts, but using 4 image files in a stack

        TileSprite bat       = new TileSprite(creatures_stack, NEW_OBJID, (0 * 28) + 1, (1 * 28) + 1, (2 * 28) + 1, (3 * 28) + 1);
        TileSprite skel_mage = new TileSprite(creatures_stack, NEW_OBJID, (0 * 28) + 21, (1 * 28) + 21, (2 * 28) + 21, (3 * 28) + 21);

        LF = new TileSheet(8, 1, NEW_OBJID,
            @"media/tiles/lava.wave_down.speed_4.frames_8.png");  // LF == LavaFlow
        TileSprite lava_flow = new TileSprite(LF, NEW_OBJID, 0, 1, 2, 3, 4, 5, 6, 7);

        // TODO: Support some manner of ITileSprite for "wave" sprites
        // TileSheet TW = new TileSheet(1, 9, NEW_OBJID, @"media/tiles/example_wave_test.intra_1.png");  // Will need WaveTileSprite to support this...

        TileSprite grass   = new TileSprite(ts, NEW_OBJID, 4);
        TileSprite trees   = new TileSprite(ts, NEW_OBJID, 6);
        TileSprite boulder = new TileSprite(ts, NEW_OBJID, 57);
        int[] path_rect_5x4 = new int[]
            { // 5 = grass, 7 = trees, 58 = boulder
               boulder.ID, grass.ID, grass.ID, trees.ID, grass.ID,
               grass.ID,   grass.ID, grass.ID, trees.ID, trees.ID,
               trees.ID,   trees.ID, trees.ID, trees.ID, 0,         // 0 is a "hole in the map" for blitting / map composition purposes
               grass.ID,   grass.ID, trees.ID, grass.ID, grass.ID,
            };

        DenseGrid map_16x64 = new DenseGrid(16, 64, lava_flow.ID);

        // Blit a non-square grid onto the map, demonstrating the various possible rotations and flips:
        DenseGrid flip_none = new DenseGrid(5, 4, path_rect_5x4);
        DenseGrid flip_we   = flip_none.Flip_WE();
        DenseGrid flip_ns   = flip_none.Flip_NS();
        DenseGrid flip_wens = flip_we.Flip_NS();

        DenseGrid.BlitFromAOntoB(flip_none, map_16x64, 1, 1);
        DenseGrid.BlitFromAOntoB(flip_we, map_16x64, 7, 1);
        DenseGrid.BlitFromAOntoB(flip_ns, map_16x64, 1, 7);
        DenseGrid.BlitFromAOntoB(flip_wens, map_16x64, 7, 7);

        DenseGrid flip_none_rot090 = flip_none.Rotate090();
        DenseGrid flip_we_rot090   = flip_we.Rotate090();
        DenseGrid flip_ns_rot090   = flip_ns.Rotate090();
        DenseGrid flip_wens_rot090 = flip_wens.Rotate090();

        DenseGrid.BlitFromAOntoB(flip_none_rot090, map_16x64, 1, 52);
        DenseGrid.BlitFromAOntoB(flip_we_rot090, map_16x64, 7, 52);
        DenseGrid.BlitFromAOntoB(flip_ns_rot090, map_16x64, 1, 58);
        DenseGrid.BlitFromAOntoB(flip_wens_rot090, map_16x64, 7, 58);

        map = new SimpleMapV1(16, 64);
        map.AddTerrainRegion(map_16x64, 0, 0);

        tvpc.scroll_constraint = ScrollConstraint.CenterTile;
        tvpc.set_center(map, 2, 2);

        // Add some elements to the Beings layer of the Map:
        // BUG: (in demo data)
        // The below are bare integers which do not correspond
        // to a constructed TileSprite; those display wrongly (confusion between object ID and OpenGL texture ID or somesuch?)
        // The fix is merely to create TileSprite objects and use their .ID
        // (This fossil is due to the TileSheet + TileSprite refactor;
        //  the sprites are no longer implicitly created and stored within the TileSheet)

        /*
        map.layers[MapLayers.Beings].set_contents_at_XY( 8,  7, 256+21);  // Horse
        map.layers[MapLayers.Beings].set_contents_at_XY( 4, 15, 256+21);  // Horse
        map.layers[MapLayers.Beings].set_contents_at_XY( 8, 20, 33);  // Wizard
        map.layers[MapLayers.Beings].set_contents_at_XY( 3, 25, 70);  // Force field
        map.layers[MapLayers.Beings].set_contents_at_XY(10, 30, 29);  // Stair down
        map.layers[MapLayers.Beings].set_contents_at_XY( 9, 35, 30);  // Ruin
        map.layers[MapLayers.Beings].set_contents_at_XY( 6, 40, 45);  // Archer
        map.layers[MapLayers.Beings].set_contents_at_XY(12, 45, 23);  // Purple tiles
        map.layers[MapLayers.Beings].set_contents_at_XY( 5, 50, 19);  // Ship
        */

        map.layers[MapLayers.Beings].set_contents_at_XY(2, 1, anim_blue_wiz.ID);  // Blue Wizard, animated (2 frames)
        map.layers[MapLayers.Beings].set_contents_at_XY(3, 3, anim_red_wiz.ID);   // Red  Wizard, animated (4 frames)

        map.layers[MapLayers.Beings].set_contents_at_XY(4, 1, count_ABC.ID);   // 3 frames (A,B,C)
        map.layers[MapLayers.Beings].set_contents_at_XY(5, 1, count_1234.ID);  // 4 frames (1,2,3,4)

        map.layers[MapLayers.Beings].set_contents_at_XY(6, 6, bat.ID);
        map.layers[MapLayers.Beings].set_contents_at_XY(4, 7, skel_mage.ID);

        map.layers[MapLayers.Beings].set_contents_at_XY(0, 0, whirlpool.ID);

        // Add some elements to the UI_elements layer of the TileViewPort:

        // Over-sized cursor
        // Drawback: outside of tile bounds
        // is off-viewport for edge-of-viewport sides of cursor on edge-of-viewport tiles.
        // Also, the "quanta" animation rate for the cursor blinking is too fast, as in "pokemon epilepsy warning" too-fast.
        // (Blinking at "frame" rate seems OK...may want a modestly faster rate.)
        //
        // This cursor _does_ look a lot better, other than for edge-of-viewport tiles.
        // One possible solution to that issue would be for the "rest" state of the viewport
        // to have an n-pixel border along all edges, showing partial tiles.
        // Will need to coordinate all this with smooth-scrolling, too...
        ts_cursor_blink_40x40 = new TileSheet(1, 1, 40, 40, 0, 0, 0, 0, NEW_OBJID,
            @"media/cursors/cursor_40x40_blink.stacked/cursor_40x40.frame_1.png",
            @"media/cursors/cursor_40x40_blink.stacked/cursor_40x40.frame_2.png");
        TileSprite large_cursor = new TileSprite(ts_cursor_blink_40x40, NEW_OBJID, 0, 1);
        int LC = large_cursor.ID;

        tvpc.layers[ViewPortLayers.UI_Elements].set_contents_at_XY(tvpc.center_x, tvpc.center_y, LC);  // Center
        tvpc.layers[ViewPortLayers.UI_Elements].set_contents_at_XY(0, 0, LC);  // NW
        tvpc.layers[ViewPortLayers.UI_Elements].set_contents_at_XY(tvpc.max_x, 0, LC);  // NE
        tvpc.layers[ViewPortLayers.UI_Elements].set_contents_at_XY(0, tvpc.max_y, LC);  // SW
        tvpc.layers[ViewPortLayers.UI_Elements].set_contents_at_XY(tvpc.max_x, tvpc.max_y, LC);  // SE

        // // "Marquee" cursor
        // // Drawback: cursor itself is entirely within tile bounds, thus clips edge pixels of the under-cursor tile...
        // //
        //reticle_single_file_ts = new TileSheet(4, 1, NEW_OBJID, @"media/tiles/bright_marquee.frame_1234.png");
        reticle_four_files_ts = new TileSheet(4, 4, NEW_OBJID,
                        @"media/tiles/bright_marquee.frame_1.png",
                        @"media/tiles/bright_marquee.frame_2.png",
                        @"media/tiles/bright_marquee.frame_3.png",
                        @"media/tiles/bright_marquee.frame_4.png");  // Also used in Form1.OnPaint()
        //TileSprite anim_reticle = new TileSprite(reticle_four_files_ts, 15, 31, 47, 63);  // Bottom right tile in each image file
        //int reticle = anim_reticle.ID;
        //tvpc.layers[ViewPortLayers.UI_Elements].set_contents_at_XY(tvpc.center_x, tvpc.center_y, reticle);  // Center
        //tvpc.layers[ViewPortLayers.UI_Elements].set_contents_at_XY(0,             0,             reticle);  // NW
        //tvpc.layers[ViewPortLayers.UI_Elements].set_contents_at_XY(tvpc.max_x,    0,             reticle);  // NE
        //tvpc.layers[ViewPortLayers.UI_Elements].set_contents_at_XY(0,             tvpc.max_y,    reticle);  // SW
        //tvpc.layers[ViewPortLayers.UI_Elements].set_contents_at_XY(tvpc.max_x,    tvpc.max_y,    reticle);  // SE

        // A few method calls to demonstrate that Archetype and Obj are working:
        Archetype aa = new Archetype("first_test_archetype", 0);
        aa.add_field("int_2a",     FieldType.INT);
        aa.add_field("string_2a",  FieldType.STRING);
        aa.add_field("decimal_2a", FieldType.DECIMAL);
        aa.add_field("ID_2a",      FieldType.ID);

        aa.add_field("int_list",     FieldType.LIST_INT);
        aa.add_field("string_list",  FieldType.LIST_STRING);
        aa.add_field("decimal_list", FieldType.LIST_DECIMAL);
        aa.add_field("ID_list",      FieldType.LIST_ID);

        Obj obj1 = new Obj(aa, "first_test_obj", 0);

        stdout.print("archetype.serialize()\n");
        stdout.print("{0}",   aa.serialize() );
        stdout.print("\n");

        stdout.print("obj.serialize()\n");
        stdout.print("{0}", obj1.serialize() );
        stdout.print("\n");
    }