日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

游戏《蔚蓝山》教我的编程道理

發布時間:2024/8/26 65 豆豆
生活随笔 收集整理的這篇文章主要介紹了 游戏《蔚蓝山》教我的编程道理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

如果有這么一款游戲,你操作的角色平均每 20 秒就會死亡一次,正常通關一次,總共需要死掉超過 2000 次。你猜這是一款神作還是垃圾?

《Celeste》(譯名:“蔚藍山”)就是這么一款游戲。在游戲里,你扮演一個名為 Madeline 的女孩,通過跳躍、抓墻、沖刺等動作,去努力登頂一座名為 “Celeste” 的高山。
?

圖:《蔚藍山》游戲畫面,它是一款點陣畫風 2D 平臺動作游戲


正如我在開頭說的,這款游戲的難度高到令人發指,玩家平均得死上千次才能通關。但奇怪的是,這款游戲獲得的成就似乎和它的難度一樣高。在 2018 發售那年,它獲得了 TGA “年度游戲”提名并成功拿下了“最佳獨立游戲”獎項。截止到 2018 年底,它總共賣出了超過 50 萬份。

極低的犯錯成本

讓《蔚藍山》大獲成功的原因有很多。精妙的關卡設計、出色的動作手感、令人驚艷的游戲配樂,以及劇情里流露出的真誠人文關懷,都是非常關鍵的因素。但除開這些,我在玩游戲時,還注意到了一個有意思的細節:在游戲里,玩家的犯錯成本非常低。

假如你操作跳躍的時機不對,角色掉入坑里死掉了。然后,在 不到 3 秒鐘 內, Madeline 就會在房間入口處復活。你可以對自己的打法稍作調整,馬上進行下一次嘗試。

并非所有游戲都給予了玩家這種快速試錯能力。比如在 PS4 游戲《血源詛咒》里,一次死亡可能代表你過去一小時獲得的資源全都化為烏有。

注解:
在《血源詛咒》中,玩家死亡后會喪失當前擁有的所有血之回響(一種游戲內資源)。如果要找回它們,你需要從一個又一個怪物堆里穿過,回到你的死亡地點。如果你在路上再次死掉,那么那些血之回響就會全部消失。

所以,在《蔚藍山》里,游戲設計者給了玩家一種可以 “低成本犯錯” 的能力。有了它,我們可以快速從錯誤中學習,更好的完成挑戰。那么,如果用編程來類比,我們在寫代碼時的犯錯成本又如何呢?

編程時的“犯錯成本”


假設我在開發一個新聞稿管理系統,系統里目前只有一種用戶:“管理員”。但因為需求變更,我現在得給系統加上兩個新角色:“編輯”和“主編”。

每類角色能做的事是有區別的:
?

  • 編輯:可以提交稿件、修改自己的稿件
  • 主編:在編輯的權限上,增加刊登稿件的功能
  • 管理員:可以做任何事以及管理所有人的權限


為了支持不同的角色,我需要改進現有的用戶權限體系。首先,我得把和權限控制相關的所有功能點整理出來,然后開始寫權限控制相關的代碼。

沒人能一次寫出不出錯的代碼,所以寫代碼,其實就是一個在不斷重復?“開發” -> “試錯” -> “修改”?的過程:
?

  • 修改后端代碼,增加新角色:“主編”
  • 在“主編”相關的功能點,增加權限保護代碼片段
  • 保存代碼,等待本地服務器重啟加載改動 (5-10 秒)
  • 打開瀏覽器,點擊各個功能頁面,確認我的改動是否生效 (10 秒以上)
  • 如果測出問題,回到步驟 2,重復整個過程


在很長一段時間里,我在工作時的開發流程就是上面這樣。我總是在接到需求后就馬上對代碼修修改改,然后打開瀏覽器,點點這里、點點那里,用肉眼觀察一切是否正常。

使用這種開發方式,假如我某次寫的賣QQ靚號代碼有問題,那么從我每次改完代碼,到一直走完步驟 3、4、5,整個過程至少得花費超過 30 秒。

如果你不覺得 30 秒很多,請你想想《蔚藍山》吧。在《蔚藍山》里,角色每次死亡到下次重試的時間間隔是不到 3 秒鐘,二者相差 10 倍。所以,上面這種開發模式的“犯錯成本”太高了。

如何降低“犯錯成本”

其實,在開發這類 web API 時,我們完全沒有必要傻乎乎的手工用瀏覽器點來點去。作為功能的開發者,我們可以(而且有義務)利用自動化測試來加速整個試錯過程。

很多 web 框架都為這類測試提供了幫助。拿 Django 為例,你可以使用?django.test.Client?來輕松編寫這類測試:

  • # 以下代碼片段來自 Django 官方文檔
  • import unittest
  • from django.test import Client
  • class SimpleTest(unittest.TestCase):
  • ? ? def test_details(self):
  • ? ?? ???client = Client()
  • ? ?? ???response = client.get('/customer/details/')
  • ? ?? ???# 測試某次請求是否返回了 200 狀態碼
  • ? ?? ???self.assertEqual(response.status_code, 200)
  • 復制代碼


    對于前面的需求,我們可以直接編寫下面這樣的單元測試代碼。

  • # 針對不同的角色定義不同的單元測試類
  • class RoleEditorTestCases(TestCase):
  • ? ? """編輯角色的測試類
  • ? ? """
  • ? ? def test_create_post(self):
  • ? ?? ???# 編輯角色可以正常調用創建帖子接口
  • ? ?? ???response = self.request_post('/posts/', {'title': 'foo'}, current_user=self.user)
  • ? ?? ???assert response.status_code == 201
  • ? ?? ???assert isinstance(response.data, dict)
  • ? ? def test_create_admin(self):
  • ? ?? ???# 編輯應該無權調用創建管理員接口
  • ? ?? ???response = self.request_post('/admins/', {'user_id': 100}, current_user=self.user)
  • ? ?? ???assert response.status_code == 403
  • class RoleAdminTestCases(TestCase):
  • ? ? """管理員角色的測試類
  • ? ? """
  • ? ? def test_create_admin(self):
  • ? ?? ???# 管理員可以調用創建管理員接口
  • ? ?? ???response = self.request_post('/admins/', {'user_id': 100}, current_user=self.user)
  • ? ?? ???assert response.status_code == 201
  • 復制代碼


    有了這些單元測試后,整個試錯流程可以得到極大改進。每當我改完代碼后,只要運行 pytest 命令跑一遍相關的單元測試,就能知道改動是否奏效了。
    ?

  • ? pytest
  • ======== test session starts ========
  • platform darwin -- Python 3.8.1, pytest-5.3.5
  • collected 5 items
  • tests/api/test_permissions.py .....
  • ======== 5 passed in 0.72s ========
  • 復制代碼


    不需要等待開發服務器加載變更、不需要打開瀏覽器點這點那。一切試錯任務都可以在幾秒鐘之內完成。

    編寫測試其實也是 DRY

    我在前面說過,在游戲《蔚藍山》里,如果角色死掉了,那么她馬上會從當前這個 房間入口處 重生。讓我們設想一下,假如游戲沒有采用這種設計:在新機制下,角色每次死亡后,玩家都得回到本章開始的地方,重新挑戰一遍好幾十個已經通過的房間。那會怎么樣?估計很多人會氣的把手柄摔地上。

    但是,依賴人工測試的開發流程,其實就非常接近于讓人摔手柄的設計。

    拿用戶權限功能來說,因為這個功能非常關鍵,所以我每次做出大改動后,都需要重復驗證一下每個功能點在各角色下的表現是否正常。假如系統里一共有 20 個功能點需要和權限掛鉤,那么?20 * 3?個角色,就是 60 個需要測試的點。

    即便我有三頭六臂,每個功能點只花 20 秒測試,整套東西測下來也需要 20 分鐘。

    但是,如果你已經為這些場景寫好了單元測試,那么事情就變得簡單多了。每次做了改動之后,你只需要重新執行一遍單元測試,就能把所有場景都驗證一次。

    Django 框架有一條設計哲學叫?“Don't repeat yourself (DRY)”?- “不要重復你自己”。多數情況下,我們說 DRY 是指不要寫重復代碼。但我認為“不要重復手工測試已經測過的東西”其實也可以算是 DRY 的一種。

    所以,每當你手動測試一次功能時,其實就是在重復你自己。既然如此,何不將它寫成一個單元測試呢?


    “所以,就是在勸我寫單元測試?”


    是的,我就是在勸你寫單元測試。作為對比,讓我們看看利用單元測試的開發流程是什么樣的:
    ?

    • 修改后端代碼,增加新角色:“主編”
    • 在“主編”相關的功能點,增加權限保護代碼片段
    • 編寫與功能代碼相關的單元測試代碼,與 2 同步進行
    • 執行單元測試,如果失敗,從 2 開始調整代碼,重復整個過程 (幾秒鐘)


    通過把測試行為自動化,我們可以大大減少整個開發過程的試錯成本。事實上,自從若干年前養成了寫單元測試的習慣,我就一直堅持至今。那么,我到底是因為什么在寫單元測試呢?
    ?

    • 單元測試讓我的代碼 Bug 更少?
    • 單元測試幫助我寫出擴展性更強的代碼?
    • 單元測試讓我在重構時更不容易出錯?

    以上可能都是。但現在,我可以往上面的列表里再加上一點:使用單元測試來開發的過程,有一種流暢感,失敗后就馬上重試,一切就猶如在操作 Madeline 登頂那座蔚藍色的山。

    與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結

    以上是生活随笔為你收集整理的游戏《蔚蓝山》教我的编程道理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。