Programare joc 2D în C șarpe tutorial

Scopul acestui tutorial este de a preda programarea jocului 2D și limbajul C prin exemple. Autorul obișnuia să programeze jocuri la mijlocul anilor 1980 și a fost un designer de jocuri la MicroProse pentru un an în anii 90. Deși o mare parte din acestea nu este relevantă pentru programarea marilor jocuri 3D din zilele noastre, pentru jocurile casual mici va servi ca o introducere utilă.

Implementarea Snake-ului

Jocurile precum șarpele în care obiectele se deplasează pe un câmp 2D pot reprezenta obiectele de joc fie într-o grilă 2D, fie ca o serie de obiecte cu o singură dimensiune. „Obiect” aici înseamnă orice obiect de joc, nu un obiect așa cum este folosit în programarea orientată pe obiect.

Controale de joc

Tastele sunt deplasate cu W = sus, A = stânga, S = jos, D = dreapta. Apăsați Esc pentru a părăsi jocul, f pentru a comuta rata de cadru (acest lucru nu este sincronizat cu afișajul, astfel încât poate fi rapid), tasta tab pentru a comuta informațiile de depanare și p pentru a-l întrerupe. Când este întreruptă, subtitrarea se schimbă și șarpele clipește,

În șarpe sunt principalele obiecte de joc

  • Sarpele
  • Capcane și fructe

În scopul jocului, o serie de ints va conține fiecare obiect de joc (sau o parte pentru șarpe). Acest lucru vă poate ajuta și la redarea obiectelor în memoria tampon de ecran. Am conceput graficele pentru joc după cum urmează:

  • Corp orizontal de șarpe - 0
  • Corp vertical de șarpe - 1
  • Intrați în rotații de 4 x 90 grade 2-5
  • Coada în rotații de 4 x 90 grade 6-9
  • Curbe pentru schimbarea direcțiilor. 10-13
  • Apple - 14
  • Căpșune - 15
  • Banana - 16
  • Capcana - 17
  • Vizualizați fișierul grafic cu șarpe snake.gif

Deci, are sens să folosiți aceste valori într-un tip de grilă definit ca bloc [LĂțime * LĂțime]. Deoarece există doar 256 de locații în grilă, am ales să îl depozitez într-o matrice de dimensiuni unice. Fiecare coordonată de pe grila 16 x16 este un număr întreg 0-255. Am folosit informații pentru a putea crește grila. Totul este definit de #defines cu WIDTH și HEIGHT ambele 16. Deoarece graficele șarpe sunt 48 x 48 pixeli (GRWIDTH și GRHEIGHT #defines), fereastra este inițial definită ca 17 x GRWIDTH și 17 x GRHEIGHT pentru a fi doar puțin mai mare decât grila.

Acest lucru are avantaje în viteza jocului, deoarece utilizarea a doi indici este întotdeauna mai lentă decât unul, dar înseamnă că în loc să adăugați sau să scădeți 1 din coordonatele Y ale șarpelui pentru a vă deplasa pe verticală, scădeți LĂțimea. Adăugați 1 pentru a vă deplasa spre dreapta. Totuși fiind truditor, am definit de asemenea o macro l (x, y) care transformă coordonatele x și y la un moment de compilare.

Ce este o Macro?

 #define l (X, Y) (Y * Lățime) + X

Primul rând este indicele 0-15, al 2-lea 16-31 etc. Dacă șarpele se află în prima coloană și se deplasează spre stânga, atunci verificarea pentru a lovi peretele, înainte de a se deplasa spre stânga, trebuie să verifice dacă coordonata% WIDTH == 0 și pentru coordonata peretelui drept% WIDTH == WIDTH-1. % Este operatorul modulului C (ca aritmetica de ceas) și restituie restul după divizare. 31 div 16 lasă un rest de 15.

Gestionarea șarpelui

Există trei blocuri (tablouri int) utilizate în joc.

  • șarpe [], un tampon de inel
  • forma [] - Ține indici grafici Snake
  • dir [] - Ține direcția fiecărui segment din șarpe, inclusiv capul și coada.

La începutul jocului, șarpele are două segmente lungi, cu cap și coadă. Ambele pot indica în 4 direcții. Pentru nord capul este index 3, coada este 7, pentru est capul 4, coada este 8, pentru sud capul 5 și coada 9, iar pentru vest, capul 6 și coada 10 În timp ce șarpele are două segmente lung, capul și coada sunt întotdeauna la 180 de grade una de alta, dar după ce șarpele crește, acestea pot fi de 90 sau 270 de grade.

Jocul începe cu capul orientat spre nord la locația 120 și coada orientată spre sud la 136, aproximativ central. Cu un cost redus de aproximativ 1.600 de octeți de stocare, putem obține o îmbunătățire a vitezei vizibilă a jocului, ținând locațiile șarpelui în tamponul de inel al șarpelui [] menționat mai sus.

Ce este un tampon inelar?

Un buffer inel este un bloc de memorie utilizat pentru stocarea unei cozi care are o dimensiune fixă ​​și trebuie să fie suficient de mare pentru a reține toate datele. În acest caz, este doar pentru șarpe. Datele sunt împinse pe partea din față a cozii și luate înapoi. Dacă partea din față a cozii lovește sfârșitul blocului, atunci se înfășoară. Atâta timp cât blocul este suficient de mare, partea din față a cozii nu va prinde niciodată spatele.

Fiecare locație a șarpelui (adică coordonata de int singură) de la coadă la cap (adică înapoi) este stocată în memoria tampon. Acest lucru oferă avantaje de viteză pentru că, indiferent cât durează șarpele, trebuie doar schimbate capul, coada și primul segment după cap (dacă există)..

Depozitarea înapoi este benefică, de asemenea, deoarece atunci când șarpele obține mâncare, șarpele va crește atunci când va fi mutat ulterior. Acest lucru se realizează prin mutarea capului o locație în tamponul de inel și schimbarea locației vechi a capului pentru a deveni un segment. Șarpele este format dintr-un cap, segmente 0-n), apoi o coadă.

Atunci când șarpele mănâncă mâncare, variabila eatfood este setată la 1 și bifată în funcția DoSnakeMove ()

Mișcând șarpele

Folosim două variabile index, headindex și tailindex pentru a indica locațiile capului și cozii din bufferul de inel. Acestea încep de la 1 (headindex) și 0. Deci, locația 1 din tamponul de inel păstrează locația (0-255) a șarpelui de pe bord. Locația 0 deține locația cozii. Când șarpele mișcă o locație înainte, atât indexul cât și indexul sunt incrementate cu una, înfășurându-se în jurul valorii de 0 când ajung la 256. Deci acum locația care a fost capul este locul unde se află coada.

Chiar și cu un șarpe foarte lung, care înfășoară și se conturează în 200 de segmente. numai headindex, segmentul de lângă cap și tailindex se schimbă de fiecare dată când se mișcă.

Rețineți din cauza modului în care funcționează SDL, trebuie să atragem întregul șarpe fiecare cadru. Fiecare element este atras în buffer-ul cadrului, apoi este întors astfel încât să fie afișat. Acest lucru are un avantaj, însă, prin faptul că am putea atrage șarpele mișcând fără probleme câțiva pixeli, nu o poziție întreagă a grilei.