LV. 7
GP 33

【攻略】【雪狼的教室!】≡=-各種彈幕製作教學-=≡【彈幕風教學結束1/11】

樓主 雪狼☇奶茶 snowshi
GP37 BP-
    
各種彈幕製作教學,輕鬆製作彈幕,製作東方夢想再也不難!

過度掙扎下,打算把這個教學文章轉載過來。
這邊名氣不是很高,於是打算先跟大家自我介紹一番後再來貼教學文。
第一時間會先更新至台灣論壇原帖,再來這裡。
目前正在GameMaker教學,但是彈幕風的教學部分還是會貼過來。


我是奶茶雪狼,目前是個青春的可愛純潔學生一枚。(別騙人了)
非常喜歡做遊戲的一個小男生,黃金單身漢(停止騙人)
話雖如此,我的遊戲都是垃圾一坨,除了最近的品質偶爾提升,其他都廢了。
緊接著的教學會滿長的(別看成學長了),但是我已經盡量簡化。
而且我也希望大家可以愉悅的上課,因此我也將我的課程幽默化了一些。(你根本不幽默的講屁)
有問題請盡量詢問,希望每個想要學習製作彈幕的人都可以圓夢!


0-彈幕工具介紹
  各位大家好,今天是雪狼第一次進行授課(屁),請各位愉快的上課吧!也歡迎提出各種問題哦。

  在上課之前我們來介紹一下製作彈幕的各種工具,各位如果覺得我更新更新的太慢也可以自己深入哦。

  第一款製作彈幕的工具應該就是這個了吧!如果有深入了解這方面的,當然會知道東方彈幕風囉。有很多很多有名的作品都是從東方彈幕風衍生出來的。

  像是,



  東方紅毛鄉!

  像是,



  東方夢終劇!

  像是,



  同性戀信仰……

  都是一些非常有名的同人作品哦。

  至於我是怎麼學會的呢?非常簡單,我用日文漢字參透一切。



  第二款大家可能就稍微沒聽過了,這是GameMaker,是我最深入的遊戲製作軟體(說深入也沒多深入根本都山寨了)。因為是圖形化介面所以作起來很簡單的喔!但是如果你想要製作彈幕可能會需要用到一點複製貼上代碼就對了啦。GameMaker由於不是彈幕專門軟體,所以在自訂系統方面會比較強一點,如果不嫌麻煩的可以先嘗試GameMaker!

  說到GM就想到我一直在關注的一個老師,這是她做的彈幕遊戲



  第三款是這個叫做《STGB》的工具,是一個非常非常簡單的彈幕製作工具喔!而且製作範圍不侷限在東方向,想要製作其他的STG遊戲都可以

  由於非常簡單而且有中文版,新手想要先製作一款遊戲自嗨這個最好。(等)

  以上是幾款彈幕製作工具,是本教室會教學的製作工具。接下來介紹林林總總的彈幕製作工具是本教室不會介紹的,因為我沒深入而且可能製作較為困難搞不好只是我懶惰。


  LuaSTG



  這是專門製作東方系列遊戲的程式: LuaSTG。建立在Lua語言基礎上的彈幕專門引擎,基本上語法較為困難,但是程式方面可跟東方彈幕風有得比。順帶一提這是網友自己寫出的製作引擎。

  BulletML

  《沒有圖片》

  是一個類似C++的彈幕製作腳本語言,但是它採用了自己的語言。基本上是建立在XML上,有興趣的可以搜尋看看。

  C++

  《沒有圖片》

  這就是傳說中神主的製作軟體了,學習比較難一點,但是其實功能非常強大。如果想要學習,網路上有非常非常多的教學哦。


  以上就是上課前的課程(咦),介紹各種彈幕製作工具。下一節課我們將要進行東方彈幕風的彈幕製作囉!各位請在下一節課以前準備以下工具:

  Notepad++
  東方彈幕風本體
  AppLocale



1-簡易彈幕的製作

  歡迎來到第二堂課!相信各位已經準備好Notepad++了吧!沒準備的也沒關係,請立刻去準備吧。Notepad++是非常好的軟體,他可以協助你用記事本寫程式語言,而且可以將編碼轉為日文,在本次的教學裡面我們非常需要哦!



  這是我們Notepad++的軟體介面,我們就是要透過這個程式寫彈幕哦。請看圖一,我們遵照他的方法將編碼調成日文後,就等於成功的跨出了第一步了。由於彈幕風是日本所製作的程式,我們才需要這個哦!如果找不到Notepad++(應該是找的到的),請用Word吧。


  接著就是程式語言的設定了。這是利用word作不出來的效果,可以增加編程的效率哦!請使用圖二的方法進行設定程式語言。設定完後是看不到效果的,我們得開始寫彈幕後才會有效果。爲什麼會增加編程的效率呢?因為啊,彈幕風是一個使用記事本就可以編輯彈幕的程式,於是我們可能會有括號漏掉等有的沒的無言現象!當我們照著圖二的方法作時、我們的括號就會有展開的功能,不但好管理更好檢查喔。


  Notepad++介紹完了,我們就準備開始寫彈幕吧!心中是否有些亢奮呢?是否?是否?是否?是否?


  首先我們建立一個新的筆記本文件「第一個彈幕」,並輸入以下內容~

#東方弾幕風

#Title[]

#Text[]

#Player[]

#ScriptVersion[]

script_enemy_main {

@Initialize {
}

@MainLoop {
}

@DrawLoop {
}

@Finalize {
}

}


  感到想吐了嗎?別吐啊!這一切都是幻覺,等我解說後你就會感到太簡單、根本一點都不可怕。


  首先呢、第一行的#東方彈幕風,是進行彈幕文件的宣告。宣告這是一份彈幕風文件、宣告這個文件可以被彈幕風打開,這一句可是非常重要的喔!而且記得一定要用日文打,否則是沒有用的。


  再來是#Title[]和#Text[]囉。空格可不是要留空的,基本上!Title是在選擇彈幕時出現的名稱、Text則是在選擇彈幕時出現的詳細說明。因此你可以在Title處打入<ㄆ符「ㄆㄆㄆㄆㄆ你ㄇㄉ」>、在Text處打入<就是亂ㄆ>之類的喔。


  請看#Player[]。由於彈幕風是可以自由選擇各種角色的,所以自然需要控制你的角色設定。比如說你想限定「只有RemiuA可以使用。」,那就輸入RemiuA。如果你覺得「都可以!我沒有特別限定。」,你就輸入FREE(當你想要限定時,請指定Player路徑!)


  #ScriptVersion[]是指彈幕風腳本的版本,腳本的英文名稱為Script,學過程式語言的自然更會知道。由於我們是0.12m版本,請輸入[2]。倘若你是ph3版本,請輸入[3]。不過我們這裡一律使用[2]。至於[1],我們就別管了吧。


  重頭戲開始囉!我們的《彈幕程式碼》部分。

  script_enemy_main {...} (...表示中間暫時省略) :這個指的是基本執行,所有彈幕的指令都會放在裡面。一個程式裡面只能有一個基本執行喔。


  @Initialize {...} :這個指的是初始化行動,在程式執行的時候只會執行一次!在這裡可以設定魔王的生命值等林林總總,待會我們會在繼續深入說明。


  @MainLoop {...} :在遊戲中會不斷循環的部分!通常於此放置於彈幕的工作


  @DrawLoop {...} :一樣也是會不斷循環的部分,但是這裡專門放置繪圖指令


  @Finalize {...} :此程式結束後發生的事情,比如魔王爆掉之類的。


  以上就是一個基本彈幕所需要的基本本體。其實還有許許多多的設定,像是背景的繪製!但是我們只是要製作一個基本的彈幕,在這個時候,我們還不需要製作什麼進階的喔。

  首先,讓我們初始化敵人吧。


  SetX(GetCenterX);
  SetY(GetClipMinY + 120);
  SetLife(2000);
  LoadGraphic("script/img/ExRumia.png");
  SetTexture("script/img/ExRumia.png");


  又是令人暈眩的語法對吧…囧。別害怕,Let's Go To 了解……


  首先、SetX和SetY是一個設定數。他指的是魔王的位置、因此在發射彈幕時我們也需要使用這兩個變數的傳回指令(除非你的彈幕比較進階)。對了!什麼是傳回指令呢?一般來說、傳回指令以Get開頭,像是語法中GetCenterX的意思即是取得中間X座標GetClipMinY則是取得最下方Y座標。這裡的SetX、SetY的傳回指令就是GetX,GetY。對了,在每個指令的後端請加上分號,這是個需要培養的重要習慣哦。




  再來就是SetLife囉!這就是設定生命的意思,相信字面上的意思就很清楚。在後面的小括號打入生命就好,基本上2000已經算是非常少的了,若想要玩這張符卡(魔王)玩的更久,你可以進行更大值的修改



  然後是圖片讀取指令,也就是所謂的魔王圖片讀取囉!在這裡的LoadGraphic是"讀取圖片"的意思,而SetTexture則是"設置魔王圖片"的意思。



  在此,我們的初始化命令已經告一段落囉!接著就是子彈的製造了~彈幕的重點!首先我們在最前端(script_enemy_main下面!)可以輸入一指令:


  let dir = 23;


  這行文字即是變數設定的意思!每個變數一開始都必須進行設定,但是在彈幕風中有一些卻是不用設定的變數(像是生命值。)此稱為全域變數(global),基本上基礎彈幕應該是不會使用到這個。


  接著請在MainLoop的大括號中,輸入這樣的一行代碼:


  CreateShot01(GetX,GetY,2,dir,WHITE04,0);
    dir+=15;

沒錯!這正是製造彈幕的指令。首先,我們從第一句開始解剖——CreateShot01即是最簡單的彈幕製造,他有6個引數:CreateShot01(發射位置X,發射位置Y,發射速度,發射角度,發射子彈圖形,發射延遲)


首先,發射子彈圖形這應該是最令人疑惑的了吧?因為不知道要怎麼樣去設定吧。





  這就是各子彈的設定了!當然你也可以自行使用自己的子彈圖,但是!別忘記我們只是要作一個簡單的彈幕,在此我們暫不討論到那麼遠哦。前面的RED是顏色,記住每個字都要大寫,所以你可以改成BLUE、PURPLE等顏色。

  然後還有發射延遲。這是當你準備發射子彈時的延遲,數字越大代表的當然是你的延遲越久。

  其中還有發射位置,我們以Get魔王位置的指令來設定發射速度以5來噴射(等)發射角度就是本次的關鍵了。由於發射子彈這種事情本來就有可能是直直往前發射,因此我們透過一開始設定的dir指令來定義彈幕的形狀。一開始,彈幕會從23角的地方開始發射,然後彈幕就會每次增加角度3發射。因此大概會形成出一個螺旋狀的彈幕囉!


  彈幕做完了,繼續進行遊戲設置的地方。請在彈幕指令之後輸入這兩行:


  SetCollisionA(GetX, GetY, 24);
  SetCollisionB(GetX, GetY, 24);


  這是敵人判定點的設定。SetCollisionA指的是命中判定點,也就是子彈打到敵人會讓敵人減少的區域。SetCollisionB就是指自機撞到敵人會死掉的判定區域。這兩個指令的設定值是一樣的,但是功能卻不相同喔。第一第二個設定值指的是判定點的區域第三個指的則是判定點的判定點的半徑。


  以上就是所有MainLoop的部分了!現在我們要來進行DrawLoop的設定。很簡單,裡面我們只需要一行指令:


  DrawGraphic(GetX, GetY);


  前面所作的事情是讀取和使用,並沒有關聯到繪製!所以我們的魔王根本就出不來。要讓魔王出來,我們只需要有這一個指令就好了,後面的設定值就是X和Y座標了。


  最後!為了讓魔王爆掉,爲什麼不要刪除魔王呢?請在Finalize中輸入這一行:


  DeleteGraphic("script/img/ExRumia.png");


  完成了嗎!作到這裡,你的彈幕幾乎已經可以顯示的出來了!如果我們整理一下,你所作的彈幕腳本應該長這樣:

#東方弾幕風
#Title[ㄆㄆ]
#Text[ㄆㄆㄆ]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let dir = 0;
@Initialize {
SetX(GetCenterX);
SetY(GetClipMinY + 120);
SetLife(2000);

LoadGraphic("script/img/ExRumia.png");
SetTexture("script/img/ExRumia.png");
SetGraphicRect(0, 0, 63, 63);
}

@MainLoop {
SetCollisionA(GetX, GetY, 24);
SetCollisionB(GetX, GetY, 24);
CreateShot01(GetX,GetY,2,dir,WHITE04,0);
dir+=15;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic("scrip/timg/ExRumia.png");
}
}


  接著就把你所建立的檔案裝進彈幕風的script資料夾中吧!對了,如果你是使用Notepad++又有選擇C++編碼,請選擇txt存檔方式。





  然後你就可以打開東方彈幕風,瀏覽你的彈幕作品啦!在這之前,請先使用上次準備好的AppLocal。再下圖位置選擇瀏覽後,找出彈幕風本體再按下一步。下一步的地方請使用日本語之後即可正常執行~(其實不用也沒關係,但是會有亂碼,且如果你的路徑有中文,你必須使用!)



  不過可能翻了又翻就是翻不到自己的作品,到底是要開哪一個呢?其實,只要你的符卡(魔王)名稱是中文,根本上就是會出現問號!所以用英文名稱(或日文)並且進入Directory這個選項,就可以找到囉!


  基本上,你若是成功了,這將是你的預覽畫面:




  是不是一個基本的彈幕了呢!但是,這樣的彈幕實在是太有規律性了!所以……下一次,我們將教到如何更改自己的彈幕使它難度增加而不會有動都不動就可以閃開的巨大空隙。


2-更多彈幕的製作

  各位同學好!又到了上課的時間了~上一次,我們講到如何使用簡單的語法創造簡單的彈幕,還有簡單的本體創造。今天我們將更深入這些內容,製造出更深入的彈幕囉。首先一般來說,彈幕不一定要很亂,或者說很整齊只要能夠閃的過去都可以稱作為一個好的彈幕。要創造一個看似沒有空間、卻又躲的過去的彈幕是很難的,光是上次教的那些根本就是不可能的。今天我們要教的叫做條件式,可以幫助自己的彈幕更加多樣化。


  我們從最基礎的條件式If說起吧,關於If條件式是有三種寫法的:

  if () {}:如果()成立,執行{}。

  else {}:如果所有if都不成立,執行{}。(前面的if存在一個或以上才可以使用。

      else if () {}:如果以上都不成立,就看看if是不是有成立則執行{}。
前面的if存在一個或以上才可以使用。

  而在()裡面,我們得輸入像是以下的條件

  a == b:如果a等於b。(不可以使用一個等於,如果使用了就是宣告式了。

      a >= b:如果a大於等於b。

      a > b:如果a大於b。

  a <= b:如果a小於等於b。

      a < b:如果a小於b。

  a != b:如果a不等於b。

其中也可以使用運算符號,在這邊除了加減乘除,還有一個比較常用的符號叫做同餘(%)。這個符號的意義就是求前面數字的餘數,比如說12%6就會得到0。這裡舉一個最簡單的例子,我們把上次的子彈射擊修改一下,就是這樣:

  變數宣告:

  let dir = 0;

      let count = 0;

  MainLoop:

  if (count%10 == 0){
  CreateShot01(GetX,GetY,2,dir,WHITE04,0);
      dir +=15;
  }

  count++;

這邊運用了上面教過的所有指令,大家應該知道是什麼意思了吧!其實,如果翻成中文,這一段代碼應該是:

變數宣告:

宣告變數dir是0;count是0。

MainLoop:

如果count除以10是0,就創造子彈,並且增加dir變數15。

如果不是count變數就加一。

這是一種條件式的用法,基本上就是使子彈的發射有間隔而不是每0.1秒就發射一顆。條件式還可以使不同子彈在不同時間發射出去,不會條件式,你就輸了。另外一種條件式叫做alternative,是當你需要非常多條件的時候使用,會比較方便。alternative的語法如下:

  alternative():設立條件對象()。

  case(){}:如果條件對象符合()中的條件,就執行{}。(可以寫成case(a,b)就是如果是a或b。

  others{}:如果所有條件都不符合,就執行{}。(和else的用法很像。)

  除了以上這兩種條件式,下面還有一種重複式。以下有幾種重複式:

  loop(){}:最常見的重複式,重複{}中的動作()次。(省略()的話就是無限次循環。

  while(){}:條件重複式,如果()成立則執行{}。

  當重複式想要結束怎麼辦?輸入break;即可。不過說這麼多,子彈還是只能夠用最基本的方式發射吧。也許有人會問:像是雷射要怎麼發射?很簡單,接下來我們教到各種子彈發射的語法~



  CreateShot02(x,y,速度,角度,加速度,最大速度,子彈圖像,延遲發射)

  這就是會越變越快的子彈了,可以透過這個語法進行夾彈的製作哦。

  CreateShotA(ID,x,y,延遲)

  這麼短的指令可不是沒有目的的,除了ID必要是數字外,輸入後我們還需要另外一項指令進行設定

  SetShotDataA(ID(剛才設定的ID),軌道變化所需時間,速度,角度,角速度,加速度,最大速度,圖像)

  設定完後~你還是不能夠看見子彈發射,因為你還需要一個發射的指令

  FireShot(ID)

  這樣子才可以圓滿發射唷。另外需要FireShot發射的簡單雷射語法

  CreateLaserA(ID,x,y,長,寬,圖像,延遲)

  SetLaserDataA(ID,軌道變化所需時間,角度,角速度,長的變化,移動速度,移動角度)

  這麼多的子彈語法,只要加上角度的妙用、條件和重複句的控制,是不是就能作出一個不錯的彈幕了呢?還沒!還沒呢!相信在東方裡面有不少人被瞄準自己的子彈打到,如果沒有瞄準自己的子彈那該有多好啊?!但是身為彈幕製作者,就是要作出打的到人的子彈啦……所以,我們來作瞄準玩家的子彈吧

  製作的方法有兩個,一個是控制全部的子彈,一個是單一子彈。控制全部的子彈非常簡單,你只需要打上一句語法即可!

  SetShotDirectionType(PLAYER)

  這句語法的意思就是:當角度為0,就是等於瞄準玩家的角度。非常的陰險狡猾吧!在括號內也可以輸入ABSOLUTE或者SEQUENCE,分別是絕對角度和相差角度的意思。

  第二個方法就是直接將單一子彈的角度設定成對玩家的角度。在設定前一定有不少人覺得無法取得角度,不過其實只要一句語法即可:

  GetAngleToPlayer

  沒錯,就是這麼簡單!直接在角度的地方貼上這麼一個語法、或者使用變數宣告,輕輕鬆鬆作出殺人彈幕。

  簡單說,到現在你已經可以做出各種不同進階的彈幕了。但是若要成為一個真正的SpellCard,你欠缺的是符卡宣言!也就是會告訴你符卡名稱的小框框,要怎麼呼喚它呢?

  let name ="符卡名稱"

          CutIn(YOUMU, name, "", 0, 0, 0, 0);

就是這樣,你應該已經可以做出屬於自己的一張符卡了!下一次,我們將學到如何將符卡串起來還有更多指令的教學~



今天先搬運到此為止,請各位努力練習哦OW<
37
-
未登入的勇者,要加入討論嗎?
板務人員:

6108 筆精華,09/28 更新
一個月內新增 0
歡迎加入共同維護。


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】