免费中文字幕在线_视频精品一区二区三区_日本在线观看视频_久久久久久亚洲精品视频_99热在线看_91精品福利

顯示游戲動(dòng)畫(huà)什么意思(子供向動(dòng)畫(huà)是什么意思)

  • 生活
  • 2023-04-19 17:23

本文適合有C語(yǔ)言基礎(chǔ)的朋友

這里是HelloGitHub推出的《講解開(kāi)源項(xiàng)目》系列,本期為您講解的是80、90后的兒時(shí)記憶,誕生于1978年經(jīng)典街機(jī)游戲《太空侵略者》也叫“小蜜蜂”的C語(yǔ)言復(fù)刻版——si78c。

這款游戲在當(dāng)時(shí)可謂是風(fēng)靡一時(shí),相信很多朋友小時(shí)候都玩過(guò)。現(xiàn)在長(zhǎng)大了,不知道有多少朋友對(duì)它的源碼感興趣呢!

原版的《太空侵略者》由大約2k行的8080匯編代碼寫(xiě)成,但匯編語(yǔ)言太過(guò)底層不方便閱讀,今天講解的開(kāi)源項(xiàng)目si78c是按照原版匯編代碼用C語(yǔ)言重寫(xiě)了一遍,并最大程度還原了原版街機(jī)硬件的中斷、協(xié)程邏輯,在運(yùn)行時(shí)其內(nèi)存狀態(tài)也幾乎與原始版本相同幾乎達(dá)到了完美的復(fù)刻,著實(shí)讓我眼前一亮!

下面就請(qǐng)跟著HelloGitHub一起抽絲剝繭,運(yùn)行這個(gè)開(kāi)源項(xiàng)目、閱讀源碼,穿越歷史感受40年前游戲設(shè)計(jì)的精妙之處!

一、快速開(kāi)始

本文的實(shí)驗(yàn)環(huán)境為Ubuntu20.04LTS,GCC版本大于GCC3

1.準(zhǔn)備工作

首先si78c使用SDL2繪制游戲窗口,所以需要安裝依賴:

$sudoapt-getinstalllibsdl2-dev

然后從倉(cāng)庫(kù)下載源碼:

$gitclonehttps://github.com/loadzero/si78c.git

此外,該項(xiàng)目會(huì)從原版的ROM中提取原版游戲的圖片、字體,所以還需要下載原版的ROM文件

2.文件結(jié)構(gòu)

在si78c源碼文件夾中新建名為inv1和bin的文件夾

$cdsi78c-master$mkdirinv1bin

然后將invaders.zip中的內(nèi)容解壓到inv1中,最后目錄結(jié)構(gòu)如下:

si78c-master├──bin├──inv1│├──invaders.e│├──invaders.f│├──invaders.g│└──invaders.h├──Makefile├──README.md├──si78c.c└──si78c_proto.h3.編譯與運(yùn)行

使用make進(jìn)行編譯:

$make

之后會(huì)在bin文件夾中生成可執(zhí)行文件,運(yùn)行即可啟動(dòng)游戲:

$./bin/si78c

游戲操控按鍵如下:

aLEFT(左移)dRIGHT(右移)11P(單人)22P(雙人)jFIRE(射擊)5COIN(投幣)tTILT(結(jié)束游戲)二、前置知識(shí)2.1簡(jiǎn)介

《太空侵略者》原版代碼運(yùn)行在8080處理器之上,其內(nèi)容全部由匯編代碼寫(xiě)成并涉及一些硬件操作,為了模擬原版街機(jī)代碼邏輯以及效果,si78c盡最大可能將匯編代碼轉(zhuǎn)換為C語(yǔ)言并使用一個(gè)Mem的結(jié)構(gòu)體模擬了原版街機(jī)的硬件,所以有些代碼從純軟件的角度來(lái)講是比較奇怪甚至是匪夷所思的,但限于篇幅原因作者無(wú)法將代碼全部貼進(jìn)文章進(jìn)行解釋,所以請(qǐng)讀者配合本人詳細(xì)注釋代碼閱讀此文。

2.2什么是協(xié)程

si78c使用了ucontex庫(kù)的協(xié)程模擬原版街機(jī)的進(jìn)程調(diào)度和中斷操作。

協(xié)程:協(xié)程更加輕便快捷、節(jié)省資源,協(xié)程對(duì)于線程就相當(dāng)于線程對(duì)于進(jìn)程。

其中ucontext提供了getcontext()、makecontext()、swapcontext()以及setcontext()函數(shù)實(shí)現(xiàn)協(xié)程的創(chuàng)建和切換,si78c中的初始化函數(shù)為init_thread。下面我們直接來(lái)看源碼中的例子:

如果這里不夠直觀可以看后面狀態(tài)轉(zhuǎn)移圖,圖文結(jié)合更加直觀。

代碼2-1

//切換協(xié)程時(shí)用的中間變量staticucontext_tfrontend_ctx;//游戲主要邏輯協(xié)程staticucontext_tmain_ctx;//游戲中斷邏輯協(xié)程staticucontext_tint_ctx;//用于切換兩個(gè)協(xié)程staticucontext_t*prev_ctx;staticucontext_t*curr_ctx;//初始化游戲協(xié)程staticvoidinit_threads(YieldReasonentry_point){//獲取當(dāng)前上下文,存儲(chǔ)在main_ctx中intrc=getcontext(&main_ctx);assert(rc==0);//指定棧空間main_ctx.uc_stack.ss_sp=main_ctx_stack;//指定棧空間大小main_ctx.uc_stack.ss_size=STACK_SIZE;//設(shè)置后繼上下文main_ctx.uc_link=&frontend_ctx;//修改main_ctx上下文指向run_main_ctx函數(shù)makecontext(&main_ctx,(void(*)())run_main_ctx,1,entry_point);/**以上內(nèi)容相當(dāng)于新建了一個(gè)叫main_cxt的協(xié)程,運(yùn)行run_main_ctx函數(shù),frontend_ctx為后繼上下文*(run_main_ctx運(yùn)行完畢之后會(huì)接著運(yùn)行frontend_ctx記錄的上下文)*協(xié)程對(duì)于線程,就相當(dāng)于線程對(duì)于進(jìn)程*只是協(xié)程切換開(kāi)銷更小,用起來(lái)更加輕便*///獲取當(dāng)前上下文存儲(chǔ)在init_ctx中rc=getcontext(&int_ctx);//指定棧空間int_ctx.uc_stack.ss_sp=&int_ctx_stack;//指定棧空間大小int_ctx.uc_stack.ss_size=STACK_SIZE;//設(shè)置后繼上下文int_ctx.uc_link=&frontend_ctx;//修改上下文指向run_init_ctx函數(shù)makecontext(&int_ctx,run_int_ctx,0);/**以上內(nèi)容相當(dāng)于新建了一個(gè)叫int_ctx的協(xié)程,運(yùn)行run_int_ctx函數(shù),frontend_ctx為后繼上下文*(run_int_ctx運(yùn)行完畢之后會(huì)接著運(yùn)行frontend_ctx記錄的上下文)*協(xié)程對(duì)于線程,就相當(dāng)于線程對(duì)于進(jìn)程*只是協(xié)程切換開(kāi)銷更小,用起來(lái)更加輕便*///給pre_ctx初始值,在第一次調(diào)用timeslice()時(shí)候能切換到main_ctx運(yùn)行prev_ctx=&main_ctx;//給curr_ctx初始值,這時(shí)候frontend_ctx還是空的//frontend_ctx會(huì)在上下文切換的時(shí)候用于保存上一個(gè)協(xié)程的狀態(tài)curr_ctx=&frontend_ctx;}

之后每次調(diào)用yield()都會(huì)使用swapcontext()進(jìn)行兩個(gè)協(xié)程間切換:

代碼2-2

staticvoidyield(YieldReasonreason){//調(diào)度原因yield_reason=reason;//調(diào)度到另一個(gè)協(xié)程上switch_to(&frontend_ctx);}//協(xié)程切換函數(shù)staticvoidswitch_to(ucontext_t*to){//給co_switch包裝了一層,簡(jiǎn)化了代碼量co_switch(curr_ctx,to);}//協(xié)程切換函數(shù)staticvoidco_switch(ucontext_t*prev,ucontext_t*next){prev_ctx=prev;curr_ctx=next;//切換到next指向的上下文,將當(dāng)前上下文保存在prev中swapcontext(prev,next);}

具體用法請(qǐng)見(jiàn)后文

由于文章篇幅有限,下面只展示的關(guān)鍵源碼部分。更詳細(xì)的源碼逐行中文注釋:

地址:https://github.com/AnthonySun256/easy_games

2.3模擬硬件

前文講過(guò),si78c是原版街機(jī)游戲像素級(jí)的復(fù)刻,甚至大部分的內(nèi)存數(shù)據(jù)也是相等的,為了做到這一點(diǎn)si78c模擬了街機(jī)的一部分硬件:RAM、ROM和顯存,它們?cè)诖a中被封裝成了一個(gè)名為Mem的大結(jié)構(gòu)體,內(nèi)存分配如下:

0000-1FFF8KROM2000-23FF1KRAM2400-3FFF7KVideoRAM4000-RAMmirror

可以看出當(dāng)年機(jī)器的RAM只有可憐的1kb大小,每一個(gè)比特都彌足珍貴需要程序認(rèn)真規(guī)劃。這里有張RAM分配情況表,更多詳情

2.4從模擬顯存到屏幕

在詳細(xì)解釋游戲動(dòng)畫(huà)顯示原理以前,我們需要先了解一下游戲的素材是怎么存儲(chǔ)的:

圖2-1

圖片來(lái)自于街機(jī)匯編代碼解讀

在街機(jī)原版ROM中,游戲素材直接以二進(jìn)制格式保存在內(nèi)存中,其中每一位二進(jìn)制表示當(dāng)前位置像素是黑還是白

比如圖2-1中顯示0x1BA0位置的內(nèi)存數(shù)據(jù)為000304781413081A3D68FCFC683D1A00八位一行排列和出來(lái)就是一個(gè)外星人帶著一個(gè)顛倒字母“Y”的圖片(圖中的內(nèi)容看起來(lái)像是旋轉(zhuǎn)了90度這是因?yàn)閳D片是一列一列存儲(chǔ)的,每8bit代表一列像素)。

si78c的作者在顯示圖片的時(shí)候直接將XY軸進(jìn)行了交換以達(dá)到旋轉(zhuǎn)圖片的效果。

我們可以找到名為Mem的結(jié)構(gòu)體,其中的m.vram(0x2400到0x3FFF)模擬了街機(jī)的顯存,這里面每一個(gè)bit代表一個(gè)像素的黑(0)白(1),從左下角向右上角進(jìn)行渲染,其對(duì)應(yīng)關(guān)系如圖2-2:

圖2-2

游戲中所有跟動(dòng)畫(huà)繪制有關(guān)的代碼都是在修改這部分區(qū)域的數(shù)據(jù),例如DrawChar()、ClearPlayField()、DrawSimpSprite()等等。那么怎么讓模擬現(xiàn)存的內(nèi)容顯示到玩家的屏幕上呢?注意看代碼3-1中在循環(huán)的末尾調(diào)用了render()函數(shù),它負(fù)責(zé)的就挨個(gè)讀取模擬顯存中的內(nèi)容并在窗口上有像素塊的地方渲染一個(gè)像素塊。

仔細(xì)想想不難發(fā)現(xiàn),這種先修改模擬顯存再統(tǒng)一繪制的***其實(shí)沒(méi)有多省事,甚至有些怪異。這是因?yàn)閟i78c模擬了街機(jī)硬件的顯示過(guò)程:修改相應(yīng)的顯存然后硬件會(huì)自動(dòng)將顯存中的內(nèi)容顯示到屏幕上。

2.5按鍵檢測(cè)

代碼3-1中的input()函數(shù)負(fù)責(zé)檢測(cè)并存儲(chǔ)用戶的按鍵信息,其底層依賴SDL庫(kù)。

三、首次啟動(dòng)

si78c和所有的C程序一樣,都是從main()函數(shù)開(kāi)始運(yùn)行:

代碼3-1

intmain(intargc,char**argv){//初始化SDL和游戲窗口init_renderer();//初始化游戲init_game();intcredit=0;size_tframe=-1;//開(kāi)始游戲協(xié)程調(diào)度與模擬觸發(fā)中斷while(1){frame++;//處理按鍵輸入input();//如果退出標(biāo)志置位推出循環(huán)清理游戲內(nèi)存if(exited)break;//preservestimingcompatibilitywithMAME//保留與MAME(一種街機(jī))的時(shí)序兼容性if(frame==1)credit--;/***執(zhí)行其他進(jìn)程大概CRED1的時(shí)間*(為什么是這個(gè)數(shù)我也不知道,應(yīng)該是估計(jì)值)*(原作者也說(shuō)這種定時(shí)***不是很準(zhǔn)確但不影響游戲效果)*/credit+=CRED1;loop_core(&credit);//設(shè)置場(chǎng)中間中斷標(biāo)志位,在下面的loop_core()中會(huì)切換到int_ctx執(zhí)行一次,然后清除標(biāo)志位irq(0xcf);//道理同上credit+=CRED2;loop_core(&credit);//設(shè)置垂直消隱中斷標(biāo)志位,下個(gè)循環(huán)時(shí)候loop_core()中會(huì)切換到int_ctx執(zhí)行一次,然后清除標(biāo)志位irq(0xd7);//繪制游戲界面render();}fini_game();fini_renderer();return0;}

啟動(dòng)過(guò)程如圖所示:

圖3-1

游戲原版代碼(8080匯編)使用的是中斷驅(qū)動(dòng)(這種編程方式和硬件有關(guān),具體內(nèi)容可以自行了解什么是中斷)配合協(xié)程多任務(wù)操作。為了模擬原版游戲邏輯作者以main()中大循環(huán)作為硬件行為模擬中心(實(shí)現(xiàn)中斷管理、協(xié)程切換、屏幕渲染)。游戲大約三分之一的時(shí)間在運(yùn)行主線程,主線程會(huì)被midscreen和vblank兩個(gè)中斷搶占,代碼3-1中兩個(gè)irq()就實(shí)現(xiàn)了對(duì)中斷的模擬(設(shè)置對(duì)應(yīng)的變量作為標(biāo)志位)。

在第一次進(jìn)入loop_core()時(shí)其流程如下:

圖3-2

因?yàn)閥ield_rason這個(gè)變量是static類型其默認(rèn)值為零

代碼3-2

//根據(jù)游戲狀態(tài)標(biāo)志切換到相應(yīng)的上下文staticintexecute(intallowed){int64_tstart=ticks;ucontext_t*next=NULL;switch(yield_reason){//剛啟動(dòng)時(shí)yield_reason是0表示YIELD_INITcaseYIELD_INIT://當(dāng)需要延遲的時(shí)候會(huì)調(diào)用timeslice()將yield_reason切換為YIELD_TIMESLICE//模擬時(shí)間片輪轉(zhuǎn),這個(gè)時(shí)候會(huì)切換回上一個(gè)運(yùn)行的任務(wù)(統(tǒng)共就倆協(xié)程),實(shí)現(xiàn)時(shí)間片輪轉(zhuǎn)caseYIELD_TIMESLICE:next=prev_ctx;break;caseYIELD_INTFIN://處理完中斷后讓int_ctx休眠,重新運(yùn)行main_ctxnext=&main_ctx;break;//玩家死亡、等待開(kāi)始、外星人入侵狀態(tài)caseYIELD_PLAYER_DEATH:caseYIELD_WAIT_FOR_START:caseYIELD_INVADED:init_threads(yield_reason);enable_interrupts();next=&main_ctx;break;//退出游戲caseYIELD_TILT:init_threads(yield_reason);next=&main_ctx;break;default:assert(FALSE);}yield_reason=YIELD_UNKNOWN;//如果有中斷產(chǎn)生if(allowed&&interrupted()){next=&int_ctx;}switch_to(next);returnticks-start;}

需要注意的是,在execute()中進(jìn)行了協(xié)程的切換,這個(gè)時(shí)候execute()的運(yùn)行狀態(tài)就被保存在了變量frontend_ctx之中,指針prev_ctx更新為指向frontend_ctx,指針curr_ctx更新為指向main_ctx,其過(guò)程如圖所示:

圖3-3

實(shí)現(xiàn)解釋請(qǐng)見(jiàn)代碼2-2

當(dāng)execute()返回時(shí)他會(huì)按照正常的執(zhí)行流程返回到loop_core(),就像它從未被暫停過(guò)一樣。

仔細(xì)觀察main_init中主循環(huán)我們可以發(fā)現(xiàn)其多次調(diào)用timeslice()函數(shù)(例如OneSecDelay()中),通過(guò)這個(gè)函數(shù)我們就可以實(shí)現(xiàn)main_ctx與frontend_ctx間的時(shí)間片輪轉(zhuǎn)操作,其過(guò)程如下:

圖3-4

在main_init()中主要做了如下事情:

在玩家投幣前,游戲會(huì)依靠main_init()循環(huán)播放動(dòng)畫(huà)吸引玩家

如果只翻看main_init()中出現(xiàn)的函數(shù)我們會(huì)發(fā)現(xiàn)代碼中并未涉及太多的游戲邏輯,例如外星人移動(dòng)、射擊,玩家投幣檢查等內(nèi)容好像根本不存在一樣,更多的時(shí)候是在操縱內(nèi)存、設(shè)置標(biāo)志位。那么有關(guān)游戲游戲邏輯處理相關(guān)的函數(shù)又在哪里呢?這部分內(nèi)容將在下面揭秘。

四、模擬中斷

在代碼3-1中l(wèi)oop_core()函數(shù)被兩個(gè)irq()分隔了開(kāi)來(lái)。我們之前提到main()中的大循環(huán)本質(zhì)上是在模擬街機(jī)的硬件行為,在真實(shí)的機(jī)器上中斷是只有在觸發(fā)時(shí)才會(huì)執(zhí)行,但在si78c上我們只能通過(guò)在loop_core()之間調(diào)用irq()來(lái)模擬產(chǎn)生中斷并在execute()中輪詢中斷狀態(tài)來(lái)判斷是不是進(jìn)入中斷處理函數(shù),過(guò)程如下:

這時(shí)它的協(xié)程狀態(tài)如下:

有兩種中斷:midscreen_int()與vblank_int()這兩種中斷會(huì)輪流出現(xiàn)。

代碼4-1

//處理中斷的函數(shù)staticvoidrun_int_ctx(){while(1){//0xcf=RST1opcode(call0x8)//0xd7=RST2opcode(call0x16)if(irq_vector==0xcf)midscreen_int();elseif(irq_vector==0xd7)vblank_int();//使能中斷enable_interrupts();yield(YIELD_INTFIN);}}

我們先來(lái)看midscreen_int():

代碼4-2

/***在光將要擊中屏幕中間(應(yīng)該是模擬老式街機(jī)的現(xiàn)實(shí)原理)時(shí)由中斷觸發(fā)*主要處理游戲?qū)ο蟮囊苿?dòng)、開(kāi)火、碰撞等等的檢測(cè)更新與繪制(具體看函數(shù)GameObj0到4)*以及確定下一個(gè)將要繪制哪個(gè)外星人,檢測(cè)外星人是不是入侵成功了*/staticvoidmidscreen_int(){//更新vblank標(biāo)志位m.vblankStatus=BEAM_MIDDLE;//如果沒(méi)有運(yùn)動(dòng)的游戲?qū)ο螅祷豬f(m.gameTasksRunning==0)return;//在歡迎界面且沒(méi)有在演示模式,返回(只在游戲模式和demo模式下繼續(xù)運(yùn)行)if(!m.gameMode&&!(m.isrSplashTask&0x1))return;//運(yùn)行g(shù)ameobjects但是略過(guò)第一個(gè)入口(玩家)RunGameObjs(u16_to_ptr(PLAYER_SHOT_ADDR));//確定下一個(gè)將要繪制的外星人CursorNextAlien();}

在這一部分中RunGameObjs()函數(shù)基本上包括了玩家的移動(dòng)和繪制,玩家子彈和外星人子彈的移動(dòng)、碰撞檢測(cè)、繪制等等所有游戲邏輯的處理,CursorNextAlien()則找到要繪制的下一個(gè)活著的外星人設(shè)置標(biāo)志位等待繪制,并且檢測(cè)外星飛船是否碰到了屏幕底端。

運(yùn)行結(jié)束后會(huì)返回到run_int_ctx()繼續(xù)運(yùn)行直到y(tǒng)ield(YIELD_INTFIN)表示協(xié)程切換回execute(),并在execute()中重新將next設(shè)定為main_ctx使main_init()能夠繼續(xù)運(yùn)行(詳情見(jiàn)代碼3-2)。

接下來(lái)是vblank_int():

代碼4-3

/***當(dāng)光擊中屏幕最后一點(diǎn)(模擬老式街機(jī)原理)時(shí)觸發(fā)*主要處理游戲結(jié)束、投幣、游戲中各種事件處理、播放演示動(dòng)畫(huà)*/staticvoidvblank_int(){//更新標(biāo)志位m.vblankStatus=BEAM_VBLANK;//計(jì)時(shí)器減少m.isrDelay--;//看看是不是結(jié)束游戲CheckHandleTilt();//看看是不是投幣了vblank_coins();//如果游戲任務(wù)沒(méi)有運(yùn)行,返回if(m.gameTasksRunning==0)return;//如果在游戲中的話if(m.gameMode){TimeFleetSound();m.shotSync=m.rolShotHeader.TimerExtra;DrawAlien();RunGameObjs(u16_to_ptr(PLAYER_ADDR));TimeToSaucer();return;}//如果投幣過(guò)了if(m.numCoins!=0){//xref005dif(m.waitStartLoop)return;m.waitStartLoop=1;//切換協(xié)程到等待開(kāi)始循環(huán)yield(YIELD_WAIT_FOR_START);assert(FALSE);//不會(huì)再返回了}//如果以上事情都沒(méi)發(fā)生,播放演示動(dòng)畫(huà)ISRSplTasks();}

其主要作用一是檢測(cè)玩家是否想要退出游戲或是進(jìn)行了投幣操作,如果已經(jīng)處于游戲模式中則依次播放艦隊(duì)聲音、繪制在midscreen_int()中標(biāo)記出的外星人、運(yùn)行RunGameObjs()處理玩家和外星人開(kāi)火與移動(dòng)事件、TimeToSaucer()隨機(jī)生成神秘飛碟。如果未在游戲模式中則進(jìn)入ISRSplTasks()調(diào)整當(dāng)前屏幕上應(yīng)該播放的動(dòng)畫(huà)。

我們可以注意到,如果玩家進(jìn)行了投幣會(huì)進(jìn)入if(m.numCoins!=0)里,并調(diào)用yield(YIELD_WAIT_FOR_START)后面會(huì)提示這個(gè)函數(shù)不會(huì)再返回。在si78c的代碼中許多地方都會(huì)有這樣的提示,這里并不是簡(jiǎn)單的調(diào)用一個(gè)不會(huì)返回的函數(shù)進(jìn)行套娃。

觀察代碼3-2可以發(fā)現(xiàn)在YIELD_PLAYER_DEATH、YIELD_WAIT_FOR_START、YIELD_INVADED、YIELD_TILT這四種分支中都調(diào)用了init_threads(yield_reason),在這個(gè)函數(shù)里會(huì)重置int_ctx與main_ctx的堆棧并重新綁定調(diào)用run_main_ctx時(shí)的參數(shù)為yield_reason,這樣在下一次執(zhí)行的時(shí)候run_main_ctx就會(huì)根據(jù)中斷的指示跳轉(zhuǎn)到合適的分支去運(yùn)行。

五、巧妙地節(jié)省RAM

開(kāi)篇的時(shí)候提到過(guò),當(dāng)年街機(jī)的RAM只有可憐的1kb大小,這樣小的地方必定無(wú)法讓我們存儲(chǔ)屏幕上每個(gè)對(duì)象的信息,但是玩家的位置、外星人的位置以及它們的子彈、屏幕上的盾牌損壞情況都是會(huì)實(shí)時(shí)更新的,如何做到這一點(diǎn)呢?

我發(fā)現(xiàn)《太空侵略者》游戲區(qū)域內(nèi)容分布還是很有規(guī)律的,特殊飛船(飛碟)只會(huì)出現(xiàn)在屏幕上端,盾牌和玩家的位置不會(huì)改變,只有子彈的位置不好把握,所以仔細(xì)研讀代碼,從DrawSpriteGeneric()可以看出,游戲?qū)τ谂鲎驳臋z測(cè)只是簡(jiǎn)單的判斷像素塊是否重合,對(duì)于玩家子彈到底擊中了什么在PlayerShotHit()函數(shù)進(jìn)行判斷時(shí),則只需要判斷子彈垂直方向坐標(biāo)(Y坐標(biāo)),如果>=216則是撞到上頂,>=206則是擊中神秘飛碟,其他則是擊中護(hù)盾或者外星人的子彈。且由于外星飛船的是成組一起運(yùn)動(dòng),只需要記住其中一個(gè)的位置就能推算出整體每一個(gè)外星飛船的坐標(biāo)。

這樣算下來(lái),程序只需要保存外星飛船的存活狀態(tài)、當(dāng)前艦隊(duì)的相對(duì)移動(dòng)位置、玩家和外星人子彈信息,在需要檢測(cè)碰撞時(shí)則去讀取顯存中的像素信息進(jìn)行對(duì)比然后反推當(dāng)前時(shí)哪兩樣物體發(fā)生了碰撞即可,這種***相比存儲(chǔ)每一個(gè)對(duì)象的信息節(jié)省了不少資源。

六、結(jié)語(yǔ)

si78c不同于其他代碼,它本質(zhì)上是對(duì)硬件和匯編代碼的仿真,希望通過(guò)本文的源碼講解,讓更多人看到當(dāng)年程序員們?cè)谟邢拶Y源下***出優(yōu)秀游戲的困難,還有代碼設(shè)計(jì)的精妙。

最后,感謝本項(xiàng)目作者所做的一切,沒(méi)有他的付出也就不會(huì)有這篇文章。如果您覺(jué)得這篇文章還不錯(cuò),歡迎分享給更多人。

猜你喜歡

主站蜘蛛池模板: 国产91精选 | 欧美二三区 | 久久三区| 一区二区三区精品 | 久久91| 成人二区 | 欧美一级做性受免费大片免费 | 欧美一级特黄aaaaaa大片在线观看 | 国产视频色 | 先锋av资源网| 中文字幕成人 | 国产成人精品久久二区二区 | 久久国产高清 | 国产精品一区二区在线 | 国产精品一二区 | 成人在线看片 | 国产精品一区二区久久久 | 狠狠干影院| yiren22综合网成人 | 日韩成人免费视频 | 99影视 | 亚洲免费视频大全 | 精品国产青草久久久久福利 | 91精品久久久久久久久久 | 国产91久久久久 | 国产精品毛片一区二区在线看 | 中文字幕2021 | 91在线播 | 久草网站 | 国产大胆自拍 | 欧美视频网站 | 日本精品久久久一区二区三区 | 黄色毛片在线看 | 国产午夜久久 | 国产免费一区 | 天天综合网7799精品 | 午夜久久久 | 99久久婷婷国产综合亚洲 | 久久精品国产99 | 美女久久| 久久9精品| 欧美精品福利视频 | 亚洲香蕉精品 | 久久国产一区 | 国产女人高潮视频在线观看 | 不用播放器的毛片 | 99视频免费看 | 国产一区二区精品丝袜 | 欧美日韩国产在线看 | 日韩一区欧美一区 | 国产精品美女一区二区三区四区 | h成人在线 | 国产区视频在线观看 | 黄色一级片 | 亚洲二区在线视频 | 精品永久免费 | 暖暖成人免费视频 | 91精品久久久久久综合五月天 | 特级淫片裸体免费看 | 国产高清一区二区 | 成人看片免费网站 | 麻豆精品一区二区 | 青青草一区二区三区 | 在线免费观看毛片 | 精品久久久久一区二区国产 | 99精品国产高清在线观看 | 一区二区三区日韩 | 色视频网站在线观看 | 小情侣高清国产在线播放 | 国产aⅴ | 欧日韩不卡在线视频 | 亚洲 欧美 综合 | 久久久久久九九九 | 日本一区二区精品视频 | 亚洲成人一区二区 | 国产综合欧美 | 免费在线观看国产 | 久久久久久久久国产成人免费 | 激情网站免费观看 | 欧洲尺码日本国产精品 | 中文字幕一区二区三区乱码图片 | 蜜桃中文字幕 | 亚洲理论电影在线观看 | 欧美一级在线观看 | 在线免费观看av片 | 91视频在线看 | 91精品视频在线 | 在线观看免费av网站 | 日韩在线观看视频一区二区 | 一级做a| 欧美日韩综合精品 | 久久人人爽人人爽人人片亚洲 | 久久国产成人 | 操久久 | 91在线| 伊人二区 | 91亚洲国产成人久久精品网站 | 日韩精品专区 | 色www精品视频在线观看 | 剑来高清在线观看 | 国产精品久久久一区 | 成人欧美一区二区三区黑人孕妇 | 亚洲伊人久久综合 | 日韩一区二区成人 | 啊v视频 | 久草热8精品视频在线观看 黄色片网站视频 | 中文字幕亚洲第一 | 国产综合视频在线观看 | 99re在线 | 国产欧美精品区一区二区三区 | 成人精品视频在线观看 | 亚洲视频一区在线 | 欧美成人精品一区二区男人看 | 久久亚洲一区二区三区四区 | 欧美国产一区二区 | 91精品国产综合久久久蜜臀图片 | 国产91色在线 | 亚洲 | 欧美成人精品一区二区男人看 | 亚洲精品久久久久久下一站 | 伊人网网站 | 中文字幕在线观看 | 日韩av成人| 亚洲三区电影 | 国产精品久久久久久久久久久久冷 | 亚洲精品一区二区三区 | 久久精品网 | 国产精品久久久久久久久久久久 | av大片 | 国产黄色大片网站 | 欧美日韩精品在线一区 | 自拍偷拍欧美 | 久久精品国产视频 | 天天插天天干 | av大片| 91极品视频在线观看 | 国产成人免费视频网站高清观看视频 | 国产精品视屏 | 日韩拍拍 | 日韩精品一区二区三区四区视频 | 999精品视频 | 亚洲成人精品在线 | 日韩欧美久久 | 伊人网站 | 一区二区三区欧美在线 | 久久久精品一区二区 | 久久亚洲精品裙底抄底 | 91精品国产91久久久久久吃药 | 国产精品久久久久久久久免费高清 | 天天操夜夜干 | 欧美日韩一区二区电影 | 久久国| 欧美在线视频一区二区 | 国产精品视频99 | 奇米影视四色777me | 91亚洲精品乱码久久久久久蜜桃 | 欧美二区在线 | 天天草狠狠干 | 国产视频网 | 中文字幕高清一区 | 国产欧美日本 | 成人不卡| 日韩城人网站 | 国产aⅴ | 欧美在线观看一区 | 国产精品久久久久久久久软件 | 久久九九国产精品 | 黄瓜av | 国产精品久久久久久久久久久久久 | 国产激情视频在线 | 91丁香婷婷综合久久欧美 | 毛片搜索| 龙珠z普通话国语版在线观看 | 久久久久久久久一区二区三区 | 久久精品视频网站 | 97视频在线免费观看 | 国产精品久久久久久吹潮 | 激情网站免费 | 国产精品国产三级国产a | 日韩成人免费 | 国产一级网站 | 色偷偷噜噜噜亚洲男人 | 婷婷亚洲五月 | 亚洲日本乱码一区两区在线观看 | 国产高清自拍 | 狠狠久久婷婷 | 成人欧美一区二区三区在线播放 | 久久久久国产精品一区二区三区 | 露娜同人18av黄漫网站 | 亚洲系列 | 久久精品影视 | 亚洲国产一区二区在线 | 亚洲欧美一区二区三区在线 | 久久毛片 | 麻豆精品一区二区 | 国产剧情一区二区 | 国产精品久久久久久久9999 | 欧美在线观看免费观看视频 | 亚洲第一网站 | 国产成人精品一区二区在线 | 91九色视频pron | 亚洲视频在线一区 | 欧美日韩亚洲另类 | 亚洲啪啪网站 | 日韩欧美一区二区在线观看视频 | 久久精品毛片 | 特级毛片| 国产一区二区视频免费 | 99久久国产| 亚洲综合区 | 欧美性18| 91精品久久| 狠狠躁日日躁夜夜躁东南亚 | 亚洲一区二区在线视频 | 日韩精品免费在线观看 | 国产欧美精品一区二区三区 | 色综合二区 | 日韩三级视频 | 99色综合| 91激情视频 | caoporn国产精品免费公开 | 久草视| av在线一区二区 | 国产精品视屏 | 国产精品日韩一区二区 | 亚洲精品视频国产 | 欧洲美女性开放视频 | 超碰首页 | 色综合久久久久 | 欧美jizzhd精品欧美巨大免费 | 台湾av片| 韩国三级中文字幕hd久久精品 | 国产欧美久久久久久 | 精品久久久久久久 | 91小视频| 久久久久一区二区三区 | 国产精品香蕉在线观看 | 91麻豆产精品久久久久久 | 久久中文字幕一区 | 国产免费av大片 | 91精品国产综合久久精品 | 精品久久久久久亚洲综合网 | 一区| 亚洲欧美精品 | 性色在线| 精品国产欧美一区二区三区成人 | 丁香婷婷综合激情五月色 | 成人免费毛片高清视频 | www.国产精品 | 免费成人av在线 | 欧美成人a∨高清免费观看 在线视频成人 | 久久久精品日本 | 成人久久精品 | 日韩日韩 | 欧美综合激情 | 国产精品国产 | 伊人久久爱 | 国产成人亚洲综合 | 女人久久久 | 免费黄色小视频 | 一区二区毛片 | 日日干天天操 | 在线精品日韩 | 国产精品视频区 | 婷婷毛片| 日韩精品一区二区三区中文在线 | 超碰人人操 | 欧美大片在线看免费观看 | 国产一区免费在线观看 | 久久国产精品免费一区二区三区 | 婷婷网址 | 91九色国产视频 | 久久久久久国产 | 日韩xxxbbb| 久久久91精品国产一区二区 | 午夜在线小视频 | 欧美中文字幕一区 | 国产精品久久久久久久久久 | 精品久久国产 | 一区二区三区四区免费观看 | 少妇久久久 | av片在线观看 | 欧美成人精品一区二区 | 日韩在线成人 | 亚洲视频在线免费观看 | 色欧美日韩 | 成人精品视频99在线观看免费 | 奇米av| 不卡一区二区三区四区 | 国产福利91精品一区二区三区 | 欧美亚洲综合久久 | 午夜社区 | 毛片免费观看视频 | 国产精品中文字幕在线播放 | 色精品视频 | 人人人射 | 欧美五月婷婷 | 国产一区二区三区免费播放 | 中文在线一区二区 | 男女免费在线观看 | 亚洲国产精品久久 | www.干| 伊人yinren22综合开心 | 久久中文视频 | 日韩成人免费av | 人人人射| 成人精品鲁一区一区二区 | 国产一区影院 | 欧美激情亚洲 | 亚洲精品一二三区 | 欧美日韩视频在线观看一区 | 欧美日韩一区在线 | 久久99精品久久久久久园产越南 | 99这里只有精品 | 99久久婷婷国产综合精品电影 | 欧美卡一卡二 | 亚洲精品a | 日韩大片免费播放 | 亚洲日本欧美日韩高观看 | 亚洲一区在线免费观看 | 中文字幕在线观看一区二区三区 | 黄色精品 | 久久蜜桃av一区二区天堂 | 天天艹夜夜艹 | 一区二区中文字幕 | 中文字幕综合在线 | 欧美视频在线观看不卡 | 国产精品美女视频一区二区三区 | 超碰在线播| 99精品久久精品一区二区爱城 | 欧美一区免费 | 成人高清| 日韩欧美视频 | 欧美日韩中文字幕 | 久久精品免费电影 | 久草在线视频网 | 日本精品久久 | 中文字幕一区二区三区乱码在线 | 久久久久久综合 | 嫩草视频入口 | 国产一区二区视频在线观看 | 日穴视频在线观看 | 不卡一区二区三区视频 | 国产野精品久久久久久久不卡 | 中文字幕第一页在线 | 日韩成人| 全毛片| 欧美一区久久 | 精品在线播放 | 国产在线观看一区二区三区 | 一区二区观看 | 久久精品一 | 在线中文字幕观看 | 日韩午夜一级片 | 久久精品一区二区 | 啵啵羞羞影院 | 国产日韩欧美一区 | 欧美精品免费在线观看 | av久久| 国产精品久久久久久久久久免费看 | 懂色中文一区二区在线播放 | 少妇精品视频在线观看 | 国产高清不卡在线 | 国产精品欧美一区二区三区 | 91精品视频在线播放 | 欧美 日韩 国产 一区 | 亚洲色图一区二区三区 | 国产精品精品 | 亚洲国产精品一区二区第一页 | 成人久久久精品乱码一区二区三区 | 日韩免费观看视频 | 日韩欧美在线播放视频 | 日韩在线亚洲 | 国产一区二区三区四区在线观看 | 一本大道久久a久久精二百 国产精品片aa在线观看 | 高清日韩av | 午夜免费福利在线 | 免费激情小视频 | 日韩欧美中文在线 | 国产一区二区在线视频观看 | 欧美国产精品一区二区 | 日韩免费在线视频 | 国产在线中文字幕 | www.日韩在线观看 | 国产中文字幕在线观看 | 性视频黄色 | 99国产精品久久久 | 日本久久精品电影 | 一区二区三区观看视频 | 亚洲国产精品一区二区第一页 | 99国产精品99久久久久久 | 亚洲毛片 | 一级一级一级毛片 | 日韩高清国产一区在线 | 成人免费在线视频观看 | 欧美污污 | 亚洲成人一区二区三区 | 成人三级网址 | 精品无人乱码一区二区三区 | av在线官网 | 五月天婷婷精品 | 精品亚洲一区二区三区 | 大胆裸体gogo毛片免费看 | 国产亚洲欧美精品永久 | 亚洲成人久久久 | 国产精品2区 | 91视频免费看 | 一区二区中文字幕在线观看 | 国产免费一区二区 | 午夜影视免费观看 | 久久久91精品国产一区二区三区 | 视频一区在线播放 | 天堂资源最新在线 | 国产v片| 人人射人人 | 综合久久网 | 毛片免费观看 | 精品免费视频 | 日韩中文字幕一区 | 国产精品原创av片国产免费 | 国产日产精品一区二区三区四区 | 日韩精品在线播放 | 成人1区2区 | 最近最新中文字幕 | 成人欧美一区二区三区白人 | 欧美成人黄色小说 | 国产免费自拍 | 一色视频 | 精品久久久蜜桃 | 97人人草| 久久久久国产成人精品亚洲午夜 | 精品久久精品 | 在线国产一区 | 国产乱码一区二区三区 | 亚洲精品久久久久久一区二区 | 中文字幕在线观看www | 午夜天 | 亚洲精品电影在线一区 | 麻豆网址| 久久不射网 | 天天操网址 | 在线 丝袜 欧美 日韩 制服 | 亚洲一区二区精品在线观看 | 亚洲精品九九 | 久久99精品久久久久婷婷暖91 | 亚洲毛片在线 | 久久精品无码一区二区三区 | 国产福利在线观看视频 | 欧美日韩一区二区电影 | 国产精品久久久久久久天堂 | 午夜精品久久久久久 | 97爱爱爱 | 97在线观看视频 | 亚洲国产精品久久久男人的天堂 | 激情91| 国产精品白浆 | 成人三级在线 | 久久综合99re88久久爱 | 欧美在线高清 | 亚洲精品乱码久久久久久按摩观 | 日韩精品一区二区三区在线 | 久草精品视频 | 自拍偷拍亚洲欧美 | 97国产一区二区精品久久呦 | 91久久久久久久久久久久久久 | 91麻豆精品国产91久久久久 | 不卡视频一区二区三区 | 精品国产一区二区三区久久久蜜 | 一区二区三区免费网站 | 成人久久18免费 | 国产一区二区三区不卡在线观看 | 午夜天堂精品久久久久 | 一级免费毛片 | 91中文字幕在线观看 | 免费观看黄色一级大片 | 天天看天天做 | 亚洲精品乱码久久久久久蜜桃 | 亚洲国产免费 | 99精品视频一区二区三区 | 国产在线观 | 一区二区久久久 | 一区二区三区观看视频 | 欧美一级黄色片网站 | www.一区| 亚洲 自拍 另类 欧美 丝袜 | 一级大毛片 | 亚洲精品91 | 亚洲视频在线一区 | 国产成人综合在线观看 | 午夜精品久久久久久久久久久久久 | www.99精品| 国产午夜视频 | 久久精品久久久久电影 | 亚洲精品一区二区三区樱花 | 久久久久九九九九 | 在线观看av网站永久 | 国产中文在线 | 亚洲精品一区久久久久久 | 日日干,天天干 | 可以免费看黄的网站 | 日本一区二区成人 | 久久国产精品免费一区二区三区 | 精品久久久久久国产 | 美女h视频| 精品九九九 | 韩日中文字幕 | 不卡日韩在线 | 91在线精品秘密一区二区 | 久久一区二区三区四区五区 | 久久精品黄 | 国产高清一区二区 | 日本人做爰大片免费观看一老师 | 国产精品99久久久久久久vr | 久久99精品一区二区三区三区 | 精品一区二区三区久久久 | 操操操av | 久久草视频 | 国产福利网站 | 一区二区欧美视频 | 午夜免费 | 99视频免费播放 | 欧美精品一区二区三区在线 | 亚洲精品视频在线观看免费 | 免费的一级视频 | 操操操日日日 | 久久久久久久久久久久网站 | 精品久久一区二区 | 欧洲精品视频一区 | 欧美在线视频一区 | 色吟av| 天天影视网色香欲综合网无拦截 | 国产一区二区三区四区三区 | 久草精品视频 | 91网在线播放 | 四虎中文字幕 | 国产高清精品一区二区三区 | 伊人春色成人 | 中文字幕一区二区三区乱码图片 | 99re国产| 亚洲一级黄色 | 国产激情免费 | 国产精品久久久久久久久久久新郎 | 亚洲免费网站在线观看 | 中文字幕在线免费看 | 久久久网| 久久久天堂国产精品女人 | 欧美精品一区在线 | 成人a在线观看 | 91高清视频 | 日本中文在线 | 伊人一区 | 日日网| 天天影视色香欲 | 一区二区三区精品视频免费看 | 国产日韩欧美 | 久久久久中文字幕 | 亚洲免费片 | 亚洲精品自在在线观看 | 在线久草 | 欧美综合视频在线观看 | 午夜欧美 | 国产精品久久久久无码av | 日本精品视频在线观看 | 亚洲欧美视频在线 | 亚洲精品一区二区三区在线观看 | 婷婷免费视频 | 黄色最新网站 | 成人免费视频观看视频 | 中文字幕免费在线 | 午夜国产羞羞视频免费网站 | 伊人久久精品久久亚洲一区 | 伊人激情综合 | 亚洲综合色自拍一区 | 欧美a区 | 午夜一级毛片 | 久久涩 | 四虎成人永久 | 中文字幕欧美在线 | 国产精品成人3p一区二区三区 | 成人影音| 激情在线观看视频 | 蜜桃官网 | 国产一区二区三区在线免费观看 | 久久久久99| 久久久久久精 | 奇米影视四色777me | 人人做人人澡人人爽欧美 | 亚洲一区中文字幕在线观看 | 看免费的毛片 | 免费观看特级毛片 | 中文字幕加勒比 | 在线免费观看黄 | 国产精品久久综合 | 久久激情综合 | 午夜精品久久久久久久男人的天堂 | 一区二区三区中文字幕 | 国产精品久久久久久久久久 | 五月综合婷 | 无码一区二区三区视频 | 懂色一区二区三区免费观看 | jizz在线播放 | 日韩精品 电影一区 亚洲 | 国产精品久久久久免费 | 国产99久久久精品视频 | 久久精品国产一区 | 韩国av片在线观看 | 精品网站999www | 国产中文一区 | 午夜精品久久久久久久男人的天堂 | av片在线观看网站 | 成人在线视频观看 | 国产农村妇女精品久久 | 国产电影一区二区三区图片 | av一区在线观看 | 日日夜夜摸 | 999国内精品永久免费视频 |