文章列表

街霸六-如何不要被【贏】成為競技遊戲的唯一目標?

手機‧電玩
MacauYeah・2024-01-19

眾所週知,玩遊戲普遍都是圖開心。很多朋友玩遊玩競技遊戲時,【贏】都是一個很重要的樂趣指標,但競技總不可能每個人都贏,輸的人反而是大多數。所以競技遊戲若沒有其他樂趣,玩著玩著,就會越來越少參與者。 問題是,競技遊戲真的有其他方面的樂趣嗎? 筆者認為是有的,但至少參與者的心態要放開。 就像求學不是求分數一樣,探索一門新知識比分高低要來得重要,玩遊戲也更是如此。以筆者玩街霸六的情況來講,可以探索的地方實在很多:- 目押、取消連技- 對空- 對策動力衝擊- 對策突進- 狗昇、防狗昇- 打亂動、搶制(Abare)- 壓起身 (Meaty)- 安全跳 (Safe Jump)- 立回 (Neutral)- 確反 (Punish)- 差合 (Whiff Punish)- 打拆 (Shimmy) 最後才引伸不同的角色對策。 而大部份人都一定會陷入的低潮就是:當等級越高,對手的熟練度就越高,對機制的理解就越深,然後就會對戰得越沮喪。筆者因為一些原由,看到別人都爬分時都有非常沮喪的練歷,也看到退遊戲的心路歷程分享。 筆者屬低分區,無條件指導別人如何進步,但筆者可以提的意見是,要逆向思維:自己會輸,是因為對方是強者,跟強者對戰,其實是在學習、在感受。有時候,筆者也會因些微差距而輸了對局。有時候,筆者也會想,是不是對方運氣好。 但感謝街霸六的對戰大堂,只要對方願意,可以很方便的跟同一位對手重複對戰。經過重複對戰,你就會知道是不是真的只是對方運氣好。更重要的是,重複對戰可以有助於大家熟知對手的策略,只要有對策,對局就不一樣。就算當下無解,也可以在訓練室再進一步研究。 街霸六的對戰機制和訓練室的各項細微功能,是眾多手遊、什至是主機遊戲,都無法提供的。可以隨時與陌生對手匹配友誼賽,可以自定義對戰,可以重播比賽,觀看對手的輸入按鍵,訓練室還可以查幀表,錄動作,混合抽樣播放動作,讓你可以有目的性地實驗、練習反應對策。 在分數線機制上也有一些保障,不同角色分數獨立,打上特別段位後有一次跌級保障。讓大家在排名賽上,輸掉也不至於十分心痛。若果心理上實在受不住排名賽的壓力,友誼賽絕對低分爬上高分區的一個試招的好選擇。在對戰大堂的友誼賽中,很易會遇到比自己排名高的對手,多找對方實戰看看,輸了沒有成本,但贏得了經驗。

Spring Boot 01 - 萬物始於Spring boot context

科技新知
MacauYeah・2024-01-16

Spring Boot 01 - 萬物始於Spring boot context 筆者早些時候向一位朋友討論,為何Java那麼不受歡迎。朋友一句就回答,Java煩爆,沒有人會喜歡。 老實講,Java在句法上,實在囉唆。但以筆者的經驗,即使使用其他語言和開發框架,在實戰到一定複雜程度下,其實也一樣煩爆。 而現在的Java框架中,就以Spring boot的入門門檻低。筆者從Spring boot 1.x用到現在的3.x,也真的感受到更多的簡化,所以筆者也加入一起推廣Spring boot的行列。筆者將會通過一系列最小的可執行程式,為大家講解Spring在Web和資料庫上的應用。 所以現在就不廢話,馬上開壇作法 快速下戴模版 使用Spring initializr,可以很容易就建立一個以Spring boot starter為底的java project。大家可以使用Spring 官網又或是vscode plugin 快速地建立一個maven或gradle project。筆者較為熟悉maven,就以maven起一個範例。 在使用Spring initializr有幾件事必需要指定的: Spring boot version: 3.x.y 或以上 Language: java Group Id: 請選擇有意思的域名,如果你用github,可以選 io.github.yourusername artifactId: 這個範例的名字,例如commandline Packaging type: 本次使用jar,日後若開發web 應用,可以使用war Java version: 17或以上 之後就不用選了。若你經官網起範例,你會得到一個zip檔,下載後解壓縮。若你使用vscode插件,最後插件會叫有一個位置儲存。它們都是最後也是會得到同一樣範例Java project。 你使用Vscode,Intellij打開,IDE都會自動辨識到它是java maven project,同時會顯示java和maven結構。道理上你用Intellij 應該可以無腦開始編譯(Community 或Ultimate版都可以), Vscode有安裝Extension Pack for Java也會開始自動編譯。不想麻煩,也可以試用Github Codespaces - java。Github Codespaces其實就是一個雲上的vscode,經網頁可以連到Github VM內的vscode,所以它也會有齊Extension Pack for Java等插件。 筆者最後也會上載已完成的範例,它也可以在Github Codespaces上以Java執行或繼續開發。 打開project中的pom.xml,它為我們添加了兩個很重要的lib org.springframework.boot spring-boot-starter ... ... org.springframework.boot spring-boot-maven-plugin spring-boot-starter是重中之重,它定義了怎樣動態地設定日後的其他lib,它是讓我們可以無腦設定的一個關鍵。(但若大家有很多客制化的設定,就要返撲歸真地逐個lib叫起)。 maven在預設情況下,只會負責編譯和打包目前的project原始碼。所有相關依賴(就是xml中的dependency),並不會自動包起。而spring-boot-maven-plugin,就是幫我們把相關依據都包在一起,讓你的jar可以獨立行起來。 註: 若大家在開發lib jar,並不是一個獨立執行的jar,也就是原始碼上沒有main函數,大家就不應該引用spring-boot-starter和spring-boot-maven-plugin。 我們繼續看其他原始碼,整個資料夾就像以下那樣。 . |-- HELP.md |-- pom.xml `-- src |-- main | |-- java | | `-- io | | `-- github | | `-- macauyeah | | `-- springboot | | `-- tutorial | | `-- commandline | | `-- CommandlineApplication.java | `-- resources | `-- application.properties `-- test `-- java `-- io `-- github `-- macauyeah `-- springboot `-- tutorial `-- commandline `-- CommandlineApplicationTests.java CommandlineApplication是我們有main函數的java class。我像可以經過IDE運行main又或者下指令mvn spring-boot:run來執行。 正式開始我們的Commandline開發 我們在CommandlineApplication.class中,加入新的程式碼,實現ApplicationRunner和它的函數run。 package io.github.macauyeah.springboot.tutorial.commandline; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; // other import @SpringBootApplication public class CommandlineApplication implements ApplicationRunner { static Logger LOG = LoggerFactory.getLogger(CommandlineApplication.class); public static void main(String[] args) { SpringApplication.run(CommandlineApplication.class, args); } @Override public void run(ApplicationArguments args) throws Exception { args.getOptionNames().stream().forEach(optionName -> { LOG.debug("option name:" + optionName); args.getOptionValues(optionName).forEach(optionValue -> { LOG.debug("option values:" + optionValue); }); }); LOG.debug("program end."); } // ... 這個run函數很直白,就是更好地演譯main中的String[] args。 但大家還要看清楚,這個main並沒有直接執行run。其實它是靠SpringApplication.run及@SpringBootApplication,跑一堆自動設定,最後因為傳入CommandlineApplication.class是一個Spring 可以處理的ApplicationRunner,所以才呼叫它的CommandlineApplication.run。 換個講法,如果今天做的是web應用,傳入去的就會是SpringBootServletInitializer,這個SpringBootServletInitializer也不一定跟main是同一個class。 如果大家有興趣,可以經過反編譯器,點入@SpringBootApplication看它的原始碼,你就可以看到它其實代表了很多自動化的東西。如果我們只做一些在同一個模組下生效的事情,《自動化》極大地降低了大家入門門檻。一般來講,如果大家不在意程式碼的複用度,比較少機會自行設定,自動化已經很有用。而隨著系統規模增加,多模組就慢慢地顯得重要,在大家了解完基本的Spring後,著者再從測試用途test case入手,為大家介紹如何手動設定。 Source Code Commandline Application

Spring Boot - Maven Cheat sheet

科技新知
MacauYeah・2024-01-12

基礎 刪除所有結果,全部重新編譯 mvn clean compile 跑起用Spring boot寫的main class,運行Spring boot context。 mvn spring-boot:run # or mvn clean compile spring-boot:run 執行測試用例,預設只會測試test資料夾下以某些命名規則的class(例如class名以Tests或Test結尾的class,其他命名規則筆者未有能力一一驗證) mvn test # or mvn clean compile test 多Profile、多組件、多測試 使用-P指定編譯時的選用pom.xml中的project.profiles.profile參數。也可以用此來傳遞到spring profile,使得編譯後的spring war預設選擇特定profile。 mvn clean compile -PmvnProfile # or mvn clean compile spring-boot:run -PmvnProfile 使用-pl限定mvn指令只對某個子組件生效,但有時候子組件之間也有引用關係,所以需要再額外加上-am參數(--also-make) mvn clean compile spring-boot:run -pl SUBMODULE_NAME -am 使用-Dtest=限定只執行某個class的測試用例,或單個測試函數。(可以無視class名的命名規則) mvn test -Dtest=TEST_CLASS_NAME # or mvn test -Dtest=TEST_CLASS_NAME#TES_METHOD_NAME 若屬於多組件情況下,其他子模組找不到同樣名稱的測試,會測試失敗。需要再加上-Dsurefire.failIfNoSpecifiedTests=false mvn test -pl SUBMODULE_NAME -am -Dtest=TEST_CLASS_NAME -Dsurefire.failIfNoSpecifiedTests=false # or mvn test -pl SUBMODULE_NAME -am -Dtest=TEST_CLASS_NAME#TES_METHOD_NAME -Dsurefire.failIfNoSpecifiedTests=false 打包 在本機電腦中,把java變成jar或者war。通常用於自行發佈的環境中。 mvn package 有時特定Profile沒法成功執行測試用例,或者你認為有些測試問題不影響使用,需要跳過package中的test。 mvn package -Dmaven.test.skip=true # won't compile test folder mvn package -DskipTests=true # compile, but won't run 例外情況 強行把一個第三方jar,種到本機電腦中的.m2/repository # copy from https://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html mvn install:install-file -Dfile= -DgroupId= -DartifactId= -Dversio

街霸六的元宇宙大笪地對戰大廳

手機‧電玩
MacauYeah・2023-12-26

上期就為大家介紹了Modern Mode的新系統。今期就再繼續為大家介紹新的對戰系統。(上期連結: https://lifemag.cyberctm.com/zh_TW/blog/macauyeah/13954 ) 找個陪練很重要 現在街霸五中,網上對戰不外乎是隨機的排名賽、隨機的友誼賽、邀請特定網友在對戰大廳輪流對賽。看下去沒有什麼大問題對不對? 實質上就是一切都很隨機,而對戰大廳很少人懂得運用。 街霸六中一個很重要的改動,就是在隨機的排名賽和友誼賽,加入賽後自訂賽制的玩法。排名賽上遇到五五波的對手,想跟它再打幾場? 可以,馬上進入自訂友誼賽,打個夠。這個改動很必要,在過去的日子裏,特發跟不同人隨便打兩三場,根本不知道應對手段;跟同一個對手來回對策,才會慢慢知道輸在哪裏,有沒有什麼地方是博奕的盲點。猜包剪揼連輸三場,你覺得是對手運氣上壓制你,但連猜十場你也輸,就代表你真的被對方看透。若在排名賽上沒有碰到想賽後重複對戰的對手,遊戲商亦很佛心地重現了一個類似大笪地的對戰大廳,讓你可以在元宇宙坐在一個虛疑街機框下,等待那些跟你一樣不太介意分數,等級差不多、但只想連續思考對策的朋友。 在過去街霸五中,隨機的友誼賽和對戰大廳,對筆者這些低端玩家來說實在沒有什麼用途。友誼賽實力差距很大,基本上就是老手開發新帳號來碾壓新手的地方。對戰大廳則是連線品質參差問題,見到高分的不敢進去,低分的基本上網路卡到不能玩。當時最能遇到熟練度差不多的對手,就只有排名戰,但同一名對手的排名戰機會不多,然後大家又非常在意分數的上上落落,所以當時的對戰實在稱不上快樂。 對比這個情況,街霸六就變得放鬆很多,大家更容易地在大笪地中找到差不多的對手陪練,不用計較分數。大笪地的成功,並不是單純地因為可以自定義對戰,它的連線品質提高,也是穩定在線玩家數量的一大原因。 其他重要改進 單從字文上,或許你覺得整個街霸六都是換湯不換藥。但筆者很負責任的說,它是在硬技術和設計上,都做到很大的改進。雖然不能稱為劃時代的改進,但有了它們,遊戲更友善: 對戰系統可以全平台跨平台對戰,PS、XBox、PC可以大混戰。你能匹配到的有效在線玩家變多了。 提高連線品質,現在那怕是Steam Deck連上Wifi也能網上進行對戰,大家也不那麼懼怕延遲的問題。 大笪地加入社交元素,你還可以通過故事模式,解鎖自定義格鬥技,在非正式的對戰中跟別人惡攪對戰。 練習模式加入極重要的幀數顯示,大家更有條件地自定義練習情境。 玩家們已經極少再需要上網查幀數資料,除了無敵幀需要上網查以外,其他的自行試就好。 官方在練習模式中預錄制了一些情境練習,例如對空、破防、解投等,讓大家可以直接練。但在解投的情境中,更讓筆者明白這遊戲有多麼的爾虞我詐。 這兩期講的東西,都是Capcom針對核心遊戲元素的多項精進。吸收了街霸五的技術和策略上的失敗,街霸六就從軟硬兩方向大改進。Modern Mode在直正意義上可以讓新手入門,但又不致於無腦遊戲。對戰機制,可以讓大家不只關注排名賽,更大地去提供實戰環境讓大家實驗自己的PvP策略。

格鬥新老手也很友好的街霸六 | MORDEN MODE

手機‧電玩
MacauYeah・2023-12-22

街霸六已經出了半年有多,但筆者也是近期在購買steam deck 後才加入街霸六。一玩就實在愛不惜手,特別是steam deck的加持,讓筆者可以在午休時間大方地玩。 可能好多網媒都有介紹它,亦十分讚賞它的單機故事模式。但對於沒有時間筆者來說,慢慢跟故事拜師成長,解鎖不用招式,實在讓筆者耐不下心。而真正讓筆者感到友好的,是它的操作系統和對戰系統,讓它可以達到老手有老手的開心,新人有新人的快樂。今期,就升為大家介紹它新的操作系統。 MORDEN MODE 經常有人誤會,格鬥遊戲玩的是連招,如果人人都可以自動連招,根本就是小朋友遊戲,拿不上大台,也不會有舉辦比賽的價值。所以有一些人,會看少「任天堂明星大亂鬥」的價值,因為不論多新手,都可以打出基本combo。但說實在,它是街霸6出來以前,最有條件同時允許新老手同樂的遊戲。 格鬥遊戲,什至其他競技遊戲,對於同等操作熟練度的選手來說,他們的比拼是應對策略。而相對公平的競技遊戲,應對策略就是很像是博弈,沒有100%安全的招,就像包剪揼一樣,可以有特定的對應策略。格鬥遊戲與包剪揼最大的差異,是在足夠熟練和專注的情況下,雙方是有條件作出對策的,所以格鬥遊戲不完全是盲猜。而過去最大的問題,就是格鬥遊戲太難讓新手學會博奕,外人看去就是combo為王,搓招難,就放棄吧。 街霸五在容納新手方面,其實都下過很多努力,包括減少每個角色招式數量,較寬鬆的combo 輸入時間,提供可錄影、重播、幀數檢視的練習模式。可惜搓招門檻始終也是讓很外行人放棄的原因。而街霸六,則提出一個很多人都提過的做法,但沒有廠商真的成功過的做法,那就是一鍵搓招與傳統搓招共存的做法。 玩家可以在對戰前,選擇新的【Modern Mode】(現代模式),然後享受以下功能便利。 簡易使出必殺技。通過 單一方向鍵+SP鍵使出不同的【必殺技】 單一方向鍵+SP+AUTO鍵使出不同的【OD必殺技】 單一方向鍵+SP+重攻擊鍵使出不同的【超必殺技】 攻擊力比較搓招或【Classic Mode】有下調 簡單使出連招。通過 不同的單一攻擊鍵+AUTO鍵 連打 使出三套特定的連技 攻擊力比較搓招或【Classic Mode】有下調 若要使用【輕、中、重必殺技】,仍需要使用傳統的搓招方式。 攻擊力回到100%。 對比【Classic Mode】,【Modern Mode】有些拳腳攻擊、必殺技的差異化版本無法使用。 例如Luke在MORDEN MODE中只可以使出後重拳,沒有後重腳。 例如Ryun在MORDEN MODE中只可以使出中旋風腿,沒有輕、重版本。 但依然可以打出大部份的搓招 + 連技。 當然,玩家可以選擇【Classic Mode】(傳統模式),一切按鍵都跟過去一樣,有輕、中、重之分。 筆者最欣賞的,就是這個【Modern Mode】的出現。因為它可以降底學習成功,但又不失公平性,讓新、老朋友可以打出一場有博弈味道的友誼賽。例如正面跳入攻擊,在過去的高端對局中,只能作為突襲的戰術,不能隨便跳。但在低端對局,正面跳入攻擊就經常是老手欺負新手的一個有效途徑。新手想要對策正面跳入,必需經過一個搓招,才能使用昇龍拳來穩定對空。但在【Modern Mode】,簡單一鍵昇龍,就可以代解威脅,雖然攻擊力變底,但正面跳入不能當是賴招使用,讓大家回到思考何時跳入的博弈問題中。 如果說【Modern Mode】只為新手當做過渡期而使用的模式,那就真的小看了它的設定。在遊戲正式推出後,意外地出現高端對局中使用【Modern Mode】,因為它可以提供快更的反應速度,可以彌補一些角色上的短處。 對筆者來講,【Modern Mode】最重要的並不是簡易必殺技。因為追求傷害量的情況下,搓招很必要的。筆者看上它的原因是它能有效地簡化Drive Rush的輸入,令到筆者可以更易地通過【延長攻擊手段】最得反應的時間。一般讀者可能不明白進攻方為何要反應,不是防守方才要做反應嗎? 在格鬥類遊戲中,大部份時間防守就是死按一個【後】或【下後】鍵就足夠,在街霸六當中,更因為有Over Drive、Drive Impact等系統,防守方有更多博奕下的對策方案。怎樣打穿敵人的防守,是進攻方要用腦的事,更因為如此,有些人選擇打後手,等對方出錯,反而很有利。 但進攻才是格鬥遊戲的重點,要走向高分層次,就必需要跨越【Hit Confirm】的障礙。經過【Hit Confirm】,若然連招中途就發現打不中對手,就以一個更安全的攻擊收尾;若然打中了,做使用更多資源打出更高傷害。提高自己【Hit Confirm】的反應能力,基本就是跟年齡作對。所以筆者就需要經過其他手段,例如:Drive Rush來延長自己的攻擊節奏,好讓反應不來的筆者有更多時間選擇打安全招還是全力攻擊。 下期,筆者會再聊一聊對戰機制的改進

找一個可以私有化的協作平台

科技新知
MacauYeah・2023-12-19

在現今這個網路為王的年代,大部份文書等編輯工作都可以在Google Drive, One Drive那邊多人協作。唯一的問題是,你是否考慮資料保密問題。 一些開放資料,放在雲端上,故然無問題;個人用資料,就自己為自己負上保密責任。但作為一家公司,把自家客戶的資料放在Google Drive、One Drive上,你又會否覺得足夠保密? 不放在這些協作平台上,改為自購一個NAS File Server,把共享檔案都放進去,這樣又足夠方便嗎?現在File Server最大的問題,是無法提供同時協作編輯的功能,想在同一個檔案,多人同時更新不同的部份,是不可能的。 Etherpad-lite 如果大家只需要一起寫文字稿,可以試用Etherpad-lite https://github.com/ether/etherpad-lite 。 筆者試用過,它提供實時協作,其他人的更改可以即時顯示,也有一些基本的排版功能。缺點是lite版沒有好好處理大量的資料問題,一次過複制貼上大量文稿的話,會出現網路問題。 NOCODB 如果大家需要的是試算表,可以試用NOCODB https://github.com/nocodb/nocodb 。它強大的地方,是可以匯入CSV, Excel,做欄位搜尋。老實講,這些功能,對於一個IT人來說,隨便安裝一個資料庫,例如:MySQL、 MSSQL, 都可以做到匯入結構性資料,並供多人操作資料。但對於普通用戶來講,要學會操作SQL語言,實在有難度。而經過nocodb之後,可以把MySQL等轉化為常見的試算表型式,實在驚喜。而且,它也能提供一些簡單的填表方式(Google Form)

Switch / Steam Deck / Mobile 使用體驗大比拼 (三)

手機‧電玩
MacauYeah・2023-12-14

上兩期,筆者從機身重量、續航性兩方面,對於遊戲機身便攜性的影響,今期最後一期,就從穩定性方面去討論,最後再做一個綜合影響。 沒有對比也就沒有傷害 - Mobile - Smart Phone 筆者所講的穩定性,其實就是正常運行一個遊戲,不會出現閃退的情況,讓你可以正正常常玩完一款遊戲。但因為Mobile原本是多用途機器,你玩著玩著,可以就要跳出遊戲回覆信息,但再次回到遊戲後,能不能正常運行的不知道。 大部份iOS遊戲,因為舊iphone機能限制,基本上跳出去後,都因為不夠RAM,回來後遊戲會重置。除非你打死不切換,否則一款遊戲沒有頻繁auto save功能,根本玩不下去。Android可能會好一點,有不同機型可以選擇,多一點RAM總是安全一點。 強行地用Linux運行Windows的黑科技 - Steam Deck 老實說,Windows已經不夠穩定,用Linux運行Windows Game,會比較穩定嗎?不過最幸運的是,Steam Deck有技術支援,更有社群支援,各遊戲經過Steam官方驗證,連續遊玩下閃退情況都很少。不穩定的原因,反而是Steam Deck主機本身。 在筆者遊玩的經驗中,待機後再打開,有一定機會率會整個遊戲閃退。這些問題在遊玩大作,特別是3A大作,會引來一個很不愉快的體驗。因為它們的auto save位置點一般都是以情節點來做考量,而以上班族來講,三步一待機的使用情境也很常見,那麼觸發閃退的機會率就很高。某次啟動會隨機引起閃退遊戲,真的欲哭無淚。 筆者也翻查過網上的資料,一年多前就有這個問題存在,而官方亦無法根治。筆者在寫稿的途中,還在測試坊間一些可能的補救方式,但因為時間不長,不敢說這問題是可以解決的。 穩定發揮 - Switch Switch在穩定性真的無可挑剔,多次待機後都沒有太多問題。完全貼合它的市場定位:在家可以隨時在電視玩,出外也可以四處走。隨時隨地停,隨時隨地再開。最多最多都是遊玩實體卡帶時,因為接觸不良而閃退。但這些不可避免的,因為實體卡始終是物理型態存在,跟著Switch四處奔波,難免會出問題。但下載數位版,存放於SD卡就不會有閃退。至少SD卡不會像實體卡會經常替換,所以出問題的機會也較少。 綜合體驗 其實討論了幾個方面,筆者都從是省心遊玩的角度出發去討論。 Mobile在裝備上會最少煩惱,想最輕鬆出問,這個是不二選擇,但考慮玩非課金類遊戲就最沒有保障。 Steam Deck優點是移動堡壘,若你玩的是高性能需求的遊戲,你只能選它。但想隨時玩就未必做得到。 Switch 在重量和穩定性上面最有優勢,考量延續性體驗,這個是首選。

Switch / Steam Deck / Mobile 使用體驗大比拼 (二)

手機‧電玩
MacauYeah・2023-12-12

上期,筆者為大家簡介機身重量對於遊戲機身便攜性的影響,今期,繼續從續航性方面去討論對於便攜性的影響。 依然是王者 - Mobile - Smart Phone 就如同重量一樣,續航性的理論值,依然是Mobile最優勝。單看電池容量,其實無能說手機最優,就算現在的iphone15,電池容量其實也比Switch, Steam Deck要低。能比得上的,可能只有iphone 15 Pro。但若果連同充電的方便性,Mobile是最易邊玩邊充的。一般來講,如果不以全效能去運行遊戲,Mobile是的電量是相當安心的。 但也如同重量一樣,續航性理論值,是Mobile最好,但不是安心長期遊玩的媒介。 一來,Mobile,一般都是用作社交通訊用,它的電量是分享給一整天使用的。一不小心遊戲時間長了,那天晚上可能就沒有電話用。除非大家想隨身攜帶奶媽(充電寶),但這是用重量來換取遊戲時間。所以筆者不會把它當作首選。 巨無霸 - Steam Deck 空有其名的巨無霸。在電池容量上,它是三者中最大的一款,但因為它對照的遊戲效能,是PS4/5、XBox One/X/S、PC等的大作上面。那些主機大作,對電量是極其大需求的,單憑散熱風篇的聲音,你就知道不秒。一般遊戲的預設畫面品質,就只夠1-2小時的遊戲。實在想延長,就必需要下調Frame Rate或是畫面品質。 玩消耗戰必選的設備 - Switch Switch預設電量不多,但因為畫面其實也不能要求太多,所以它的續航性不低。相比Mobile,Switch就是完完全全的純遊玩設備,也不需要筆者去刻意規劃電量。沒電?關機就好。待機也是單純的待機,不需要什麼定期連上Wifi、GPS,藍牙亦單純地為耳機及手柄使用。想更省電,就待機前就全數關掉就好。 綜合體驗 老實說,看完重量及續航性之後,Steam Deck主打市場明顯不是遊戲掌機,而是一台可以搬走的PC。你可以方便地整台電腦帶走,從自己家到公司,從公司去親友家。它的體型,比主機和Notebook要細,它的售價,也比一台Notebook要便宜。但想拿著玩?可能不會特別開心。 Mobile在重量及續航性綜合考量,其實很有競爭力。不過考量用途問題,否則你也很難安心用Mobile來玩遊戲。 老任的Switch,重量及續航性在初推出市場之際,筆者都不看好。但實用和對比之後,畫面效能和續航性控制得還不錯。

Lambda 表達式之可讀性

科技新知
MacauYeah・2023-11-24

Java作為一個真OOP物件導向的程式,在設計和編寫上是很嚴謹,什至是囉嗦的程度。近年很多Programmer因為各種原因,都放棄Java跳船去其他語言。 Javascript是其中一個很多人的選擇,因為Javascript有nodejs的加持,在Web世界下,可以同時走frontend、backend路線。而Javacript亦有一個很明顯的特性,就是大部份的library都以callback的型式出現。另外,Javascript也讓很多人覺得很簡潔,這除了是因為它沒有強型態的規限外,另一個原因也是因為有callback的大量使用。 Function Pointer 其實callback,籠統一點講就是在一個function A傳入另一個function pointer B。而編寫function A的作者,並初期並不知道function pointer B的實際操作會是什麼。A作者只是強調在特別定時候,它就會使用這個function pointer B。而這種把function pointer 傳來傳去的做法,就可以看成是Functional Programming的基礎。 Functional Programming除了把function pointer 當成是一等公民以外,還有很多附加要求,例如: Pure Function: 它只會使用到自己的Local Variable本地變數,這樣它的作用域就鎖死在Function內部,就不會有副作用。 傳統的OOP,Class中不少變數會以Class Attribute型式存在,雖然它們可能是private attribute,但還是獨立於Function外,這樣各Function的操作,都要靠作者好好地記著Class Attribute的狀態。 Nested Functions: 與普通程式語言類似,很多情況下都需要local variable,而Function Programming要足夠好用的話,就需要彈性地在function裏定義local function pointer。 Java Lambda 表達式 其實從Java 8開始,就有提供Lambda表達式,這是一個可以制作匿名function pointer的方法。所以硬要講,Java也可以做Functional Programming。 但必需要盡早強調的是,Java經常性地使用class attribute,它們很多時候都會引申請狀態的概念。即是在它們必需經過特定步驟後,class attribute才會有特定的意義。也就是Lambda表達式想保持Pure Function的特性,它可以使用的時期就有很大限制。 但我們還有必要使用Lambda嗎? 以筆者的經驗來講,它還是有作用的,特別在於它可以改善Class Function的閱讀性。 例如下面一個Java Class。它是一個工廠,提供一個服務可以生產一堆車。那些車而需要經過特定檢測,才能推出。 public class Factory { // ex1 public static List generateListOfCarByForLoop() { List tempCars = new ArrayList(); // many other logic // many other logic // many other logic List passTestCars = new ArrayList(); for (Car car : tempCars) { if (car.getWheels().size() == 4) { // many other check logics // many other check logics // many other check logics passTestCars.add(car); } } return passTestCars; } } 中間的for loop可以用lambda來改寫。 // ex2 public static List generateListOfCarByLamda() { List cars = new ArrayList(); // many other logic // many other logic // many other logic cars = cars.stream().filter((car) -> { if (car.getWheels().size() == 4) { // many other check logics // many other check logics // many other check logics return true; } return false; }).toList(); return cars; } 有人會說,上述ex2只是形式上改變了,沒有特別易讀。就像ex3這樣,把特定邏輯抽成獨立function,才是真正的易讀,對嗎? // ex3 public static List generateListOfCarByForLoopFunction() { List tempCars = new ArrayList(); // many other logic // many other logic // many other logic List passTestCars = filterCarsByWheelsSize(tempCars, 4); return passTestCars; } private static List filterCarsByWheelsSize(List originalList, int targetSize) { List passTestCars = new ArrayList(); for (Car car : originalList) { if (car.getWheels().size() == targetSize) { // many other check logics // many other check logics // many other check logics passTestCars.add(car); } } return passTestCars; } 上述ex3是一個有效的改進。如果大家不計較傳入參數的先後順序及交互影響的話,就已經很足夠。 但如果大家對於多參數的解讀又怎樣? private static List someotherfunction(List cars, List wheels) 大家又會不會突然停住,想想到底是cars影響wheels,還是wheels影響cars? 對於多參數的function來講,相互影響就會越來越多,但使用Lambda的話,可以針對性地表達這是一個Predicate Lambda。 // ex4 public static List generateListOfCarByLamdaComposition() { List cars = new ArrayList(); // many other logic // many other logic // many other logic List wheels = new ArrayList(4); cars = cars.stream().filter( filterCarByWheelSizePredicate(wheels) ).toList(); return cars; } private static Predicate filterCarByWheelSizePredicate(List wheels){ return (car) -> { if (car.getWheels().size() == wheels.size()) { // many other check logics // many other check logics // many other check logics return true; } return false; }; } 就最後的ex4版本,可以很明確的知道是cars被Predicate所作用。 如果大家還有其他使用Lambda的明顯好處,也可以一起來Github分享大家的Code

Switch / Steam Deck / Mobile 使用體驗大比拼 (一)

手機‧電玩
MacauYeah・2023-11-21

還記得很早開Blog之初,筆者一直都集中於主機遊戲評論。筆者不想放棄主機的主要原因是移動端難有一個款可以提供高品質的遊戲,不論PVE類型機還是PVP類型。 但逐漸地,各種遊玩動機,例如個人作息、方便性、遊戲品質,都有了很大的改變,經過漫長的時間,筆者最後亦都完全放棄主機,進入Portable Gaming時代。 筆者第一台便攜型機,就是PSV,不過因為已經停產,聊太多也沒有重要意義。但重提它的原因,主要一些操作體驗需要拿來做對比。那時的PSV,左右肩健各有一個,也就就沒有所謂的L2, R2 (ZL, ZR),左右有類比搖桿L3, R3,所以當時完全是一個比PSP的進階替代品。筆者也對PSV有很高評價,因為它的重量、續航性、軟件穩定性,都對得起筆者的期待。亦因此,筆者對於第一期的Switch,都認真失望。不過Switch最後卻成為筆者現今最支持的平台,這亦主要是因為它的重量、續航性、軟硬件穩定性。 今期算是第一期,筆者就先從Switch、Steam Deck、Mobile的重量、型狀,來影響它們的便攜性。也因為一些外置設備影響,重量、續航性、軟硬件穩定性自己都會互相影響。 最輕的一定別無他選 - Mobile 各大手機,在成型設計上,沒有預設手抦,所以一定是最輕的。但前題是你的遊戲對捽MON(搓玻璃)有做優化。現在很多競技手遊,已經發展出一套相對可以接受的捽MON設計,一些跨平台移植的PVE遊戲,亦都盡最大努力地加入附助機制援解捽MON下的不便。 但但但但,如果你需要真的最佳化操作體驗,Mobile配手柄的話,就不一定是最輕的選擇。在最入門的情況下,買一個很經濟的手柄,配上支架,你就可以把手柄、手機一起拿著玩。但問題是這會直接影響重量。最入門的選擇,手柄的重量通常都不輕。如果你配上一體式支架,手柄托著手機,就完完全全可以重過一台Swtich。有一些極致的手柄,可以很輕,合來會比Switch還輕。但這種很柄依然還有一個很大的天敵,就是不能與手機套共存。每次使用手柄,都要拆一次手機套。而手機套的設計,通常都是易裝難拆(這樣才能保證不便隨便跌出來),所以那怕你的手柄多輕,但每次你都要東攪西攪,便㩦性大打折扣。 結論是,若果你需要輕,而且即開即玩,你就要接受捽MON的選擇。你需要精準操作,就不能要求即開即玩。 巨無霸 - Steam Deck 如果大家有一直接關於外文媒體,有時候你會看到它們評價Steam Deck的重量為:「沒有你想像的那麼重」。 That is fake!!!!!!! 老實說「沒有你想像的那麼重」,只能在你沒有比較對像時才能說得出口。在配上外設手柄的手機情況下,我已經覺得重,怎麼可能這台Steam Deck不重?抱著這台Steam Deck到處走,真的不容易。你想通勤期間想拿出來玩玩而整天背著他,不能說是很化算。你連續拿著玩個三十分鐘,也不是很好受。 不過筆者依然會覺得它有存在價值,主要是它可以帶著PS4以上的品質遊戲到處走,那些重量,是可以接受的。魂系遊戲、Capcom動作遊戲,也只有Steam Deck才能提供。想到處可以刷一場爽快的動作遊戲,有60fps,聲畫特效都打開,那是多麼美好的一回事。更重要的是,因為快餐打個兩、三場,也不過十五分鐘,電量不是筆者最大的問題。它預設的手柄按鍵也夠用。所以筆都會把它排在手機更高的評價。(據說其他Windows掌機,更重、更耗電,很難想像它們還是走便攜路線) 結論:重,但可以滿足你的聲畫需求。 中規中矩 - Switch Swich在預設配件的性況下,不重,除非你拿著玩超過一小時。Switch平常最多人投訴的是Joy-Con手感問題。筆者覺得這是官方的一個合理選擇,對比PSV,什至更舊的設備,Joy-Con不算手感差。最影響體驗的,其實是它易壞的問題。大家聽得最多的,是它搖桿的漂移問題。但其實還不止,手柄充電、接觸配對,都是可能出現問題。但老實講,手柄屬於消耗品,再加上Jon-Coy的內部的設計比同等體量的手柄要複雜,如果兩年換一套Joy-Con,不能說是不合理的。 扣除Joy-Con的成本差異性後,基本上它的重量很適合隨身攜帶,而且手感可以接受,它也有齊各個功能健、陀螺儀,在極致的體形下做出全功能的手柄,玩動作遊戲也是可以接受的。加下可拆性,就算壞了手柄,不用整台送修也是一個優點,找第三方手柄也是一個選擇。 結論,在於通勤的情況下,在原裝的情況下,就極快地從待機到進入遊戲,那是極重要的一件事。而且重量不重,每次帶著四圍走都不是問題,這也是它的面對碎片化時間之下,還能有高開機率的原因。 (最後筆者選了一套重量、價錢都合理的第三方手柄,它主要是不能當成無線手柄使用。但價錢便宜,而且手感更好,而且重量不會暴升。) 重量的綜合體驗 由可接受的重量範圍,Switch的便攜性最高,其次就是mobile,但在衡量重和按鍵的操作性,Steam deck 比mobile讓筆者更有遊玩的意欲。 下期,筆者會再從續航性方面去討論對於便攜性的影響。

澳門IT教育 | 到底現在缺什麼?

科技新知
MacauYeah・2023-11-10

筆者最近跟朋友聊天,也剛好在進修,談到一些IT知識的傳播問題。進修課的導師,或更廣泛的教育機構,都很積極地宣傳,人必需經常upgrade自己,接受新知識。而不同的導師,就是用不同的方式,去介紹新知識。而最普偏的知識傳播方式,就是人與人之間有溝通。 溝通,好像好實制好有效,對不對? 對。溝通是很易的,不過掌握知識,是很難的。所以阻礙大部份人持續進修的原因,其實是實踐知識的成本,包括時間、空間、金錢。但最近在接觸一些大公司的官方課程後,至少在software上,都有遠端的實驗環境。 Cisco 在多年前就有提供Packer Tracer,可以模擬一些網路情況。雖然不多,但至少可以實作打command。Oracle、SQL Server,現在除了提供免費的開發版本多,還有提供docker版本,希望把本地初次安裝的問題也解決了。Oracle的官方班,還會提供雲端的預安裝版本,你就可以省下本機資源做其他整合測試。寫程式方面,在早期,為推廣Web Frontend開發方面,已經有JSFiddle,很多朋友要試code,要做POC,都可以直接跑起程式看效果。這些,都是推廣IT知識的良好切入方式。 近年多得VM、Docker、VSCode,即使Web Backend,什至是Binary program,也完全可以提供遠端的實驗環境。良心的Github、GitPod,還有提供一定量免費的VM、Docker服務,你想把整個IDE放上Cloud,真的不再用像筆者以前要自己研究的CodeServer,用它提供的就好。不過遠端的環境還是有限制,例如你需要模擬硬件,或是需要很健全的測試環境,例如frontend backend cookie domain rewirte,又或是需要健全的除錯工具,都還是要等等。 好多事,雖然不能馬上上production,但look and feel,是吸引新朋友加入的重要關口。現今澳門IT的教育發展,就是總是留存在實體課,去指定的教室讀者PT教材,使用指定機器。若導師準備充足,就還好,可以順利實習,邊聽講解邊做實驗。頂多就是上課時間、地點不夠便利。但預者有一些老師不備課,食老本,Lab沒有提前預習,做live demo時才錯誤百,修正錯誤的時間成本很高。若要想更多人持續接受新事物,就必需要提供足夠多的可以實操的Lab,而且要可以自行重複。 對於澳門IT教育機構,希望可以提供更多的網上資源,讓學生可以解放地點和機器的限制。對於現在的IT/Software的從業員,希望大家都可以擁抱Docker/Linux Container,這樣才能最低成本地試用新事物。

Spring官方教學 | Spring Certified Professional 2023

科技新知
MacauYeah・2023-11-07

筆者作為一個網頁程式開發者,使用Spring Boot開發已經有六年。從當初Spring Boot 1.x開始,查看官方Tutorial七零八落,慢慢摸索,到大改版升級2.x,都碰過不少釘。最近Spring Boot亦要升級到3.x,正式進入Java 17時代。筆者亦不斷Update自己,保持程式於一個可支援的狀態。 相對以前,現在入門Spring Boot已經比1.x年代輕鬆很多。主要前些年某些網頁開發的概念,例如REST API,已經深入行業,大家不再糾結要走傳統MVC還是RESTFul API,也使得Spring Boot這樣的Framework,可以有一個受眾比較廣的統一入門教學。 筆者最近也正式參與Spring Academy的官方教學,好好地厘清一些概念。 官方連結 https://spring.academy/paths/spring-certified-professional-2023 在讀過官方的幾個章節後,真的覺得很適合有興趣的人去看一看。主要是因為: 官方以一個經典例子作為切為點,教學REST API,In Memroy Database。它還介紹了一些簡易的HTTP Code Standard、Test Case。真的比其他民間教學更有系統性。 提供一個可以在網頁上就實驗到的Lab實習環境。那是極為重要的一件事,因為九成人,在setup java 及library dependency (maven, gradle)時,都碰釘到直接放棄。有時是因為公司工作環境比較有要求,並不允許你使用一鍵安裝的java套件及它的library dependency;有時則因為網路安全,java把你公司的firewall當作a man in the middle (MITM) attack擋了,也有時是因為你公司的firewall把java擋了。Spring Academy在一個遠端的https網頁提供實驗環境,真的比本機開發要易入門很多。 Spring Academy可要多謝vscode、code-server,及其他VM、Container技術。 在真實環境中,筆者也有自己的code-server,打包java / os cert等等,盡量減少firewall問題。 因為官方教學持續以Spring boot的最新版本作為教材,它更新的速度總比民間要快。只是官方的教學不會全面覆蓋到所有Spring project。如果大家作為Web入門的話,還是有推薦的。 在Spring boot 3.x當中,因為要求Java 版本至少為17以上,那些教材也有使用一些Java 17的新語法(Syntax),實在也令人驚喜。 基本上Java 17現在可以簡化getter / setter / switch statement,這些在開發Web的環境下都是很重複的事。在Java 11或以前,只能經過IDE去生成getter / setter等,但似始都有會一大堆Code佔據你的頁面。 官方教學及Lab環境暫時免費,除非大家很在意的修業證書,不然都可以自由免費看。 官方教學真的值得一看,雖然距離真正開發還差很遠,筆者日後若有條件,會針對官方沒有提及的內容作補充,分享一些在技術面上所需求的最少可運行配置。

Coding | Test Case 值得寫嗎?

科技新知
MacauYeah・2023-11-02

很多做軟件開發的朋友,其實都會聽過Test-driven的開發模式。就像Scrum一樣,名氣很高,但試過的人很少。為何會這樣呢?筆者認為,並非開發者懶,而是編寫Test Case的難度真的高。對比開發程式本身的成本,寫Test Case的時間/學習成本一樣高。 造成這些高成本的原因很多。一來是因為開發者並不像過往一樣,慢慢從零寫程式,一般都應用Framework去預構建一些東西,例如打包Database connection pool,Dependency injection。Framework是好用的,但就令你要模擬Mock up特定資源,變得越來越複雜。所以一般中、小型開發,都鮮有人懂得做Test Case(除了大神獨立開發者外)。筆者對於Spring boot等Framework,都摸索了很久,才能模擬一些特定資源。但Framework一更新,就很多部份都要重寫。所以筆者沒有很強調要做Test Case,因為成本認真大。 最近,在摸清一些test case 基本concept後,筆者又重新開始嘗試編寫test case。以下假設用的是object oriented programming 在開發自己的class,為每個public function,都寫test case。很多IDE, 都有提供相關自動生成test case function signature的功能(就是為你的目標function,起一個只有外框的test function。)vscode雖然不是原生支援java,但只安裝基本的java test package,就可以達到同樣效果。 在不依靠framework的情況下,自己class要『引用』的其他class object,不要經過自己使用new來生成object。全部經set function來傳入你要引用的class object。除非你的class是作為Factory Pattern(工商模式)生產某些object,不然你就不會再有new字眼。 在為自己class編寫test case時,就會可以模擬被『引用』Object的行為。這個object在傳統上可以使用oop中的interface類型來達到模擬又不會影響到原結構的做法。實在不想做interface,java還可以用mackito 這個libraray來硬改Object的行為。 同理,自己class要『引用』一些外部資源,那些設定資源的config,都應該要set function傳入。這樣你在test case中才能起一個臨時的模擬外部資源。 在不使用framework的情況,要全數去自行模擬,當然很痛苦,但至少你可以做一些很簡單的測試。 在使用framework的情況下,還有些教學都是教你mockito繼續模疑。但這會是很痛苦的,因為這樣叫做unit test,單元測試,你要模擬所有東西。在折衷的情況下,應該底層元件做unit test,但上層的元件就做integration test,整合測試。 在做integration test時,就差不多等同使用framework行起部份或必要的資源。而那些必要資源,可能指是的database service, network service。我們可以在test case中設立不同的config,從而把framework指向一些備用資源。 Database好貴,腦細不會付錢set up多一套,自己電腦不夠強,也不能跑起多個開發用Database。好在還有h2 database可以幫你,它是memory可以操作的。只要你的framework支緩就好。在初次使用Framework時,你總會覺得為何Database層要設得這些抽像,其實為的就是讓你可以隨時換Database。不論做測試還是做移植,都會少很多問題。 模擬Network service還是沒有銀彈,要麼就mockito硬改行為,要麼就是提供一套測試用service。筆者曾經為模擬別人的Network Http API,也花了相當時間自己建立dummy server,提供模擬效果。無論dummy的效果有多假,有多局限,例如if id == 1,always return true,也是有一定價值。當你做source code refactoring (重構),又或是做framework升級時,還是讓你可以安心一點。