C .
ODE
G
AMELET
# PIXI 文字輸入框(PixiTextInput) 基於 Mwni 的函式庫改編而來, 這個 PIXI.js 的模組提供了一種方便的方法來將文字輸入框添加到 PIXI.js 舞台上。輸入框本身是一個 HTML \<input\> 元素,根據 PIXI.DisplayObject 給定的變換位置放置在舞台上方。方框會在 PIXI 舞台上繪製。此外,您可以選擇在文字輸入框失去焦點時,選擇是否應該用 PIXI.Text 來替代 \<input\>。 ## 我的改動 1. 事先宣告 Class 的屬性變數,因為 TypeScript 在使用 `this` 賦值前,需要事先宣告屬性變數。 2. 將所有帶有 _ 前綴的屬性、函數,變成私有屬性(`private`)。 3. 修正了一個把 `_dom_visible` 誤寫成 `dom_visible` 的 BUG。 4. 添加了三個 `interface`,`TextInputOptions、TextInputStyle、TextBoxStyle`,並於部分輸入參數加上型別標註。 5. 刪除函數 `renderWebGL`、`renderCanvas`,這些函數用於支援 pixi v4,但此模組使用的 pixi 為 v5,因此不需要這些函數。 6. 讓 _surrogate.resolution 預設為 2。 7. 修正部分因 JavaScript 源碼,轉移到 TypeScript 後所出現的錯誤提示,如型別錯誤等。 ## 使用範例 ```typescript import pixi = CG.Base.pixi; import TextInput = CG.PixiTextInput.TextInput; function examples() { // 初始化 pixi 舞台 pixi.initialize(600, 500); // 建立文字輸入框 const input = new TextInput({ input: { fontSize: '25pt', padding: '14px', width: '500px', color: '#26272E' }, box: { fill: 0xE8E9F3, rounded: 16, stroke: { color: 0xCBCEE0, width: 4 } } }) input.position.set(pixi.stageWidth * 0.5, pixi.stageHeight * 0.5); // 調整輸入框的位置 input.pivot.set(input.width * 0.5, input.height * 0.5); // 調整輸入框的錨點 pixi.root.addChild(input); // 將文字框添加到舞台中 const input2 = new TextInput({ input: { fontSize: '20pt', padding: '14px', width: '400', color: '#26272E' }, box: { fill: 0xFFFFFF, rounded: 16, stroke: { color: 0x333333, width: 4 } } }) input2.position.set(pixi.stageWidth * 0.5, pixi.stageHeight * 0.75); input2.pivot.set(input.width * 0.5, input.height * 0.5); pixi.root.addChild(input2); } examples(); ``` ## 原始 MIT 許可證 ```txt MIT License Copyright (c) 2018 Mwni Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` ## Links and Resources - [pixi-text-input](https://github.com/Mwni/pixi-text-input) ## Authors **[cook1470](/profile/cook1470)**
<center><strong> <font size=5> <font color=EA7869> # 光暈戰記武器素材擴充包(TwilightWarsWeaponsResource) </font> </font> </strong><br> <font color=7869EA> <strong> <font size=4> <font color=7869EA> # 本模組為光暈戰記同人陣添加多種武器外觀 </font> </font> </strong><br> <strong> <font size=4> <font color=EA7869> <details> <summary> <strong> <font size=4> <font color=EA7869> ## 手動新增自創武器教學(點擊打開) </font> </font> </strong> </summary> <br> <font color=7869EA> 點開事件表(.events)的<strong>光暈戰記遊戲設定</strong> <br><br> ![](https://i.imgur.com/bnCBKkk.png) <br><br> 找到下方的<strong>自製近身武器</strong>與<strong>自製遠程武器</strong> <br><br> ![](https://i.imgur.com/Al86kNu.png) </font><br><br><br> <strong> <font size=4> <font color=EA7869> </details> <details> <summary> <strong> <font size=4> <font color=EA7869> ## 預置武器修改教學(點擊打開) </font> </font> </strong> </summary> <br> <font color=7869EA> <a href="cg://source/CG.TwilightWarsWeapons/Preset.events" class="mat-raised-button mat-primary">預置事件表</a> <br><br> 找到最左側<strong>檔案總管</strong>內,<strong>CG.TwilightWarsWeapons</strong> 之中的<strong>Preset.events</strong>,右鍵<strong>複製檔案</strong>,更新後就不會遺失改過的設定 <br><br> ![](https://i.imgur.com/svcKdMk.png) <br><br> 找到複製後的<strong>Preset_copy.events</strong>,接著就能依照自己的喜好修改預置武器 <br><br> ![](https://i.imgur.com/Cuu5mUp.png) <br><br> 改完之後,找到需要使用自創武器的事件表選擇<strong>設定</strong> <br><br> ![](https://i.imgur.com/JBQr85k.png) <br><br> 在<strong>預先載入</strong>的地方把剛剛的<strong>Preset_copy.events</strong>打勾,就可以使用裡面的武器了 <br><br> ![](https://i.imgur.com/cd1zJkg.png) <br><br> </font> </details> <details> <summary> <strong> <font size=4> <font color=EA7869> ## 預置武器事件表更新教學(點擊打開) </font> </font> </strong> </summary> <br> <font color=7869EA> 首先刪除原本在 CG.TwilightWarsWeapons 資料夾中的<a href="cg://source/CG.TwilightWarsWeapons/Preset.events" class="mat-raised-button mat-primary">預置事件表</a> <br><br> 接著更新模組 <br><br> 打開最新版本的<a href="cg://source/CG.TwilightWarsWeapons/Preset.events" class="mat-raised-button mat-primary">預置事件表</a> <br><br> 點開右上角的**編輯原始資料(JSON)** <br><br> ![](https://i.imgur.com/QH5bVdp.png) <br><br> 找到武器代碼,從上方**逗號與大括號**一次框選到下方相對位置的**大括號**(可以從顏色判斷)並複製 <br><br> ![](https://i.imgur.com/iOI38jq.png) <br><br> ![](https://i.imgur.com/MyDAyGa.png) <br><br> 最後複製到 **自己的** 預置武器事件表之中的對應位置內就完成了 <br><br> ![](https://i.imgur.com/QH5bVdp.png) <br><br> </font> </details> <strong> <font size=5> <font color=EA7869> ## 作者 </font> </font> </strong> <strong> <font size=5> <font color=7869EA> 阝千翎 </font> </font> </strong> **[<img src="https://gamelet.online/clients/assets/v1/img/cg_logo.png" width="30px" /><a href="https://code.gamelet.com/profile/Chinatsu" target="_blank" style="color:#55BBFF;">CG](/profile/117336754650487480063@google)**</a> **[<img src="https://gamelet.online/clients/assets/v1/img/gamelet_icon.png" width="30px" /><a href="https://gamelet.online/user/117336754650487480063@google/board" target="_blank" style="color:#55BBFF;">嘎姆](https://gamelet.online/user/117336754650487480063@google/board)**</a> **[<img src="https://play-lh.googleusercontent.com/Qolm5gr9jnabjk-0z79srjYC1XPVExribNz5kbDmGJeEtmRlo0UQoQEIkKMHRyt5paw" width="30px" /><a href="https://www.youtube.com/channel/UCALDNiLyfHERP13-BG9xpFQ?sub_confirmation=1" target="_blank" style="color:#55BBFF;">YouTube](https://www.youtube.com/channel/UCALDNiLyfHERP13-BG9xpFQ?sub_confirmation=1)**</a> **[<img src="https://cdn-icons-png.flaticon.com/256/1384/1384065.png" width="30px" /><a href="https://twitter.com/V_chiurin" target="_blank" style="color:#55BBFF;">推特](https://twitter.com/V_chiurin)**</a> **[<img src="https://cdn.iconscout.com/icon/free/png-256/twitch-11-461838.png" width="30px" /><a href="https://www.twitch.tv/haokute39171765" target="_blank" style="color:#55BBFF;">Twitch](https://www.twitch.tv/haokute39171765)**</a> **[<img src="https://cdn-icons-png.flaticon.com/512/145/145802.png" width="30px" /><a href="https://www.facebook.com/profile.php?id=100041014581991" target="_blank" style="color:#55BBFF;">facebook](https://www.facebook.com/profile.php?id=100041014581991)**</a> </center> <meta http-equiv="refresh" content="0;url=https://youtu.be/I9iP_hCM7mU?si=PbEhnT0Xud1pvzRw">
# Base2 重新架構的Base2,相比Base少了很多功能,包括Pixi/Sound/ResourceManager/Physics/geoms都被拿掉,只留最主要的CG功能。 ## 基本功能 1. 取得專案的資料 ```typescript // 取得專案代碼 CG.Base2.projectCode; // 取得資源 CG.Base2.getAppResource(resourceAlias: string) // 取得資源網址 CG.Base2.getAppResourceFileUrl(resourceAlias: string, filename?: string) ``` ## 更新循環 Base2內建了一個更新循環系統。 ```typescript // 先定義一個每幀都要更新的函式 function updateFunc(dt: number) { } // 將函式加入更新循環系統 CG.Base2.addUpdateFunction(updateFunc); // 將函式移出更新循環系統 CG.Base2.removeUpdateFunction(updateFunc); ``` 另外也提供子更新循環系統可使用。 ```typescript import Updater = CG.Base2.utils.Updater; // 先定義一個每幀都要更新的函式 function updateFunc(dt: number) { } // 建立子更新循環系統 let updater = new Updater(); // 將函式加入更新循環系統 updater.addDelayFunction(updateFunc); // 可暫停 updater.pause(); // 可繼續 updater.resume(); ``` ## 鍵盤管理員 Base2提供了一個基本的鍵盤管理員,可以在按鍵被按下去(DOWN)、提起來(UP)、先按再提(PRESSED)的時候觸發事件。 ```typescript // 取得鍵盤管理員 import Keyboard = CG.Base.keyboards.Keyboard; import keyboard = CG.Base2.keyboard; import Key = CG.Base2.keyboards.Key; // 鍵盤事件 keyboard.on(Keyboard.EVENT.DOWN, (event: KeyboardEvent) => { if (Key.SPACE.matchEvent(event)) { // 當空白鍵被按下去的時候... } }) // 檢查目前按鍵狀態 if (keyboard.isDown(Key.SPACE)) { // 目前空白鍵是正在按下去的狀態 } ``` ## 補間變化 Base2內建了[tweenjs](https://github.com/tweenjs/tween.js)用來將某個物件的屬性,在一段時間內作動態的變化。 ```typescript async function makeAnimation() { // 建立一隻有x,y資料的動物 let animal = { x: 100, y: 100, }; // 建立補間變化,在1秒內讓動物的x和y變化到指定的值 let tween = new TWEEN.Tween(animal); tween.to( { x: 300, y: 200, }, 1000 // 毫秒 ); tween.start(); // 等待變化完畢 await CG.Base2.waitTween(tween); console.log(animal.x); // 這時會印出 300 } ``` ## JSZip Base2內建[JSZip](https://stuk.github.io/jszip/)。 ```typescript async function loadZip() { let zip = new JSZip(); await zip.loadAsync(buffer); for(let filename in zip.files) { ... } } ```
# MidiLib A simplified library to easily play midi music. ## Getting Started Minimum codes to get a midi to play. ```typescript async function examples() { // load the midi resource let player = await loadAndCreateMidiInstrumentPlayer("MidiLib.testmidi"); player.play(); } ``` Also support playSound() in Base library. ```typescript CG.Base.resourceManager.playSound("MidiLib.testmidi"); ``` Codes to get full control. ```typescript async function examples() { // load the midi resource await resourceManager.addAppResource("MidiLib.testmidi").load(); // create the player let player = createMidiInstrumentPlayer("MidiLib.testmidi"); // preload instruments, you can specify the default instrument // find the full list of instrument names in `instruments.ts` await player.preload({ defaultInstrument: "acoustic_grand_piano" }); // play the music player.play({ loop: true, startTick: 0, loopStartTick: 0, gain: 2, // volume tempoScale: 1.5, // tempo }); // control the music player.stop(); player.pause(); player.resume(); } ``` ## Player Events Player emits events for advanced controlling ### Track Events This event emits when a midi note is time to be played (or other meta data is dispatched.) ```typescript function catchTrackEvents(player: InstrumentPlayer) { player.on(MidiTrackEvent.TYPE, (event: MidiTrackEvent) => { let trackEvent = event.trackEvent; if(trackEvent.name == NoteOnEvent.NAME) { // check events/TrackEvent.ts for all TrackEvent names ... } }) } ``` ### EndOfFileEvent This event emits when the play head running to the end of all tracks. ```typescript function catchEndOfFileEvent(player: InstrumentPlayer) { player.on(EndOfFileEvent.TYPE, (event: EndOfFileEvent) => { ... }) } ``` ### ControlEvents This event emits when the player is being controled by calling control functions ```typescript function catchControlEvents(player: InstrumentPlayer) { // play() player.on(ControlEvent.TYPES.PLAY, (event: ControlEvent) => { // this happens when preloading completes after play() is called }) // stop() player.on(ControlEvent.TYPES.STOP, (event: ControlEvent) => { ... }) // pause() player.on(ControlEvent.TYPES.PAUSE, (event: ControlEvent) => { ... }) // resume() player.on(ControlEvent.TYPES.RESUME, (event: ControlEvent) => { ... }) } ```
# RyvexiaLib 這是一個用來製作 **[Ryvexia](https://ryvexia.gamelet.online/)** 音樂遊戲的核心模組,如果想要摳出新專案來製作遊戲,請不要摳此模組,建議摳遊戲成品。 有任何問題請於 **[專案討論](https://code.gamelet.com/discuss/p/RyvexiaLib/0)** 回報,會盡快解決。 ### 遊玩方法 遊戲開始後,會播放音樂,並從畫面上方落下音符,當音符與下方的判定框重合後按下對應的按鍵來打擊音符,打擊時機越準分數越高。 預設為四個軌道,對應按鍵分別為 D、F、J、K。 音符的種類目前分為下列幾種: - **Tap**:單壓,當音符與下方的判定框重合後,按下對應的按鍵來打擊音符。 - **Hold**:長壓,當音符與下方的判定框重合後,按住對應的按鍵直到音符結束時完成打擊。 遊戲中按下 ESC 可暫停遊戲。 ## 如何開始? ```typescript // 設置譜面檔案路徑(專案內),必須先於專案內新增譜面資料檔案。 const chartSource = `CG.${CG.Base.projectCode}/test.json`; // 加載檔案。 CG.Base.resourceManager.addAppSource(chartSource) // 初始化 RyvexiaLib。 CG.RyvexiaLib.initialize() .then(() => { // 初始化完成後 // 初始化 pixi 舞台,建議舞台寬高 1920 x 1080。 CG.Base.pixi.initialize(1920, 1080); // 新增一個譜面資料物件,並匯入譜面資料。 const chartData = new CG.RyvexiaLib.datas.ChartData(); chartData.importSource(chartSource); // 加載該譜面的音樂資料。 chartData.loadMusic(() => { // 加載完成後 // 建立 Ryvexia 遊戲物件,並加入到 root 舞台顯示於畫面上。 const game = new CG.RyvexiaLib.games.Game(); CG.Base.pixi.root.addChild(game); // 設置該遊戲的譜面資料並開始遊戲。 game.setup(chartData).start(); }) }) ``` ## 自製譜面 本模組提供了具有圖形化介面的譜面編輯器,當然你也可以自己使用程式碼添加,甚至利用譜面資料可以新增資料的功能,自製一個譜面編輯器也可以。 ### 如何從編輯器開始? #### 快捷鍵: - W、上:譜面向上移動。 - S、下:譜面向下移動。 - Shift + 移動:加速移動。 - +:增加每小節的拍數。 - -:減少每小節的拍數。 - Shift + 測試遊戲:啟用自動遊玩模式。 (也可以拖動進度條來改變音樂進度。) ```typescript // 初始化 RyvexiaLib CG.RyvexiaLib.initialize() .then(() => { // 初始化 pixi 舞台 CG.Base.pixi.initialize(1920, 1080); // 創建譜面資料物件,BPM 為 160 const chartData = new CG.RyvexiaLib.datas.ChartData(160); // 設定譜面音樂資源名稱 chartData.musicAlias = "你的音樂資源別稱"; // chartData.musicFilename = "你的音樂資源檔名"; // 如果你的音樂是壓縮檔,就會需要用到這一條。 // 建立譜面編輯器並匯入譜面資源 const editor = new CG.RyvexiaLib.editors.ChartEditor(chartData); editor.loadByStorage(); // 於譜面編輯器建立後嘗試讀檔,若無檔案則會忽略。 editor.saveWhileTest = true; // 啟用編輯器測試遊戲時自動存檔。(只有在測試遊戲時會存檔,不是有更新就會儲存) // 建立主要遊戲(讓編輯器用於測試) const game = new CG.RyvexiaLib.games.Game(); // 建立編輯器頁面(用於控制編輯器與遊戲之間的溝通) const editorPage = new CG.RyvexiaLib.utils.pages.ChartEditorPage(editor, game); // 顯示編輯器頁面 editorPage.show(); }) ``` ### 如何從程式碼編輯? ```typescript // 創建一個譜面資料,bpm 為 175。 const chartData = new CG.RyvexiaLib.datas.ChartData(175); // 設定一些譜面資料。 chartData.title = 'Sing My Pleasure'; // 譜面標題 chartData.musicAlias = 'RyvexiaLib.Sing My Pleasure'; // 音樂資源別稱 chartData.musicAuthor = 'Vivy (Vo.Kairi Yagi)'; // 音樂作者、歌手 chartData.chartAuthor = '酷可(cook1470)'; // 譜面作者 // 預設有 4 個軌道,於第 1 軌道,第 0 節拍,位置 0 添加音符。 chartData.tracks[1].addNote(0, new NoteData(0)); // 於第 0 軌道,第 0 節拍,位置 0.5 添加音符。 chartData.tracks[0].addNote(1, new NoteData(0.5)); // 於第 2 軌道,第 7 節拍,位置 0.5 添加音符,音符長度 8。 chartData.tracks[2].addNote(7, new NoteData(0.5, 8)); // 創建好以後,可以使用 exportJson 匯出 JSON 物件,並使用 JSON.stringify 轉換成字串。 const text = JSON.stringify(chartData.exportJson()); // 再使用 Base 的 HtmlUtil 來下載檔案。 CG.Base.utils.HtmlUtil.downloadText(text, '我的譜面.json'); // 也可以將譜面資料壓縮後直接下載,不需轉換 JSON,且檔案大小會更小。 // CG.Base.utils.HtmlUtil.downloadText(chartData.exportGzip(), '我的譜面.rvx'); ``` 如果你想要使用壓縮後的譜面檔案,匯入的方法稍有不同。 ```typescript const chartSource = 'CG.YourProject/我的譜面.rvx'; // 與 #如何開始? 相同,先加載要使用的譜面,可參考上方介紹,在此省略。 // 利用 Base 的資源管理器讀取成字串。 const text = CG.Base.resourceManager.getText(chartSource); // 新增一個譜面資料物件,並匯入壓縮譜面資料。 const chartData = new ChartData(); chartData.importGzip(text); // 後續與 #如何開始? 相同,建立遊戲、載入音樂並開始遊戲。 ``` ## 頁面控制器 本模組提供了一個簡單的頁面控制器,以及一些預設的頁面可供使用,以下展示以編輯器為主的控制流程。 包含了封面、校正頁面、編輯器頁面。 ```ts // 初始化 RyvexiaLib CG.RyvexiaLib.initialize() .then(() => { // 初始化 pixi 舞台 CG.Base.pixi.initialize(1920, 1080); // 建立頁面管理器。 const pageManager = new CG.RyvexiaLib.utils.PageManager(); // 建立封面頁面,並註冊到頁面管理器中。 const coverPage = new CG.RyvexiaLib.utils.pages.CoverPage(); // coverPage.titleText.text = "我的音樂遊戲"; // 可改變封面標題文字,預設為 Ryvexia pageManager.registerPage(coverPage); // 建立校正、設定頁面,並註冊到頁面管理器中。 const calibrationPage = new CG.RyvexiaLib.utils.pages.CalibrationPage(); pageManager.registerPage(calibrationPage); const chartData = new CG.RyvexiaLib.datas.ChartData(175); chartData.musicAlias = "你的音樂資源別稱"; const editor = new CG.RyvexiaLib.editors.ChartEditor(chartData); editor.loadByStorage(); editor.saveWhileTest = true; const game = new CG.RyvexiaLib.games.Game(); // 建立編輯器頁面(用於控制編輯器與遊戲之間的溝通),並註冊到頁面管理器中。 const editorPage = new CG.RyvexiaLib.utils.pages.ChartEditorPage(editor, game); pageManager.registerPage(editorPage); // ========== 操控個頁面之間的切換流程。 ========== // 當於封面頁面開始時。 coverPage.onStart = () => { // 顯示校準頁面。 pageManager.show(calibrationPage.code); } // 當於校準頁面返回時。 calibrationPage.onReturn = () => { // 顯示譜面編輯器頁面。 pageManager.show(editorPage.code); } // 當於譜面編輯器頁面返回時。 editorPage.onReturn = () => { // 顯示封面。 pageManager.show(coverPage.code); } // 一開始先顯示封面頁。 pageManager.show(coverPage.code); }) ``` ## 進階設定 本模組將一些可設置常數放在 `CG.RyvexiaLib.Constant` 內,裡面有一些特別的參數可以調整,以下為預設值。 ```typescript // 以下可設定各判定分的範圍(時間差)。 CG.RyvexiaLib.Constant.PERFECT_TIME_RANGE = 46; CG.RyvexiaLib.Constant.GREAT_TIME_RANGE = 92; CG.RyvexiaLib.Constant.GOOD_TIME_RANGE = 138; CG.RyvexiaLib.Constant.MISS_TIME_RANGE = 200; // 以下可設定作為判定分顯示的文字,遊戲中、結算等。 CG.RyvexiaLib.Constant.SCORE_TYPES.PERFECT = "Perfect"; CG.RyvexiaLib.Constant.SCORE_TYPES.GREAT = "Great"; CG.RyvexiaLib.Constant.SCORE_TYPES.GOOD = "Good"; CG.RyvexiaLib.Constant.SCORE_TYPES.MISS = "Miss"; ``` ## 作者 **[module_cook1470](/profile/64897095@github)**
ⒸCode.Gamelet.com | Privacy Policy | Terms of Service