用C語言開發NES遊戲(CC65)08、背景 碰撞

背景和精靈有些區別,我們無法讀取PPU中的字節。

我們先搞個地圖,每個塊大小是 16x16,填充整個背景需要 240字節的數組。X從0-15,Y從0-14。我們把數組放到RAM中,以防止被修改。

後面演示運行情況,先看下數組結構。

 

 


 

 

const unsigned char c2 [] = {

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,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,0,1,0,0,1,0,0,0,0,0,0,0,

0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,

0,0,0,0,0,1,0,0,1,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,1,0,0,0,0,0,0,1,0,0,0,0,0,

0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,

0,0,0,0,0,1,1,1,1,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,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,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,0,0,0,0,0,0,0,0,0

};

 

 

 

1表示遊戲中的塊

 

 

要檢測碰撞,你只需要將X和Y的低字節去掉,然後拼到一起,後面解釋方法

X>>4 將X向右挪4位,Y & 0xF0 將Y的低4位變成0,用他和數組中的值逐個對比,1碰撞,0沒有

 

我會檢測精靈的4個方向,並在碰撞的時候修改U D L R 4個屬性值(就是精靈的上下左右方向是否有碰撞)

我先進行X移動,檢查是否碰撞,如果碰撞了則跳,再移動Y,檢測是否碰撞,如果碰撞則跳過,也就是不執行移動的動作。具體看函數bg_collision()

 

這段代碼應該精簡,因爲每一幀都會有XY的變動,我會修改代碼實現變速。每幀1個像素太慢了,會造成很差的遊戲體驗。

 

我習慣使用 Tiled Map 製作遊戲關卡,他使用非常簡單,並且可以導出csv文件,這樣可以方便製作C的數組。但是這個工具無法導入NES格式的.chr文件,所以我不得不重做所有類型的地圖塊。這很簡單,我們只需要2個種,空白塊和普通的地圖塊。

 

我先用NES Screen Tool製作圖塊,然後繪製2x2的塊。看起來這樣的做法有點蠢,但是當你的遊戲裏有幾十種圖塊的時候,這樣做起來就會很happy了

因爲沒有辦法導出nametable的圖片,所以我截圖然後在GIMP編輯,另存爲metatile.png

以tileset的方式導入 Tiled Map地圖編輯器中。因爲nes屏幕工具會使像素加倍,所以每個圖片的尺寸都是32x32

(翻譯備註:意思就是編輯器截圖圖像比較大,不是8x8的,而是32x32的,所以纔會有上面這種情況)

編輯完關卡地圖,導出csv文件。

 

 

SV文件轉換爲C數組是件小事兒,但是我還是做了個python3的腳本來實現。我將C數組導入我的代碼,然後使用一個指針的數組指向前面的數組。

 

 


 

 

#include “CSV/c1.c”

#include “CSV/c2.c”

#include “CSV/c3.c”

#include “CSV/c4.c”

 

const unsigned char * const All_Collision_Maps[] = {c1,c2,c3,c4};

 

 

 

現在,我編寫了一些代碼,將一個2×2塊的塊打印到屏幕上,使用了一個大的循環,裏面用了vram_put()方法。

使用vram_put()前需要先關閉屏幕,寫入PPU是以從左到右,然後下一行開始從左到右。這樣你可以很簡單的就寫完整個屏幕。

 

Start按鍵可以切換下一個地圖顯示

 

當你按右的時候,X的位置會+1,然後檢測4個碰撞點,如果發生碰撞則會結束向右移動(X會-1)

(翻譯備註:作者用 座標變換後的點去檢測碰撞,發生碰撞就退回變化,如果沒有碰撞,精靈就會按照變化後的點移動--也就是重新繪製精靈新的位置)

 

測試:按方向撞牆,碰撞可以生效。按Start按鈕,背景變化,碰撞依舊有效,因爲RAM加載了一個新的地圖碰撞檢測。

 

注意:我使用屏幕滾動的方式將整個背景向下移動了1個像素。Y scroll=ff(-1),因爲精靈總是會向下移動一個像素,所以必須將背景整體下移1個像素。

 

https://github.com/nesdoug/09_BG_Collide/blob/master/collide.c

 

https://github.com/nesdoug/09_BG_Collide

 

地圖加載部分的代碼寫的不是很好,因爲只能繪製一種貼圖塊,而且屬性表不會修改,稍後我會介紹一個更好的加載方式(11、Metatiles),在此之前我先說一下滾動。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章