Пример #1
0
    public bool set_origin(SimpleMapV1 map_arg, int map_xx, int map_yy)
    {
        // Set the map and the origin coordinates of the viewport
        // such that the viewport origin (top-left tile, for square grid)
        // is the tile with the specified coordinates.

        if (map_arg == null) {
            this.map      = null;
            this.x_origin = 0;
            this.y_origin = 0;
            return false;
            //throw new ArgumentException("Got null map_arg");
        }
        int xx = Utility.clamp(0, map_arg.width,  map_xx);
        int yy = Utility.clamp(0, map_arg.height, map_yy);

        this.map = map_arg;
        this.x_origin = xx;
        this.y_origin = yy;
        allocate_layers();

        // The resulting coordinates may differ from those specified by args,
        // either due to out-of-map-bounds coordinates which were clamp()ed,
        // or due to the scroll_constraint.
        // If so, return false, so that our caller (if it cares) can distinguish.
        if ((map_xx != xx) || (map_yy != yy)) { return false; }
        return true;  // The specified coordinates were set, without adjustment
    }
Пример #2
0
    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");
    }
Пример #3
0
    public bool set_center(SimpleMapV1 map_arg, int map_xx, int map_yy)
    {
        // Set the map and origin such that the center tile
        // of the viewport is the tile with the specified coordinates,
        // or as close as can be managed, given scrolling constraints.
        if (map_arg == null) { throw new ArgumentException("Got null map_arg"); }

        int xx = Utility.clamp(0, map_arg.width,  map_xx);
        int yy = Utility.clamp(0, map_arg.height, map_yy);

        this.map      = map_arg;
        this.x_origin = xx - center_x;
        this.y_origin = yy - center_y;
        allocate_layers();

        // The resulting coordinates may differ from those specified by args,
        // either due to out-of-map-bounds coordinates which were clamp()ed,
        // or due to the scroll_constraint.
        // If so, return false, so that our caller (if it cares) can distinguish.
        if (this.x_origin != map_xx - center_x) { return false; }
        if (this.y_origin != map_yy - center_y) { return false; }
        return true;  // The specified coordinates were set, without adjustment
    }
Пример #4
0
        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(@"Main/U4.B_enhanced-32x32.png", 16, 16);  // causes GL textures to be loaded, needs some GL setup prior...
            f1234 = new TileSheet(@"Main/example_all_facings.4_frames.intra_1.png", 4, 9, 32, 32, 1, 1, 1, 1);
            ui_ts = new TileSheet(@"Main/bright_marquee.frame_1.png", 4, 4);  // Sprite ID 272 is the reticle
            //ui_ts = new TileSheet(@"Main/bright_marquee.frame_1.alpha.png", 4, 4);  // Hmmm...not quite right...
            //ui_ts = new TileSheet(@"Main/bright_marquee.frame_1.alpha.2.png", 4, 4);  // Hmmm...not quite right...
            wp_ts = new TileSheet(@"Main/whirlpool_bright.png", 4, 1);

            // TODO:
            // After setting up all these AnimTileSprite instances, the utility is clear for
            // various constructor overloads which infer the wanted StaticTileSprite IDs...
            AnimTileSprite anim_blue_wiz = new AnimTileSprite(ts, ts[32], ts[33]);
            AnimTileSprite anim_red_wiz  = new AnimTileSprite(ts, ts[0, 14], ts[1, 14], ts[2, 14], ts[3, 14]);

            // 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).
            AnimTileSprite count_ABC     = new AnimTileSprite(ts, ts[0, 6], ts[1, 6], ts[2, 6]);
            AnimTileSprite count_1234    = new AnimTileSprite(f1234, f1234[0, 0], f1234[1, 0], f1234[2, 0], f1234[3, 0]);

            AnimTileSprite whirlpool = new AnimTileSprite(wp_ts, wp_ts[0], wp_ts[1], wp_ts[2], wp_ts[3]);

            LF = new TileSheet(@"Main/lava.wave_down.speed_4.frames_8.png", 8, 1);  // LF == LavaFlow
            AnimTileSprite lava_flow = new AnimTileSprite(LF, LF[0], LF[1], LF[2], LF[3], LF[4], LF[5], LF[6], LF[7]);

            // TileSheet TW = new TileSheet(@"Main/example_wave_test.intra_1.png", 1, 9);  // Will need WaveTileSprite to support this...

            int[] path_rect_5x4 = new int[]
            { // 5 = grass, 7 = trees, 58 = boulder
               58,  5,  5,  7,  5,
                5,  5,  5,  7,  7,
                7,  7,  7,  7,  0,
                5,  5,  7,  5,  5,
            };

            int lava_ID = ts[12, 4].ID;  // Lava
            //DenseGrid map_16x64 = new DenseGrid(16, 64, lava_ID);  // StaticTileSprite lava
            DenseGrid map_16x64 = new DenseGrid(16, 64, lava_flow.ID);  // AnimTileSprite flowing lava

            DenseGrid flip_none = new DenseGrid(5, 4, path_rect_5x4);  // Test with width != height, the better to see the rotations and flips
            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, ts);
            map.AddTerrainRegion(map_16x64, 0, 0);

            //tvp = new TileViewPort(this.tvp_control,
            //    15, 15,
            //    //ViewPortScrollingConstraint.EntireMap,
            //    ScrollConstraint.CenterTile,
            //    //ViewPortScrollingConstraint.EdgeCorner,
            //    map, 0, 0);
            tvpc.scroll_constraint = ScrollConstraint.CenterTile;
            tvpc.set_center(map, 2, 2);

            // Add some elements to the Beings layer of the Map:  // TODO: Still using hard-coded Sprite ID values here...
            map.layers[MapLayers.Beings].set_contents_at_XY( 8,  7, 21);  // Horse

            map.layers[MapLayers.Beings].set_contents_at_XY( 8,  7, 21);  // Horse
            map.layers[MapLayers.Beings].set_contents_at_XY( 4, 15, 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(0, 0, whirlpool.ID);

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

            int reticle = ui_ts[3, 3].ID;  // avoiding hard-coding Sprite ID 272
            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
        }