顯示具有 筆記 標籤的文章。 顯示所有文章
顯示具有 筆記 標籤的文章。 顯示所有文章
2020年9月20日 星期日

[筆記] Round() 不一定是四捨五入

  使用程式語言函式庫提供的 `Round()` 之類的函式對數值做四捨五入時,要小心它的捨入結果可能不是所預期的四捨五入,因而踩到雷。
來看看 Python 的:

來看看 JavaScript 的:

最後看看 C# 的:

可以發現,對 1.5 跟 3.5 都是四捨五入到 2 與 4,可是在 Python 與 C# 中,對 2.5 的結果卻是 2。

2020年9月16日 星期三

[筆記] Unity3D - 繼承類別不要有與基礎類別同名的屬性

  最近在寫遊戲時遭遇一點困難:在繼承基礎類別時,需要將其附屬的資料類別一併繼承,而在建立繼承類別的實體後,遇到初始化基礎類別的資料類別的問題,原因只是因為兩者的欄位 (field) 同名。有問題的程式碼像這樣:
class Character : MonoBehaviour
{
    protected CharacterData data;

    ...
}

class CharacterData : ScriptableObject
{
    public float movingVelocity = 10.0f;
    public float rotatingVelocity = 10.0f;
}

class Player : Character
{
    public new PlayerData data;

    private void Start()
    {
        base.data = data;
    }

    ...
}

[CreateAssetMenu(fileName = "PlayerData",
    menuName = "Scriptable Object/PlayerData", order = 1)]
class PlayerData : CharacterData
{
    public float firingPeriod = 0.1f;
}
Unity 在編譯後會出現錯誤訊息,"The same field name is serialized multiple times in the class or its parent class. This is not supported: Base(Player) data":

即使可以忽略錯誤訊息將 PlayerData 的 scriptable object 設給 data 欄位:
但只要重新編譯後,該欄位還是會變回 None,即使為基礎類別的 data 加上 [HideInInspector] 的性質。因為 Unity 無法為一個物件同名的欄位初始化多次(一次是 Player 裡的 data,一次是繼承的 Character 裡的 data)。
2020年7月12日 星期日

[筆記] API 設計概念 — 下篇

  下篇整理演講後半的內容,主要更進一步探討類別跟函式的設計概念。

類別設計


減少易變性(mutability)

  • 除非有好理由,不然類別應該要 immutable:好處是單純、thread-safe、可重複使用;缺點是每個不同的值都是獨立的物件,也就是為了改一個值,就要放棄現在的物件取得新的物件。
  以 python 為例,int 是 immutable 的,所以使用 '1' 的值,它只要產生一次對應的物件,後續只要使用到 '1' 的值,就使用同一個物件即可。
>>> id(1)
10914496
>>> x = 1
>>> id(x)
10914496
2020年7月11日 星期六

[筆記] API 設計概念 — 上篇

  當初在設計 MLGame 專案時,為了能夠讓遊戲開發者和玩家能夠使用 MLGame 架構,於是嘗試查了關於 API 設計的概念。本篇整理一場 Google 的技術演講,演講標題為「How to Design a Good API and Why it Matters」,演講雖然是在講 API 的設計概念,但我認為這些概念在平常撰寫程式上也很受用。演講以 Java 為舉例語言,文章中會引用演講中的例子,我也會盡量舉在專案中(以 Python 撰寫)遇到的情況。
上篇整理演講前半段的部分,主要是 API 設計的通用概念。

為何 API 設計重要?


  • 好的 API 可以是公司最重要的資產之一:客戶會使用 API 來製作產品,同時也會學習使用 API。而放棄一個 API 去學習另一個全新的 API 的成本太高,所以一個好的 API 會吸引客戶來使用
  • 壞的 API 就會是公司的負債:客戶會佔滿客服線路。公司要修改 API 也會困難重重,造成技術負債
  • 發布的 API 就發布了:修改 API 可能會造成客戶的程式崩潰。

為何 API 設計對你重要?


  • 平常寫程式也是在做 API 設計:好程式是模組化的,而模組之間的界線就是 API。而且好的模組應該要能夠一再被重複使用
  • 以 API 設計的方式去寫程式可以增進程式品質

2020年3月18日 星期三

[筆記] 矩形的碰撞偵測 (下篇) - 沒被偵測到的碰撞

  有時就是天不從人願,當覺得碰撞 OK,反彈 OK 的時候,就會出現不 OK 的情況。做了一個球速會漸漸加快的 pixel game,然後遊戲就逐漸毋湯。當球移動的速度很快的時候,球會穿越平台,連碰撞都沒有被偵測到,然後就蹦蹦了。

問題點


如圖所示,當球一次移動的距離大於板子的厚度時,板子可是一點感覺都沒有呢。因為球的移動並非連續移動,而是在這個影格是 A 地點,下一個影格就直接出現在 B 地點(直接加上要移動的距離)。可以想像做碰撞偵測時,是看當下每個物件的位子來判斷有沒有碰撞的,所以當球直接「掠過」板子時,就不會被偵測到碰撞。如此一來就會出現穿板的現象,原本應該繼續的遊戲,就 Game Over 了。

2019年7月10日 星期三

[筆記] 矩形的碰撞偵測 (中篇) - 反彈

  處理完碰撞後,接著就要來處理碰撞後的反彈。因為做的是打磚塊這類 pixel game,所以呈現的是簡單反彈,也就是反彈物體速度的 xy 分量的正負號變換(呈現出來是入射角 = 反射角,反彈後速率維持不變)。
  這個功能困擾的我很久,困難點在於如何判斷是哪個面發生碰撞。期間一直無法做出理想中的反彈效果。後來拋出問題向朋友求救,討論後終於得到解答,雖然想出來的演算法不盡完美,但大部分的情況下都能有預想中的反彈行為。

2019年6月16日 星期日

[筆記] Unity3D 設置 Android apk 建置環境 - 不安裝 Android Studio

  以前可以直接單獨下載 Android SDK manager 來管理 Android apk 開發環境,但後來必需安裝 Android Studio 才可以使用 SDK manager。Android Studio 需要大量空間與資源,對於只需要 Android SDK 的我來說顯得多餘,此外要使用 manager 還必須先等待 Android Studio 啟動,相當不方便。幸好還是可以透過 command line tools 來管理 SDK 套件。

  本篇文章要建立 Android apk 建置環境所需要的套件如下,示範的作業系統為 Windows:
  • Java SE Development Kit (JDK) 8
  • Android SDK Tools 25.2.3 (也就是 SDK manager)
  • Android platform 27 (Android 8.1,要選擇其他 API level 可以查看對照表)
  • Android build-tools 27.0.3 (Android 8.1)
  • Android platform-tools

2019年3月31日 星期日

[筆記] Django - File Validator 上傳檔案與驗證

  Django 的表格 (Django.forms.Form) 能夠從設定的欄位產生對應的 html 表格,並幫助開發者從提交的資料中過濾有害的資訊,將資料轉換成 Python 物件供取用。還可以撰寫額外的程式碼以驗證提交的資料是否有效。
  撰寫驗證資料的方式有三種:在表格的定義中撰寫 clean_<field_name> 函式、繼承對應的欄位類別並提供 validate()、撰寫驗證類別並傳入到對應的欄位中。本篇網誌使用第三種方法來驗證使用者上傳的檔案,檢查檔案副檔名、MIME type、檔案大小。

2019年1月17日 星期四

[筆記] 矩形的碰撞偵測 (上篇)

  寫遊戲常常用 API 來幫忙處理碰撞偵測,當需要自己寫類似的功能時,發現內部的運作沒有想像中的簡單。最近因為專案的需求,撰寫打磚塊遊戲,原本想利用 pygame 的碰撞偵測,但是不適合這個專案,只好挽起袖子研究研究作作看。上篇介紹矩形碰撞偵測的原理,下篇則介紹在碰撞之後反彈的效果。

2018年12月3日 星期一

[筆記] Python - 應用 decorator 實作函式開關

  最近為了課程撰寫遊戲的 server 端 (專案於 Github),主要提供遊戲資訊跟進程控制的功能,client 端是一群擁有通訊功能的迷宮車,兩邊靠既定的指令溝通。在設計遊戲功能時,有些指令希望只在遊戲開始後才有作用,但又不可能讓 client 端乖乖在遊戲開始後才發送指令。最直觀的作法就是在每個處理指令的函式中檢查遊戲是否開始:
def game_command(...):
    if not game_is_started:
        return
    # Other jobs
但很快發現充滿重複的程式碼,而且影響程式碼的簡潔與維護的不方便。於是上網查找有無類似 C# 的 function attribute 的寫法,只要在函式的定義前加上像是 game_started 的 attribute,就可以控制該函式的行為。於是找到了 decorator (裝飾器)

  本篇主要介紹我如何在專案中使用 decorator,先簡單介紹 decorator,接著是本篇主題 ─ 利用 decorator 來實作函式開關,與在類別中使用 decorator,最後是如何進一步強化 decorator 的能力。以下講解皆使用 python 3。

2017年9月7日 星期四

[筆記] 多一點、少一點 ─ 雷切或 3D 列印卡榫時的預留空間

  個人在設計作品時,多多少少會加入螺絲孔,或是耍廚想要作一個純粹使用卡榫固定的作品。而當材料的製作是使用雷切或是 3D 列印時,在設計時就要考慮一些眉角,讓螺絲孔或是卡榫能夠符合預期的樣子使用。本篇文章介紹我在使用雷切與 3D 列印的這方面的心得(我也只用過這兩種

2016年11月27日 星期日

[筆記] 深入了解 switch-case

  之前在課堂的作業中第一次看到神奇的 switch-case 用法,藉著機會研究一番;剛好朋友也詢問了類似的問題,也查看更多資料,完全顛覆我以前對 switch-case 的理解。因此藉著這篇文章來記錄我所查到的知識,也順便掃掃灰塵((汗。

  最初學到的 switch-case 用途是「多重選擇」,也就是說用來取代一連串的 if-else statement 對於一個變數的連續判斷,如以下的例子:
if (value == 0)
    printf("Grade S\n");
else if (value == 1)
    printf("Grade A\n");
else if (value == 2)
    printf("Grade B\n");
else if (value == 3)
    printf("Grade C\n");
else
    printf("Grade D\n");
可以用 switch-case 取代成:
switch (value) {
    case 0:
        printf("Grade S\n");
        break;
    case 1:
        printf("Grade A\n");
        break;
    case 2:
        printf("Grade B\n");
        break;
    case 3:
        printf("Grade C\n");
        break;
    default:
        printf("Grade D\n");
        break;
}
基礎複習完了,大家可以回家了。

以下會討論到:
  • 在 switch-case 中宣告變數
    • switch 之下,case 之前
    • 在 case 中宣告變數
    • 不同 case 之間宣告相同名稱的變數
  • 不只是 if-else 的替代品 (對於一個變數的連續判斷)
而接下來的討論皆引用 C98/99 的規格書,需要一點 language syntax 的概念。
2015年5月9日 星期六

Unity3D - Circular Scrolling List - Part 2 - 顯示內容

了解 ListBox 的移動概念後,接下來就要顯示內容拉~

以下分成幾個部分:

  • ListBank
  • 初始化內容
  • 更換內容

2014年9月4日 星期四

Unity3D - Circular Scrolling List - Part 1 - 移動概念

實作影片:https://youtu.be/iZSN6CC--9Y

這個 Scrolling List 有幾個特色:
  • 使用固定數量的選單物件來代表無限數量的內容
  • 弧形移動效果
  • 慣性移動效果
將它分成幾的部分來教學:
  • 滑鼠動作
  • 慣性滑動
  • 多個物件同時移動
  • 邊界處理及環狀功能
  • 弧形移動
2014年4月6日 星期日

[筆記/GitHub] git add -p 及 git stash

  在使用 git 一陣子之後,應該都會遇到「修改 code 到一半,發現之前的 code 有地方需要修改」之類的問題。當遇到這樣的情況往往會選擇連同之前的 code 一起做修改,然後一同 commit 上去,一次提交太多而且不同功能的 code,造成 commit message 混亂。以下介紹兩種實用的 git 指令:git add -pgit stash,來幫助解決這樣的情況。

2014年2月14日 星期五

[筆記] Cruise Control番外篇-Ant build file介紹

  Ant的build file類似makefile,不過使用的是xml語法來撰寫。下面介紹如何撰寫Ant的build file。
完整的Ant build file範例

[筆記] Cruise Control(三)-config.xml設定

  XML全寫為eXtensible Markup Language,是一種標記語言,而在這裡被用為描述軟體的設定參數。其巢狀式的結構也方便人來閱讀。基本上每個元素都有開頭和結尾,如果是多行則為<ele> ...</ele>,如果是單行則為<ele.../>,如果該元素帶有屬性則應該寫為<ele attr1=... attr2=... >...</ele>
2014年2月13日 星期四

[筆記] Cruise Control(二)-架設Cruise Control及概觀



  Cruise Control是提供Continuous Integration的工具之一,他的介面陽春、簡單,安裝也相當方便。Cruise Control由Java寫成,屬於開放原始碼,也因此有第三方的插件可供使用。

[筆記] Cruise Control(一)-介紹Continuous Integration

什麼是CI?


Continuous Integration,持續整合。 當一個大型Project由很多人共同開發時,軟體的品質維護就變得更加困難但也更加重要。在開發過程中會遇到一些問題,像是開發人員用的開發軟體版本不同、一個人開發了新的功能,可能會影響舊的功能運作等。應該在一發生錯誤時就立即更正,到了開發後期才進行build後果不堪設想。

2014年1月25日 星期六

[筆記/Ubuntu] Java環境架設

  JAVA是一個跨平台的物件導向程式語言,廣泛被應用在Web應用開發和行動應用開發。風格與C++近似,但捨棄了C++中的指標,完全使用reference,移除運算子多載,也移除C++的多重繼承的特性,改用介面(Interface)。JAVA的另一個特性是Garbage Collection,也就是將不會再被使用到的物件清除掉,釋放記憶體。以下是如何在linux環境安裝JDK的方法: