游戲發展早期,C甚至匯編當道;復雜的游戲邏輯(玩家操作、攻擊技能、傷害判定、各種特殊的技能/狀態邏輯,等等等等)想要有條不紊的管理起來、隨時間流逝均勻可控的運作、同時又要盡量優化性能(比如其它答案談到的“圖形顯示優化”)……
這難度,飛上天了吧?
因此,就有了“精靈”抽象:游戲里一切能感知時間流逝、具有坐標位置的,都是精靈。
你看,一下子抓住了兩個根本:一、有坐標信息;二、能感知時間流逝。
一旦抓住這兩個根本,事情就容易起來了。
我們可以設計一個定時器,周期性的調用和精靈綁定的處理函數(相當於C++的虛函數,接受的傳入參數是interval)——實際上,這個處理函數是一個dispatcher,它負責轉調用我們寫的一切動畫以及碰撞判定等邏輯的處理函數。
所有這些函數都要接受interval參數,比如讓精靈按貝塞爾曲線運動的函數就是用interval乘以運行速率、然后改寫精靈的坐標信息;同樣的,動畫呢,就是按照interval的節律縮放扭曲圖片或者改變它的顏色(或者基於interval把一組圖片換來換去,從而實現走路、放大招等效果)。
注意精靈是可以沒有對應的圖片的,比如我們要在進門處放個陷阱,那就是一個和門口坐標重疊的、不可見的“觸發器trigger”,當碰撞檢測發現游戲物體和這個“觸發器精靈”坐標重合時,就會調用對應的trigger。
換句話說,這是用C甚至匯編實現的一個原始而精巧的繼承體系;它的根是“精靈”這個基類,提供坐標這個公開數據成員和dispatcher時鍾信息的接口;然后是“支持碰撞檢測以及提供接受碰撞事件並加以處理的接口”的繼承類,和“支持動畫”的繼承類以及其它各種繼承類。
至於為什么叫“精靈”,大概是因為它只是能“感知”有位置,卻未必有實體吧——在西方傳說里,“精靈sprite”本來就是有魔力的、介於虛實之間的幻想角色,如火之精靈、光之精靈之類。
一旦有了這個抽象,那么無論聲音還是圖像,無論是軟件還是硬件優化,就都要以精靈為中心了:負責游戲性循着精靈這條線更改角色位置、檢測碰撞、觸發相關處理邏輯;負責畫面的也循着精靈這條線,更新屏幕顯示、優化圖形性能;負責聲音的呢,同樣循着精靈這條線,根據距離畫面焦點的遠近改變不同聲源的聲音大小、以及考慮是否應該添加濾波/回音等效果;負責劇情的同樣可以把文字/過場動畫/事件觸發等綁到精靈上,設定觸發條件即可,等等等等。
總之,每個人只關注自己需要關注的那個側面,完全可以忽視其它東西的存在。這樣不管游戲多么復雜、世界多么宏大,一切都可以井井有條的解決。
注意這個先后順序:程序員設計的東西,肯定是以便利程序員自己為最優先。
先有了一個最合理最高效的架構,然后一切就可以基於這個架構提供方便。
就好像是計算機3D圖形先把3D真實感圖形渲染以面片為中心、然后硬件設計(顯卡/GPU)才提供了迎合這個抽象的渲染體系;並不是硬件先弄出來面片,然后程序員們一陣焦頭爛額手忙腳亂的往面片遷移……肯定不是這個過程,對吧。
換句話說,硬件支持可以證明一種做法的流行——流行到通過硬件管線直接支持——卻幾乎不可能是這種做法的來源(都出硬件支持了,可想而知這種設計在硬件出來之前有多流行)。
另一個,因為大多數人只負責自己那一塊,很容易局限於“在我的領域,XX事是怎么怎么來的”。這大概就是高票二位大佬掐架的原因。
但游戲開發是個很復雜的工作,不可能遷就於某個單一方面。
比如在3D游戲邏輯開發里就沒有“面片”,那是建模和渲染玩的,不會“侵染”游戲邏輯開發過程,對吧。
同樣的,2D游戲開發,精靈是從軟件架構來的;但這個架構在設計時,一定綜合考慮了圖像渲染、游戲邏輯等諸多方面,最終才決定“同時向圖像組和游戲邏輯組開放sprite這個概念”——也只有站在總體架構的角度,sprite這個術語才是貼切的:如果是圖像處理方單獨決定的,那他們肯定不會叫它sprite。這個詞和他們做的事(合成活動圖片到背景)有半點關系嗎?
當然,因為語言層面沒有面向對象的支持,這個設計只能通過以強制類型變換為核心的各種奇技淫巧實現。
到了面向對象時代后,這套體系就沿用下來了;后來大概是為了區分吧,2D游戲仍然沿用精靈這個術語;而3D游戲就改名叫GameObject,不再使用“精靈”這個說法(但一切GameObject仍然有坐標有transform,哪怕它只是個計分牌、只關心屏幕坐標)。
正因此,當年C++等面向對象語言火爆時,游戲界反而不怎么感冒。因為這些都已經在C語言里面有了完美的解決體系,面向對象語言搞的那么一堆private啦繼承啦之類約束反而會打破這個體系,把既有體系推倒重來、然后再把附着於既有體系的無數現有邏輯重寫一遍,這實在太麻煩了。所以……C++,從游戲行業滾開!嗯,當然,說“C++滾開”是開玩笑。
上古時代的確只能用C或者匯編寫游戲;但后來漸漸轉向C寫引擎、然后通過內嵌的腳本引擎或協作其它語言寫游戲邏輯這類解決方案,以便提高生產效率。那么這些協作語言完全可以用各種面向對象的新秀。
只是當時的游戲引擎被鎖定到C了,推倒重來代價太大;而把和引擎配合、寫游戲邏輯的語言改成C++,一個是不能像腳本那樣簡化和加速游戲開發任務(用腳本就圖它簡便,換成一輩子精通不了的C++不是找不痛快嗎),一個是游戲邏輯這塊並沒有太高的性能需求。這等於說換C++一點好處沒有,反而帶來很多麻煩。因此在相當長一段時間里,最面向對象的游戲業反而普遍不用C++。
直到多年以后、基於C++開發的新游戲引擎/框架越來越成熟、越來越強大,游戲業這才慢慢拋棄C,轉而擁抱C++以及其它面向對象語言。
但由於學習門檻高,C/C++系還是只用在引擎內部,游戲邏輯部分還是會選用其它語言。