• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當自強而不息

            二維圖形的使用(2)

             

            本篇是二維圖形的使用(1)的續篇。

            從計算機游戲產生之初到現在,創建一個貼片引擎的首選方法仍然是最常用的二維圖形技術。繪制基本的貼片地圖是一個快速而輕松的過程,只需要循環那些行與列,并繪制貼片即可,所繪制的貼片總數是基于貼片的大小以及顯示率的。

            大多數基于貼片的游戲運用了多重層次(場景被堆疊起來),以便創建出一些非常酷的效果,如下圖所示:

            比如,首先繪制地面,再在地面上繪制角色,然后再繪制其他相互重疊的對象層次,就可以模擬出一個三維的場景。

            為了使用多重層次,可以申明另外不同的地圖數組(每個層次都有一個地圖數組),并使用它自己的貼片信息來填充它。從第一個層次開始,繪制包含在該層次中的每個貼片。在繪制好層次中的最后一個貼片后,移動到下一個層次繼續繪制它的貼片,直到繪制完所有的層次。

            添加對象

            角色以及其他移動的對象只需被作為自由浮動的貼片來進行繪制,而不需要為他們使用一個地圖數組。更確切的說,要根據所有的角色和對象在世界中的各自坐標來記錄它們,然后把那些對象的坐標轉換為它們準備在屏幕上進行繪制的坐標,也就是它們出現在視野里的坐標。

            為了使事情保持簡單,設置一個結構體來存儲對象的坐標和貼片索引。

            typedef struct OBJECT_INFO
            {
                
            long x_pos, y_pos;
                
            char tile_index;
            } *OBJECT_INFO_PTR;

            將把每件可以自由移動的事物認為是一個對象,包括玩家的角色。

             

            平滑卷軸

            操作貼片引擎時,大型的地圖需要卷軸以便玩家可以看到整個地圖,具體說,在繪制地圖時嘗試去改變坐標,貼片引擎就會產生一個急促的運動。為了提高引擎的視覺質量,需要使用一種稱之為平滑卷軸(smooth scrolling)的技術來使運動平滑地進行。

            為了實現平滑卷軸,將貼片繪制的地圖想象成一個很大的位圖。在位圖中的每個像素都有它自己的一對坐標,即所謂的地圖的精細坐標,代表貼片像素的每個分組被賦予它自己的地圖坐標集,如下圖所示:

            舉個例子,如果貼片是16 x 16像素大小,同時地圖數組為10 x 10,當完全渲染時,地圖將會為160 x 160像素大小(這就意味著地圖有一個分辨率為160 x 160 的精細坐標)。

             

            創建一個地圖類

            為了使游戲保持運行的平滑,首先需要對每一幀所繪制的自由浮動貼片的數量(子畫面)進行限制,一個宏定義將出色地完成這個工作,它會通知地圖類在每一幀中繪制了多少子畫面:

            #define MAX_OBJECTS 1024

            每個地圖類的實例可以存儲大量的層次(甚至超過一百萬個),將每個層次的貼片數據存儲到一個數組_map_info里。因為地圖的尺寸大小一旦被創建,將是固定不變的,可以通過計算在_map_info數組里的當前位移,并利用一個指針對每個層次的貼片數據進行讀取或寫入。

            來看看MAP類的定義:

            #define MAX_OBJECTS     1024

            typedef 
            struct OBJECT_INFO
            {
                
            long x_pos, y_pos;
                
            char tile_index;
            } *OBJECT_INFO_PTR;

            //=========================================================================================
            // This class encapsulate 2D map draw.
            //=========================================================================================
            typedef class MAP
            {
            public:
                MAP();
                ~MAP();

                
            // function to create and free a map class
                BOOL create(long num_layers, long map_column, long map_row);
                
            void free();

                
            // function to set a map's layer data
                BOOL set_map_layer_data(long layer_index, char* layer_data);

                
            // function to clear and add an object to list
                void clear_object_list();
                BOOL add_object(
            long x_pos, long y_pos, char tile_index);

                
            char* get_ptr(long layer_index);    // get pointer to map array
                long  get_map_column();             // get column of map
                long  get_map_row();                // get row of map

                // assign TILE object to use for drawing map tiles
                BOOL use_tile(TILE_PTR tile);

                
            // Render map using specified top-left map coordinates,
                // as well as number of columns and rows to draw, plus layer used to draw objects.
                BOOL render(long pos_x, long pos_y,
                            
            long num_rows, long num_columns,
                            
            long object_layer,
                            D3DCOLOR color = 0xFFFFFFFF,
                            
            float scale_x = 1.0f, float scale_y = 1.0f);

            private:
                
            long        _map_column;   // column of map
                long        _map_row;      // row of map
                long        _per_layer_size; // size of per map

                
            long        _num_layers;   // number of layers
                char*       _map_info;     // array for tile informarion
                TILE_PTR    _tile;         // pointer to TILE object

                
            long        _num_objects_to_draw;       // number of object need to be drawed
                OBJECT_INFO _objects_info[MAX_OBJECTS]; // object information array
            } *MAP_PTR;

            實現:

            /*************************************************************************
            PURPOSE:
                Implement for 2D map.
            *************************************************************************/


            #include "core_global.h"
            #include "tile.h"
            #include "map.h"

            //----------------------------------------------------------------------------------
            // Constructor, zero member data.
            //----------------------------------------------------------------------------------
            MAP::MAP()
            {
                memset(
            this, 0, sizeof(*this));
            }

            //----------------------------------------------------------------------------------
            // Destructor, release allocated resources.
            //----------------------------------------------------------------------------------
            MAP::~MAP()
            {
                free();
            }

            //----------------------------------------------------------------------------------
            // Release allocated resources.
            //----------------------------------------------------------------------------------
            void MAP::free()
            {
                
            // free map information array
                delete[] _map_info;
                _map_info = NULL;

                _map_column = _map_row = 0;
                _num_layers = 0;    
            }

            //----------------------------------------------------------------------------------
            // Create map object.
            //----------------------------------------------------------------------------------
            BOOL MAP::create(long num_layers, long map_column, long map_row)
            {
                
            // free a prior map
                free();

                
            // save number of layers, map column and row.
                _num_layers   = num_layers;
                _map_column   = map_column;
                _map_row      = map_row;
                _per_layer_size = map_column * map_row;

                
            long total_map_size = num_layers * _per_layer_size;

                
            // allocate map data memory
                if((_map_info = new char[total_map_size]) == NULL)
                    
            return FALSE;

                
            // clear it out
                ZeroMemory(_map_info, total_map_size);

                
            // reset number of objexts to draw
                _num_objects_to_draw = 0;

                
            return TRUE;
            }

            //----------------------------------------------------------------------------------
            // Set map data.
            //----------------------------------------------------------------------------------
            BOOL MAP::set_map_layer_data(long layer_index, char* layer_data)
            {
                
            // error checking
                if(layer_index >= _num_layers)
                    
            return FALSE;

                
            // copy over data
                memcpy(&_map_info[layer_index * _per_layer_size], layer_data, _per_layer_size);

                
            return TRUE;
            }

            //----------------------------------------------------------------------------------
            // Clear object list which need to be drawed.
            //----------------------------------------------------------------------------------
            void MAP::clear_object_list()
            {
                _num_objects_to_draw = 0;
            }

            //----------------------------------------------------------------------------------
            // Add object to object list.
            //----------------------------------------------------------------------------------
            BOOL MAP::add_object(long x_pos, long y_pos, char tile_index)
            {
                
            if(_num_objects_to_draw < MAX_OBJECTS)
                {
                    _objects_info[_num_objects_to_draw].x_pos      = x_pos;
                    _objects_info[_num_objects_to_draw].y_pos      = y_pos;
                    _objects_info[_num_objects_to_draw].tile_index = tile_index;

                    _num_objects_to_draw++;

                    
            return TRUE;
                }

                
            return FALSE;
            }

            //----------------------------------------------------------------------------------
            // Return pointer to specfied layer map data.
            //----------------------------------------------------------------------------------
            char* MAP::get_ptr(long layer_index)
            {
                
            if(layer_index >= _num_layers)
                    
            return NULL;

                
            return &_map_info[layer_index * _per_layer_size];
            }

            //----------------------------------------------------------------------------------
            // Return map columns.
            //----------------------------------------------------------------------------------
            long MAP::get_map_column()
            {
                
            return _map_column;
            }

            //----------------------------------------------------------------------------------
            // Return map rows.
            //----------------------------------------------------------------------------------
            long MAP::get_map_row()
            {
                
            return _map_row;
            }

            //----------------------------------------------------------------------------------
            // Set tile to map.
            //----------------------------------------------------------------------------------
            BOOL MAP::use_tile(TILE_PTR tile)
            {
                
            if((_tile = tile) == NULL)
                    
            return FALSE;

                
            return TRUE;
            }

            //----------------------------------------------------------------------------------
            // Render map.
            //----------------------------------------------------------------------------------
            BOOL MAP::render(long pos_x, long pos_y, 
                             
            long num_rows, long num_columns, 
                             
            long object_layer, 
                             D3DCOLOR color,
                             
            float scale_x, float scale_y)
            {
                
            // error checking
                if(_map_info == NULL || _tile == NULL)
                    
            return FALSE;

                
            long tile_width  = _tile->get_tile_width(0);
                
            long tile_height = _tile->get_tile_height(0);

                
            // calculate smooth scrolling variables
                long map_x = pos_x / tile_width;
                
            long map_y = pos_y / tile_height;
                
            long off_x = pos_x % tile_width;
                
            long off_y = pos_y % tile_height;    

                
            // loop through each layer
                for(long layer = 0; layer < _num_layers; layer++)
                {
                    
            // get a pointer to the map data
                    char* map_ptr = &_map_info[layer * _per_layer_size];

                    
            // loop for each row and column
                    for(long row = 0; row < num_rows+1; row++)
                    {
                        
            for(long column = 0; column < num_columns+1; column++)
                        {
                            
            // get the tile index to draw
                            char tile_index = map_ptr[(row + map_y) * _map_column + column + map_x];

                            
            long screen_x = column * tile_width  - off_x;
                            
            long screen_y = row    * tile_height - off_y;

                            
            // draw tile                
                            _tile->draw_tile(0, tile_index, (DWORD)screen_x, (DWORD)screen_y, color, scale_x, scale_y);
                        }
                    }

                    
            // draw objects if on object layer
                    if(layer == object_layer)
                    {
                        
            for(long i = 0; i < _num_objects_to_draw; i++)
                        {
                            _tile->draw_tile(0, _objects_info[i].tile_index,
                                             _objects_info[i].x_pos - off_x, _objects_info[i].y_pos - off_y,
                                             color, scale_x, scale_y);
                        }
                    }
                }

                
            return TRUE;
            }

            我們接著編寫兩個例子來測試,第一個例子演示了基本貼片技術的使用,第二個例子演示了平滑卷軸的使用。

            來看看第一個例子:

            下載源碼和工程

            /*****************************************************************************
            PURPOSE:
                Test for class TILE and MAP.
            *****************************************************************************/


            #include "Core_Global.h"
            #include "tile.h"
            #include "map.h"

            #pragma warning(disable : 4996)

            class APP : public APPLICATION
            {
            public:
                APP()
                {
                    _width  = 384;
                    _height = 384;

                    _style = WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;

                    strcpy(_class_name, "scale_tile_class");
                    strcpy(_caption, "scale tile demo");
                }

                BOOL init()
                {
                    
            // initialize the graphics device and set display mode

                    
            if(! _graphics.init())
                        
            return FALSE;

                    
            if(! _graphics.set_mode(get_hwnd()  , TRUE, FALSE))
                        
            return FALSE;

                    
            // create and load the tile set

                    
            if(! _tile.create(&_graphics, 1))
                        
            return FALSE;

                    
            if(! _tile.load_texture(0, "tiles.bmp", 64, 64))
                    {
                        err_msg_box("load texture failed.");
                        
            return FALSE;
                    }

                    
            // create and set the map

                    
            char map_data[3][3] = {
                        { 0, 1, 0 },
                        { 2, 2, 2 },
                        { 1, 2, 3 }
                    };

                    _map.create(1, 3, 3);
                    _map.set_map_layer_data(0, (
            char*) &map_data);
                    _map.use_tile(&_tile);

                    
            return TRUE;
                }

                BOOL APP::frame()
                {           
                    
            // calculate elapsed time
                    static DWORD s_last_time = timeGetTime();
                    DWORD now_time = timeGetTime();

                    DWORD elapsed_time = now_time - s_last_time;

                    
            // frame lock to 30ms per frame
                    if(elapsed_time < 30)
                        
            return TRUE;
                
                    s_last_time = now_time;         

                    
            if(_graphics.begin_scene())
                    {
                        
            if(_graphics.begin_sprite())
                        {
                            D3DCOLOR color;        

                            
            static uchar s_red = 0, s_green = 0, s_blue = 0;
                            
            static BOOL s_increment_color = TRUE;

                            
            if(s_increment_color)
                            {
                                color = D3DCOLOR_RGBA(s_red++, s_green++, s_blue++, 255);

                                
            if(s_red >= 255)         
                                    s_increment_color = FALSE;
                            }
                            
            else
                            {
                                color = D3DCOLOR_RGBA(s_red--, s_green--, s_blue--, 255);

                                
            if(s_red <= 0)
                                    s_increment_color = TRUE;
                            }

                            
            // draw the map
                            _map.render(0, 0, 3, 3, 0, color, 2.0f, 2.0f);

                            _graphics.end_sprite();
                        }

                        _graphics.end_scene();

                        _graphics.display();
                    }

                    
            return TRUE;
                }

                BOOL shutdown()
                {
                    
            return TRUE;
                }

            private:
                GRAPHICS    _graphics;
                TILE        _tile;
                MAP         _map;
            };

            int PASCAL WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
            {
              APP app;

              
            return app.run();
            }

            該程序淡入淡出地改變貼圖的顏色,截圖如下:

             

            接著來看第二個例子:

            下載源碼和工程

            /*****************************************************************************
            PURPOSE:
                Test for class TILE and MAP.
            *****************************************************************************/


            #include "Core_Global.h"
            #include "tile.h"
            #include "map.h"

            #pragma warning(disable : 4996)

            #define TILE_WIDTH      64
            #define TILE_HEIGHT     64

            #define MAP_COLUMNS     16
            #define MAP_ROWS        16

            #define TOTAL_MAP_SIZE  1024

            class APP : public APPLICATION
            {
            public:
                APP()
                {
                    _width  = 640;
                    _height = 480;

                    _num_columns_to_draw = _width / TILE_WIDTH;
                    _num_rows_to_draw    = _height / TILE_HEIGHT;

                    _max_move_width  = TOTAL_MAP_SIZE - _width;
                    _max_move_height = TOTAL_MAP_SIZE - _height;

                    _style = WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;

                    strcpy(_class_name, "map class");
                    strcpy(_caption, "map demo");
                }

                BOOL init()
                {
                    
            // initialize the graphics device and set display mode

                    
            if(! _graphics.init())
                        
            return FALSE;

                    
            if(! _graphics.set_mode(get_hwnd(), TRUE, FALSE))
                        
            return FALSE;

                    
            // create and load the tile set

                    
            if(! _tile.create(&_graphics, 1))
                        
            return FALSE;

                    
            if(! _tile.load_texture(0, "tiles.bmp", TILE_WIDTH, TILE_HEIGHT))
                    {
                        err_msg_box("load texture failed.");
                        
            return FALSE;
                    }

                    
            // create and set the map

                    
            char map_data[MAP_ROWS][MAP_COLUMNS] = {
                        { 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                        { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0 },
                        { 1, 2, 2, 1, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0 },
                        { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 0 },
                        { 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 0, 0, 0, 2, 0 },
                        { 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 },
                        { 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 },
                        { 3, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0 },
                        { 3, 0, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0 },
                        { 0, 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0 },
                        { 0, 2, 2, 1, 1, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 0 },
                        { 0, 1, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 1, 1, 2, 0 },
                        { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0 },
                        { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0 },
                        { 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
                    };

                    _map.create(1, MAP_COLUMNS, MAP_ROWS);
                    _map.set_map_layer_data(0, (
            char*) &map_data);
                    _map.use_tile(&_tile);

                    
            return TRUE;
                }

                BOOL APP::frame()
                {
                    
            static long s_x_pos = 0, s_y_pos = 0;

                    
            // calculate elapsed time
                    static DWORD s_last_time = timeGetTime();
                    DWORD now_time = timeGetTime();

                    DWORD elapsed_time = now_time - s_last_time;

                    
            // frame lock to 33ms per frame
                    if(elapsed_time < 33)
                        
            return TRUE;

                    s_last_time = now_time;

                    
            if(_graphics.begin_scene())
                    {
                        
            if(_graphics.begin_sprite())
                        {
                            
            // draw the map
                            _map.render(s_x_pos, s_y_pos, _num_rows_to_draw, _num_columns_to_draw, 0, 0xFFFFFFFF, 1.0f, 1.0f);

                            
            // press arrows to scroll map around

                            
            if(GetAsyncKeyState(VK_LEFT))   s_x_pos -= 8;
                            
            if(GetAsyncKeyState(VK_RIGHT))  s_x_pos += 8;
                            
            if(GetAsyncKeyState(VK_UP))     s_y_pos -= 8;
                            
            if(GetAsyncKeyState(VK_DOWN))   s_y_pos += 8;

                            
            // bounds check map coordinates

                            
            if(s_x_pos < 0)
                                s_x_pos = 0;

                            
            if(s_x_pos > _max_move_width)
                                s_x_pos = _max_move_width;

                            
            if(s_y_pos < 0)
                                s_y_pos = 0;
                
                            
            if(s_y_pos > _max_move_height)
                                s_y_pos = _max_move_height;

                            _graphics.end_sprite();
                        }

                        _graphics.end_scene();

                        _graphics.display();
                    }

                    
            return TRUE;
                }

                BOOL shutdown()
                {
                    
            return TRUE;
                }

            private:
                GRAPHICS    _graphics;
                TILE        _tile;
                MAP         _map;

                
            long        _num_columns_to_draw;
                
            long        _num_rows_to_draw;

                
            long        _max_move_width;
                
            long        _max_move_height;
            };

            int PASCAL WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
            {
              APP app;

              
            return app.run();
            }

            該程序展示了平滑卷軸技術的使用,用上下左右鍵進行控制,截圖如下:


            posted on 2007-10-16 01:19 lovedday 閱讀(408) 評論(0)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            久久精品不卡| 久久影院久久香蕉国产线看观看| 狠狠色丁香婷婷久久综合五月 | 蜜臀av性久久久久蜜臀aⅴ | 久久精品中文字幕久久| 国产免费福利体检区久久| 久久午夜福利无码1000合集| 2022年国产精品久久久久| 久久免费视频6| aaa级精品久久久国产片| 久久激情亚洲精品无码?V| 麻豆AV一区二区三区久久| 亚洲国产成人精品女人久久久| 久久精品国产亚洲AV无码娇色| 久久影院午夜理论片无码| 国产午夜精品久久久久免费视| yy6080久久| 色婷婷久久综合中文久久一本| 国产一区二区三区久久| 新狼窝色AV性久久久久久| 久久久国产99久久国产一| 99久久国产免费福利| 久久久中文字幕| 99国产欧美久久久精品蜜芽| 亚洲精品无码专区久久久| 久久这里有精品| 欧美国产成人久久精品| 九九热久久免费视频| 亚洲国产成人久久综合一| aaa级精品久久久国产片| 国产亚洲色婷婷久久99精品| 久久精品国产免费观看 | 怡红院日本一道日本久久| 一本久久知道综合久久| 久久人人爽人人人人片av| 亚洲日韩欧美一区久久久久我| 久久久久久无码国产精品中文字幕 | 国内精品伊人久久久久777| 久久国产欧美日韩精品| 亚洲国产精品无码久久98| 一本久久a久久精品亚洲|