iT邦幫忙

2023 iThome 鐵人賽

DAY 22
0
SideProject30

年輕人,想玩自己寫!系列 第 22

第二十一章,你很誠實,所以我決定讓你的手機響個不停(上)

  • 分享至 

  • xImage
  •  

透過前幾天的討論,我們應該能列出符合遊戲需要的成就清單。
也應該能建置成功成就資料表了。
但這些還不能算是已經建置好我們的成就系統了,因為他並不會自動運作起來。
要讓他真正產生作用,要將整個成就獲得的行為串連起來才行。
成就獲得的行為流程如下:

遊戲行為 -> 記錄 -> 判定是否符合成就條件 -> 若符合則給成就

確定得到成就之後:

給成就 -> 發送通知 -> 展示成就

這表示最少有三件事我們要做到:

  1. 在程式初始化時,確定成就清單的資料表有被建立
  2. 在程式初始化時,開始notification的工作
  3. 在每一個行為發生時,例如登入、開始遊戲、選擇、數值改變,都能有東西記錄下來並確定能不能給成就

將工作拆成AchieveManager類別的建立、資料表的建立、畫面的刻畫及通知的發送,
今天會先把前面的部份完成。

  • 首先是資料表的建立,這邊可以用sqlite的資料庫去存,也可以和使用者資料一樣存在SharedPreferences。
    因為前面已經有將使用者資料存在SharedPreferences的類別,且實作了單例的設計。
    這邊一樣把資料表的建立與確認放在裡面就行了。
    如果沒有存在的資料表,則讀取放在assets裡的json直接寫入,羅列出所有設計好的成就。
在 main.dart 裡

Future<void> main() async {
  ///連結硬體
  WidgetsFlutterBinding.ensureInitialized();
  ///設為全螢幕
  Flame.device.fullScreen();
  var defaultHome = const LoginPage();

  final SharedPreferences prefs = await SharedPreferences.getInstance();
  StaticFunction.prefs = prefs;
  StaticFunction.getInstance().checkAchieveListBuild();
  
  ......
}
  
在 StaticFunction class 裡

  checkAchieveListBuild() async {
    String? dataString = prefs.getString("achieve_data");
    if(dataString == null){
      dataString = await rootBundle.loadString('assets/achieve_data.json');
      await prefs.setString("achieve_data",dataString);
    }
  }
  • 建置一個AchieveManager的管理類別,實作單例,內置許多方法能記錄使用者的行為。
    然後在對應的地方,都要記得去使用這個管理類別的方法,才能把使用者的行為都記錄下來。
    同時,又因為我不太想把要記錄的東西寫死、寫成一個固定的類別,這樣以後有新的東西要記都要改動前面寫好的。
    所以我想用非常自由加入Map<dynamic,dynamic> data的方式,寫入並記錄相關的數據,像是這樣:
///登入時都會呼叫這個方法
UserData? getAccount ()  {
    String? dataString = prefs.getString("user_data");
    print(dataString);
    ///在這裡加一次登入次數
    achieveManager.add({"login_times":1});
    return dataString != null ? UserData.fromJson(jsonDecode(dataString)) : null;
  }
  
在AchieveManager裡 add方法的設計

add(Map dataInput) async {
    ///取得使用者的記錄資料
    String? recordString = prefs.getString("user_records");
    Map recordData = jsonDecode(recordString??"{}");
    ///傳入的資料若是數值表示要加上該數值,若是其他,則是覆寫
    if(dataInput[dataInput.keys.first] is int){
      int addValue = dataInput[dataInput.keys.first]??0;
      int oldValue = recordData[dataInput.keys.first]??0;
      recordData[dataInput.keys.first] = oldValue + addValue;
    }else{
      recordData[dataInput.keys.first] = dataInput[dataInput.keys.first];
    }
    await prefs.setString("user_records",jsonEncode(recordData));
    ///印出來在後台看
    print(recordData);
  }

成功給寫入方法保留了最大的自由度,不論是key值還是類型(之前提過的一次或累計)都沒有寫死。

  • 比較成就資料表中,有沒有已滿足的條件。
    若是有,則要修改成就資料表中的記錄,並且要發出通知。(今天先印在後台)
compareAchieve(String key, recordData){
    List achieveList = jsonDecode(prefs.getString("achieve_data")??"[{}]");
    for(int i=0;i<achieveList.length;i++){
      if(achieveList[i]["ID"].toString().compareTo(key)==0 && achieveList[i]["AMOUNT"] == recordData){
        achieveList[i]["HIDDEN"] = false;
        ///印在後台
        print("獲得成就 名稱: ${achieveList[i]["NAME"]} \n ${achieveList[i]["DESCRIPTION"]}");
      }
    }
  }

今日簡單測試

https://ithelp.ithome.com.tw/upload/images/20231007/20162723oPtzk40UK9.pnghttps://ithelp.ithome.com.tw/upload/images/20231007/20162723AtL3h7bXvH.png

其實滿簡單的,但這只有後台看得到,明天讓使用者無法乎視我~
/images/emoticon/emoticon39.gif


上一篇
第二十章,你掉的是這個金成就?還是這個銀成就?
下一篇
第二十二章,你很誠實,所以我決定讓你的手機響個不停(下)
系列文
年輕人,想玩自己寫!31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言