編程擊球
發布時間: 2023-09-11 06:38:30
A. 從零開始學編程做游戲:一個文科生策劃的14周
前言: 劉嘉俊是一名從業不久的游戲策劃,他在14周的時間里,從技術小白到能寫600行代碼。他的方法是,在日常工作之餘,每周製作一個小游戲,通過這種方式來鍛煉自己對游戲系統設計和開發過程的理解。以下為投稿原文,未經作者許可請勿轉載。我沒有計算機背景或美術基礎,但乘中國游戲行業大發展,卻也幸運入行成為一名游戲策劃。我希望在日常工作之餘,用一個辦法來鍛煉自己對游戲系統設計和開發過程的理解。因此,我參加了 Coursera 上的幾個課程,並且用課程提供的方便工具來實現設想中的功能。
這個方法我稱之為「每周一游」,即每個星期快速開發一個游戲,連續進行數個星期。這是許多開發者們磨練自己想法和技巧的方式。
一開始的成果非常基本、非常簡單,但到後面挑戰等級逐漸上升,到最後已經能獨立完成 600 行左右的程序。
接下來我就給慎茄各位看看我在這近四個月中的成果,以及我從中學習和體會到的內容。我盡量省略比較枯燥的實現細節,一來可以避免無聊,二來需要下功夫的東西還是親手實踐比較有幫助。如有興趣可來我的微博交流。
第一周:包剪錘蜥史波克(Rock-paper-scissors-lizard-Spock)
Sheldon 喜歡的游戲。
電腦則會隨機生成一個數字,轉換成字元串。再根據雙方數字,用 if-else 判斷勝負即可。
對我來說這是自己親手編寫的第一個游戲。它雖然簡單,但包含了一個游戲必須的全部要素:它有著固定的開始和結束,以及勝負的規則。
第二周:猜數字
在這個游戲中第一次引入全局變數的概念。初始化時,上下限以及允許你猜測的次數都是讀取全局變數。這樣一來,我們可以在游戲核心的方法之外,使用別的方法來修改全局變數,讓玩家可以自己選擇數字范圍和猜測次數。游戲本身則依然是 if-elif-else 這樣寫成的。
這是我親手編寫的第一個可以由玩家調整游戲設置的游戲。
第三周:秒錶游戲
這個游戲中涉及到為每個功能編寫單獨的方法。如玩家控制的按鈕start()、stop()、reset();游戲本身時間前進的tick()等。同時,為了讓時間正確地顯示在屏幕上,還有一個將時間轉化為「A:BC:D」這種形式的方法。
我們計時的方法是定義一個叫 time 的變數。由於這個游戲中最小的計時單位是 0.1 秒,所以每經過 100 毫秒我們就讓這個數字 +1。與此同時,編寫一個 format() 方法經過一系列計算將這個數字轉化為分、秒和0.1秒,顯示在屏幕上即可。判斷玩家是否得分仍然使用 if-else 結構。
這是第一次涉及到玩家進行的復雜操作,也是第一次認識到,在游戲畫面的表象之下究竟應該有些什麼機制在運行。
第四周:乒乓(Pong)
傳說 Pong 是世界上第一個電子游戲。在那個游戲機只有滾軸操作的年代,這個有著極簡單畫面的游戲啟發了無限後來者。看著它在手下形成還有些小感動呢。
這個游戲也是我製作的第一個不模擬現實中的「邏輯」,而是模擬「物理」的游戲。它的核心部分是球的速度變化、板子的速度變化,以及球與邊界和板子的碰撞。
為了讓這個游戲不至於無限地進行下去,我讓球的速度隨著每一次板子碰撞上升。但上升的公式寫成了指數函數,於是這球就啪啪啪越打越快每一回合很快就結束了。若改為對數寬叢察函數,則會緩慢地趨近一個上限,令每一回合後期的雙人對局非常緊張、充滿變數。
這是我第一次體會到游戲的「手感」到底是怎麼回事。每一次對參數的細微調整對手感帶來的變化,可以讓設計者與游戲本身有著更深刻的接觸。這是在目前分工充分的網游公司的日常工作中體會不到的感覺。
除此之外,很快地你就能從一個簡單原型中看出未來變化的可能。是否可以加入:
「球擊打在板子的不同部位,會彈向不同方向」?
「當板子擊球時,板子本身的速度會令球曲線飛出」?
或者「連續擊中球數次後玩家可以發出大招」?等等諸如此類。想到這里,這個游戲能成為數十年游戲業的起點,也是有其道理的。
第五周: 記憶游戲
在這個游戲中,暫且用數字來代替撲克牌。我們用了一個 list (我有點搞不太清 list, array, tuple, set 幾個詞的中文翻譯,不亂講了……)來以 Boolean 值(True 和 False)記錄每張牌是否翻開的狀態。當設為翻開時,露出數字,否則在相應位置繪制一張牌背。
這個游戲的邏輯方面比較 tricky 的地方就是整個游戲實際上有三種狀態,需要分別處理:
新游戲,一張牌都沒翻開
翻開了(本回合內)第一張牌,等待翻開第二張
翻開了(本回合內)第二張牌,等待判斷是否相同於是我使用一個叫做 state 的變數,分別以 0, 1, 2 代表三種狀態。在核心方法中利用 state 的值來決定接下來要做什麼。
第六周:21點(Blackjack)
這是個賭博游戲。簡單來說規則是:莊家給自己和玩家各發(deal)一張暗牌、一張明牌,玩家決定是否繼續加牌(hit);玩家加牌結束(stand)後莊家自行加牌,接著雙方攤牌。擁有最高點數的玩家獲勝,其點數必須等於或低於21點。
在編寫這個游戲的過程中第一次引入了類(class)概念。因為在游戲中許多物件都會重復出現,使用類可以很方便地重復製造它們:
每一張牌是 Class Card;方法 get_suit() 可以獲取它的花色;
方法 get_rank() 可以獲取它的數字;
還有一個方法來把它繪制出來。
手牌是 Class Hand;方法 add_card() 可以在手牌中增加一張牌;
方法 get_value() 可以算出手牌的分數。
牌庫則是 Class Deck。方法 shuffle() 可以洗牌庫;
方法 deal_card() 用來發牌。
規定好這些基礎方法以後,重發牌、加牌、攤牌都可以通過這些功能的組合來實現。例如開局就是洗牌庫,向雙方發牌;雙方手牌加上兩張發出來的牌。等等。
此外這個游戲還第一次涉及到怎樣在畫面上繪制固定的圖形。整張牌表是一張大圖,怎麼樣根據牌的值定位到對應的牌面也是要好好算一下。
第七周:小行星(Asteroid)
這回的游戲涉及的內容比以前多,除了控制小飛船打來打去之外,動畫、音效、UI 等也都引入了游戲中。但每一部分的實現都可以通過之前嘗試的小功能疊加實現。簡單地了解游戲圖像和聲音到底怎麼運作後,並無特別的困難。只是這一次我學著一個模塊一個模塊漸次開發和測試,一個功能調通無誤,再進行下一個。
反而是在游戲設計方面,製作這個游戲的過程給我帶來很多思考。在這個游戲中可供調整的變數太多了:飛船需要推進和旋轉;但推進是給飛船一個向前的加速度,而飛船本身還會有向著其他方向的速度。宇宙空間中微小的摩擦力、和隕石撞擊後受到的力,都要考慮並且編入游戲中。
這時你會發現,同樣的一些參數,經過調整會讓整個游戲變得徹底不同。這艘飛船到底是笨重、轉向慢、射速慢、射程遠的戰列艦,還是輕盈、轉向快、射速快、射程近的戰斗機?你要躲閃的是從一個方向襲來的流星群(隕石都從一邊來,而且向一個方向阻力特別大),還是四面八方出現的亂石?每一種選擇,好像都挺好玩的……
到這時我才了解到一個游戲設計者腦中「指揮意圖」清晰的重要性。你到底要做一個什麼樣的游戲,給玩家帶來什麼樣的情感?只有一個大概的「我要爽」是不夠的:究竟是控制巨大戰艦緩慢機動將將擦過一塊流星的
B. 編程好學習嗎
編程好學,就是要多練習,抱書本不行。主要是就是邏輯,你的邏輯思維很嚴謹,發散型思維很強,就能編出好東西,數學基礎好對編程有很大幫助。
熱點內容