• <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>

            天行健 君子當(dāng)自強(qiáng)而不息

            二維圖形的使用(2)

             

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

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

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

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

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

            添加對象

            角色以及其他移動(dòng)的對象只需被作為自由浮動(dòng)的貼片來進(jìn)行繪制,而不需要為他們使用一個(gè)地圖數(shù)組。更確切的說,要根據(jù)所有的角色和對象在世界中的各自坐標(biāo)來記錄它們,然后把那些對象的坐標(biāo)轉(zhuǎn)換為它們準(zhǔn)備在屏幕上進(jìn)行繪制的坐標(biāo),也就是它們出現(xiàn)在視野里的坐標(biāo)。

            為了使事情保持簡單,設(shè)置一個(gè)結(jié)構(gòu)體來存儲對象的坐標(biāo)和貼片索引。

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

            將把每件可以自由移動(dòng)的事物認(rèn)為是一個(gè)對象,包括玩家的角色。

             

            平滑卷軸

            操作貼片引擎時(shí),大型的地圖需要卷軸以便玩家可以看到整個(gè)地圖,具體說,在繪制地圖時(shí)嘗試去改變坐標(biāo),貼片引擎就會(huì)產(chǎn)生一個(gè)急促的運(yùn)動(dòng)。為了提高引擎的視覺質(zhì)量,需要使用一種稱之為平滑卷軸(smooth scrolling)的技術(shù)來使運(yùn)動(dòng)平滑地進(jìn)行。

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

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

             

            創(chuàng)建一個(gè)地圖類

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

            #define MAX_OBJECTS 1024

            每個(gè)地圖類的實(shí)例可以存儲大量的層次(甚至超過一百萬個(gè)),將每個(gè)層次的貼片數(shù)據(jù)存儲到一個(gè)數(shù)組_map_info里。因?yàn)榈貓D的尺寸大小一旦被創(chuàng)建,將是固定不變的,可以通過計(jì)算在_map_info數(shù)組里的當(dāng)前位移,并利用一個(gè)指針對每個(gè)層次的貼片數(shù)據(jù)進(jìn)行讀取或?qū)懭搿?/p>

            來看看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;

            實(shí)現(xiàn):

            /*************************************************************************
            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;
            }

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

            來看看第一個(gè)例子:

            下載源碼和工程

            /*****************************************************************************
            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();
            }

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

             

            接著來看第二個(gè)例子:

            下載源碼和工程

            /*****************************************************************************
            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();
            }

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


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


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            公告

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關(guān)鏈接

            搜索

            最新評論

            亚洲国产精品狼友中文久久久| 亚洲AV乱码久久精品蜜桃| 国产 亚洲 欧美 另类 久久| 国产精品免费看久久久香蕉| 久久综合色区| 99久久久精品| 国产欧美久久久精品影院| 成人综合伊人五月婷久久| 97久久综合精品久久久综合| 国产女人aaa级久久久级| 久久91精品国产91| 欧美一区二区精品久久| 国产精品久久久久免费a∨| 精品久久久久久国产91| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 久久久久亚洲精品男人的天堂| 久久久国产99久久国产一| 国产精品久久久久久福利69堂| 99久久免费国产精品特黄| 国产精品青草久久久久福利99| 久久综合久久自在自线精品自| 久久久久这里只有精品| 久久国产精品99精品国产987| 日韩精品久久久久久久电影| 久久精品国产99久久丝袜| 精品久久久久久无码中文字幕| 久久久女人与动物群交毛片| 久久精品国产福利国产琪琪 | 久久ZYZ资源站无码中文动漫| 久久久久亚洲AV无码专区桃色| 免费国产99久久久香蕉| AV无码久久久久不卡网站下载| 久久久一本精品99久久精品88| 久久精品国产男包| 久久这里有精品| 久久人人爽人人人人爽AV| 思思久久好好热精品国产| 婷婷久久五月天| 日产精品久久久久久久性色| 午夜精品久久久久久99热| 久久久久AV综合网成人|