中山大學 West BBS-西子灣站

『主選單』
分類佈告
分類精華
休閒聊天
個人郵件
個人設定
重新登入
『應數系組合語言(楊昌彪老師)』一般區佈告
←回列表  ↑上一篇  ↓下一篇        張貼  回應       
發信人: neverforget (墮落天使路西法)    看板:math-asm
日期: Mon Jul  7 03:54:34 1997
標題: 期末報告--小畫家


主題 : 小畫家(繪圖軟體)

學號:8424023
姓名:趙勗辰

指導教授:楊昌彪


一、主題說明﹕

    開發一類似視窗中的小畫家般的繪圖軟體。
    繪圖軟體﹐故名思意當然是用來繪製圖形的軟體。目前市面上有的繪圖軟體約可分為
    兩種﹐for視窗與for DOS的。前者大多畫面精緻、美觀﹐且功能多樣化﹐而相反的後
    者畫面則較為粗劣﹐而且各種軟體所製圖形自成一格式﹐互不相通。
    而兩者第一眼立刻能分辨的不同則在於底色﹐視窗軟體一向以白色為底﹐
    視白色為無色。而DOS的軟體則都以黑色為底﹐以黑色為無色。這差異乍看之下並不
    算什麼﹐但是當要在做出跟小畫家般的軟體時﹐卻會明顯的增加其難度。
    這點我稍後在說明。

二、事先所需知識﹕

    滑鼠控制:

      繪圖軟體的整個功能控制當然是以滑鼠為主。
      由於整個程式是不斷的在判斷滑鼠的狀態﹐並依其狀態決定目前所應執行之
      功能函式﹐所以若滑鼠功能有一點延遲﹐便會對程式產生不良影響﹐
      小則使程式出現bug﹐大則使函式功能混亂(例如鉛筆函式無法畫出平滑的線條﹐
      稍後會提到)。也就是說對滑鼠的功能函式的速度須有一定的要求﹐
      所以以組合語言來撰寫﹐以使其影響降到最低(我目前並無法完全去除)。

      首先要學會應用INT 33H為滑鼠的BIOS呼叫﹐挑出所需的功能將其撰寫成
      應用函式即可。而對於各功能的實際應用也要有所認知﹐
      在學期中的上機作業lab6中已學過一些最基本的應用﹐但是那些並不夠用
      來完成此程式﹐我須要能更靈活且更簡便的應用更多樣的功能﹐

    繪圖函式演算法﹕

      每一種繪圖的函式都牽涉到演算法。以最簡單的畫直線的函式來說﹐
      最簡單的演算法便是起點、終點求直線方程式﹐然後再依方程式逐一描點。
      然而此法的速度卻比較慢﹐不一定合乎某些軟體的須要﹐
      所以便有人會想出其它的演算法來使得此函式執行起來更為順暢。

      說到繪圖函式的演算法﹐最常為人討論的當然非多邊形塗網莫數。
      最單純直接的想法﹐用recursive判斷每一點的鄰近四點是否須塗色﹐
      想起來似乎很簡單﹐但是此法在平常的pc上卻一定會讓stack爆掉。
      所以一定得想出各種的演算法來完成此函式。

      總而言之﹐必需要對一些繪圖函式的演算法有一定的了解﹐如此才能應用自如。

    圖形檔格式﹕

      為了要使軟體看起來像視窗軟體般美觀﹐
      所以軟體中各功能的icon當然不能偷功減料﹐必須盡量能畫得漂亮點。
      但要在程式中以數字來畫出一個icon並不容易﹐於是最簡單的方法便
      是以其它軟體繪製icon圖形檔﹐然後只要將其圖形檔的資料解讀並放到
      螢幕上的正確位置即可。而要解讀圖形檔便必須對其格式有一定的了解。
      至少必需知道存放圖點資料的位址與資料壓縮的方式。

      而另一方面﹐若能完全的了解某圖形存檔的格式的話﹐
      便能自己製作此類形的圖形檔。即以其格式來存檔﹐
      於是此軟體便能與其它繪圖軟體通用。


三、一些解題技巧與成果

    在滑鼠的應用上﹐由於我要求必須有一定的速度﹐
    所以在滑鼠的函式中那些比較、跳躍、等指令盡量是能不用就不用。
    所以以前那種將好幾個功能寫在同一個函式中的方法
    (以傳入值判斷要執行何者)就不能用。所以可想而知﹐
    我必需將各功能分開撰寫函式。例如讀取滑鼠位置便為一函式﹐
    呼叫後將須要備份的暫存器值堆入stack﹐然後立刻給定ax的值3並呼叫
    int 33h中斷﹐然後把cx﹐dx中的座標值傳回。

    另外將各部功能分開寫還有一個好處是可以使在撰寫程式的利用上更為便利。每個功能都有自己的函式名稱﹐不會混亂。此次我一共用到下列的各函式﹕
    void mouse_reset(void)﹕滑鼠重置﹐ax=0。
    void mouse_on(void)﹕啟動滑鼠游標﹐ax=1。
    void mouse_off(void)﹕隱藏滑鼠游標﹐ax=2。
    void get_mouse_position(int *,int*)﹕讀取滑鼠座標﹐ax=3。
    int left_pressed(void)﹕判斷左鍵狀態﹐ax=3。
    int right_pressed(void)﹕判斷右鍵狀態﹐ax=3。
    void set_mouse_position(void)﹕設定滑鼠座標﹐ax=4
    void set_min_max_x_limit(int,int)﹕設定滑鼠移動之x軸範圍﹐ax=7。
    void set_min_max_y_limit(int,int)﹕設定滑鼠移動之y軸範圍﹐ax=8。
    void set_graphic_cursor(int,int,unsigned int far *)﹕設定繪圖模式滑鼠游標
                                                         ﹐ax=9
    void mouse_motion(char*,char*)﹕判斷滑鼠是否移動﹐ax=11﹔

    Turbo C繪圖函式﹐這次我選擇用Turbo C來撰寫程式的主體部份。
    前面提到各繪圖功能都有其演算法﹐而Turbo C本身便具有一些繪圖的函式
    供我們利用﹐如此可以減少許多不必要的麻煩﹐我們只要懂得去使用那些函式便可﹐
    而不需完全的了解其演算法。下面是我所用到的一些函式﹕
    void far putpixel(int x,int y,int color)﹔
                         在螢幕像點(x,y)的位置顯示color顏色的點。
    unsigned far getpixel(int x,int y)﹔傳回螢幕像點(x,y)的顏色值。
    void far setcolor(int color)﹔設定螢幕前景色。
    void far outtextxy(int x,int y,char far *string)﹔
                         在像點(x,y)的地方為起點輸出字串。
    void far getimage ( int left, int top, int right, int bottom,
                        void  far  *bitmap)﹔將螢幕上一區域的影像備份。
    void far putimage(int left, int top, void far *bitmap, int op)﹔
                         將先前備份的影像放回螢幕。
    void far setviewport(int left, int top, int right, int bottom, int clip)﹔
                         設定繪圖輸出視界﹐clip是控制繪圖輸出是否要剪裁。
                         設定視界後﹐Turbo C的繪圖函式所給的座標都是邏輯座標。
    void far line(int x1, int y1, int x2, int y2)﹔從(x1,y1)到(x2,y2)畫一直線。
    void far moveto(int x,int y);設定螢幕CP。
    void far lineto(int x,int y);從CP到(x,y)畫一條直線。
    void far rectangle(int left, int top, int right, int bottom);畫一個矩形。
    void far setwritemode(int mode);設定線條繪圖模式,有COPY_PUT、XOR_PUT兩種。

    然而在C++的繪圖函示中就會出現剛所提到的底色問題,當底色變為白色後,
    原本的XOR_PUT模式來繪圖時就會產生畫不出來的狀況,
    使得在產生必須隨時清除的圖形時(例如矩型功能的游標)就出現問題,
    而解決的方法便是在繪製圖行前先將前景色以setcolor來設定為其補色,
    如此一來便可成功的繪製圖形,但相對的它也占去了不少的時間。


四、 主要函式的功能與流程

    main();主程式;程式開始執行便設定所有須用到的函式的初值
      (例:前景背景色、功能選項---------),重設滑鼠與配置所須記憶體等。
      接下來便為程式的主要迴路,程式到結束前都在此迴圈中打轉。
      此迴圈為while迴圈,判斷quit變數值為零(否)則繼續執行此迴圈,
      而迴圈內容為讀取滑鼠位置後判斷其處於功能選項的位置或圖形編輯區的位置,
      若處於前者,則再判斷處於改變顏色的位置或改變功能的位置,
      前者進入change_color()函式,後者進入change_function()函式;
      若處於繪圖編輯區則衣現在所選取的功能進入相對應的函式
      (例如鉛筆功能便進入pen()函式)。

    change_color();判斷mouse左右鍵是否壓下,若否,結束函式;
      否則便判斷mouse位置改變記錄前景或背景色的值 並以setcolor()設定前景色值。
      並在畫面中表示目前所選取的顏色的地方將之表示出來。

    change_function();判斷mouse_left()的值若為假,則結束。
      不然則分兩部份,一為若mouse的位置為改變在繪圖編輯區工作的功能時,
      首先先改變原本的icon圖形的顏色為原來的顏色,
      再改變目前選取的icon圖形顏色為反白,並將目前圖形編輯區記錄下來
      (供undo功能使用),然後再改變記錄目前功能的變數。
      若mouse的位置在其餘直接執行的功能上時,先一樣改變icon的顏色,
      然後呼叫其相對應函式,再改回icon的顏色。

    frag();噴槍功能函式;while迴圈判斷mouse是否在繪圖視界中,
      若否,便結束函式。判斷是否壓下左鍵,若是,
      則以亂數產生器取兩變數為目前座標的偏差值繪點。

    pen();鉛筆;同上,若mouse離開繪圖視界便離開函式。
      若left_pressed()為真則設定營幕CP為mouse目前座標(moveto(x,y)),
      在左鍵未被放開的情形下,一旦偵測出mouse移動則讀取新座標,
      以lineto(x,y)連接CP至目前座標,並設定新的CP。

    line();連續直線;同上,若mouse離開繪圖視界便離開函式。
      若left_pressed()為真則開始繪制直線。首先以目前座標為CP,
      若mouse移動,則以XOR_PUT方式清除原本所畫的線並畫出現在位置與CP相連的線。
      若mouse左鍵再被按下,則清除前一條線後,以COPY_PUT的方式畫出直線,
      並改便CP為目前座標,繼續畫下一條線。若右鍵被壓下則結束畫線。

    poly();多邊形;同上,若mouse離開繪圖視界便離開函式。
      若left_pressed()為真便開使畫多邊形。左鍵每壓一次便依座標繪點並記錄,
      直到按下右鍵便以直線連接每一點,並把起點和終點相連。

    rect();矩形;同上,若mouse離開繪圖視界便離開函式。
      以兩變數記錄矩形的大小(與目前座標的偏差值),當左鍵按下便繪製矩形。
      若壓住右鍵移動mouse便改變上述的偏差值以改變矩形大小。

    erase();橡皮擦;同上,若mouse離開繪圖視界便離開函式。
      跟rect()幾乎相同,只有當左鍵按下時為把矩形範圍中的像點塗上底色。

    circle();圓形;同上,若mouse離開繪圖視界便離開函式。
      亦與rect()相同,不同的為只用一變數存圓形半徑,及畫圖時為畫圓形而已。

    text();文字;同上,若mouse離開繪圖視界便離開函式。
      當讀取到鍵盤有按鍵反應時,只要此鍵不為特殊鍵,
      便以outtextxy()將其輸出在座標的位置上,並改變滑鼠位置到字元末端。

    save(),load();以浮現式式窗提示要玩家輸入檔名,
      若開檔不成則顯示錯誤訊息。檔案存取方式為前前四個byte存圖形的大小,
      後面則緊接各像點的顏色值。至於BMP檔的格式雖已了解,
      但時間不足並沒有去完成它。


五、 心得:

    此程式的成品(半成品)我自己覺得是還不錯,可是實際上用到組語的部份僅有滑鼠,
    而比較稱得上低階的東西,除了滑鼠外大概也只有圖形檔的格式(??)。
    然而最後的存檔讀檔卻沒用上那格式的道理,僅有在icon的顯示上有讀取BMP檔
    的圖形來顯示而已。這是我最不滿意的地方。

    實際上此程式的主體完全是C++的語言,組語不過成為其中插花的部份
    (因為C++本身也能做)。撰寫此程式讓我充份感受到高階與低階的差異性。老實說,
    低階的東西實在是難以實行。

    這程式與我原本想像中的目標實有一段的差距,因為後來發現時間實在太緊迫了,
    逼不得已只有將能做的盡量以最簡單的方式完成(例如save,load),
    而無法將其它所知道的東西放進程式裡,大概是我最大的失敗吧。

--
    在天使美麗的羽翼下....隱藏著一顆叛逆與憂鬱的心....
    帶著無盡的憂愁與感傷....不顧一切的往自己的夢想邁進....
    這....就是我的墮落天使....
                                        路西法..



㊣ Origin: 國立中山大學 West BBS ㊣ From: 140.117.36.148


←回列表  ↑上一篇  ↓下一篇        張貼  回應