Kā uzrakstīt savu pirmo Android spēli Java

Autors: John Stephens
Radīšanas Datums: 1 Janvārī 2021
Atjaunināšanas Datums: 19 Maijs 2024
Anonim
How to Make a Tic Tac Toe Game in Android [Java 2020]
Video: How to Make a Tic Tac Toe Game in Android [Java 2020]

Saturs


Ir daudz iespēju, kā izveidot spēli Android, un viens svarīgs veids ir to darīt no nulles Android Studio ar Java. Tas dod jums maksimālu kontroli pār to, kā vēlaties, lai spēle izskatās un izturētos, un process iemācīs jums prasmes, kuras varat izmantot arī daudzos citos scenārijos - neatkarīgi no tā, vai veidojat lietotnes šļakatu ekrānu vai vienkārši vēlaties pievienojiet dažas animācijas. Paturot to prātā, šī apmācība parādīs, kā izveidot vienkāršu 2D spēli, izmantojot Android Studio un Java. Visu kodu un resursus varat atrast vietnē Github, ja vēlaties sekot līdzi.

Uzstādīt

Lai izveidotu savu spēli, mums būs jāizskata daži īpaši jēdzieni: spēles cilpas, diegi un audekli. Sākumā sāciet Android Studio darbību. Ja jums tas vēl nav instalēts, skatiet mūsu Android Studio pilnu ievadu, kurā sniegts instalēšanas process. Tagad sāciet jaunu projektu un pārliecinieties, ka esat izvēlējies veidni “Tukša aktivitāte”. Šī ir spēle, tāpēc, protams, jums nav vajadzīgi tādi elementi kā FAB poga, kas sarežģī lietas.


Pirmais, ko vēlaties darīt, ir mainīt AppCompatActivity uz Darbība. Tas nozīmē, ka mēs neizmantojam darbību joslas funkcijas.

Līdzīgi mēs arī vēlamies padarīt mūsu spēli pilnekrāna režīmā. Pievienojiet šo kodu vietnei onCreate () pirms zvana uz setContentView ():

getWindow (). setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); this.requestWindowFeature (Window.FEATURE_NO_TITLE);

Ņemiet vērā: ja jūs izrakstāt kādu kodu un tas tiek pasvītrots sarkanā krāsā, tas, iespējams, nozīmē, ka jums jāimportē klase. Citiem vārdiem sakot, jums jāsaka Android Studio, ka vēlaties izmantot noteiktus paziņojumus un padarīt tos pieejamus. Ja jūs vienkārši noklikšķināt uz pasvītrotā vārda jebkur un pēc tam nospiežat taustiņu kombināciju Alt + Enter, tas tiks darīts jums automātiski!

Spēles skata izveidošana

Iespējams, esat pieradis pie lietotnēm, kas izmanto XML skriptu, lai definētu skatu izkārtojumu, piemēram, pogas, attēlus un etiķetes. Tāda ir līnija setContentView dara mūsu labā.


Bet atkal šī ir spēle, kas nozīmē, ka tai nav jābūt pārlūkprogrammas logiem vai ritinātiem pārstrādātāju skatiem. Tā vietā mēs vēlamies parādīt audeklu. Operētājsistēmā Android Studio audekls ir tieši tāds pats kā mākslā: tas ir nesējs, uz kura mēs varam zīmēt.

Tāpēc mainiet šo rindiņu, lai lasītu šādi:

setContentView (jauns GameView (šis))

Jūs redzēsit, ka tas atkal ir pasvītrots ar sarkanu krāsu. Bet tagad nospiežot taustiņu kombināciju Alt + Enter, jums nav iespēju importēt mācību priekšmetu. Tā vietā jums ir iespēja izveidot klase. Citiem vārdiem sakot, mēs gatavojamies izveidot savu klasi, kas definēs, kas notiks uz audekla. Tas ļaus mums pievērsties ekrānam, nevis tikai parādīt gatavus skatus.

Tāpēc ar peles labo pogu noklikšķiniet uz paketes nosaukuma savā hierarhijā kreisajā pusē un izvēlieties Jauna> klase. Tagad jums tiks parādīts logs, lai izveidotu savu klasi, un jūs to sauksit GameView. Zem SuperClass rakstiet: android.view.SurfaceView kas nozīmē, ka klase manto metodes - savas iespējas - no SurfaceView.

Lodziņā Interface (s) jūs rakstīsit android.view.SurfaceHolder.Callback. Kā jebkurai klasei, tagad mums ir jāizveido savs konstruktors. Izmantojiet šo kodu:

privāts MainThread pavediens; publiskais GameView (konteksta konteksts) {super (konteksts); getHolder (). addCallback (this); }

Katru reizi, kad mūsu klase tiek aicināta izgatavot jaunu objektu (šajā gadījumā mūsu virsmu), tā vadīs konstruktoru un radīs jaunu virsmu. Līnija “super” izsauc superklases, un mūsu gadījumā tas ir SurfaceView.

Pievienojot atzvanīšanu, mēs varam pārtvert notikumus.

Tagad ignorējiet dažas metodes:

@Pārvarēt publisko tukšo virsmuMainīts (SurfaceHolder turētājs, int formāts, int platums, int augstums) {} @Pārsniegt publisko tukšo virsmuCreated (SurfaceHolder turētājs) {} @Pārsniegt publisko tukšo virsmuDestroyed (SurfaceHolder turētājs) {}

Šie principā ļauj mums ignorēt (līdz ar to arī nosaukuma) metodes superklasē (SurfaceView). Tagad kodā nedrīkst būt vairāk sarkanu pasvītrojumu. Jauki.

Jūs tikko izveidojāt jaunu klasi, un katru reizi, kad atsauksimies uz to, tā tiks veidota audekls jūsu spēlei, lai tā tiktu uzkrāsota. Klases izveidot objektus, un mums ir vajadzīgs vēl viens.

Vītņu izveidošana

Tiks saukta mūsu jaunā klase MainThread. Un tā uzdevums būs izveidot pavedienu. Vītne būtībā ir tāda pati kā koda paralēlā dakša, kas vienlaikus var darboties blakus galvenais daļa no jūsu koda. Jums var būt daudz pavedienu, kas darbojas uzreiz, tādējādi ļaujot lietām notikt vienlaicīgi, nevis stingri ievērojot. Tas ir svarīgi spēlei, jo mums jāpārliecinās, ka tā darbojas vienmērīgi, pat ja notiek daudz.

Izveidojiet savu jauno klasi tāpat kā iepriekš, un šoreiz tā turpināsies Vītne. Būvētājā mēs vienkārši zvanīsim super (). Atcerieties, ka tā ir superklases klase, kas ir Thread un kas mūsu labā var darīt visu smago. Tas ir tāpat kā programmas izveidošana trauku mazgāšanai, kas vienkārši zvana veļas mašīna().

Kad šī klase tiek saukta, tā izveidos atsevišķu pavedienu, kas darbojas kā galvenās lietas atzars. Un tas ir no plkst šeit ka mēs vēlamies izveidot savu GameView. Tas nozīmē, ka mums jāatsaucas arī uz GameView klasi, un mēs izmantojam arī SurfaceHolder, kurā ir audekls. Tātad, ja audekls ir virsma, SurfaceHolder ir molberts. Un GameView ir tas, kas to visu apvieno.

Pilnai lietai vajadzētu izskatīties šādi:

sabiedriskās klases MainThread paplašina pavedienu {private SurfaceHolder surfaceHolder; privāts GameView gameView; publisks MainThread (SurfaceHolder surfaceHolder, GameView gameView) {super (); this.surfaceHolder = surfaceHolder; this.gameView = gameView; }}

Šveice. Mums tagad ir GameView un pavediens!

Spēles cilpas izveidošana

Mums tagad ir izejmateriāli, kas nepieciešami mūsu spēles veidošanai, bet nekas nenotiek. Šeit nonāk spēles cilpa. Būtībā šī ir koda cilpa, kas iet pa apli un pārbauda ievadi un mainīgos pirms ekrāna uzzīmēšanas. Mūsu mērķis ir padarīt to pēc iespējas konsekventāku, lai kadrētavā nebūtu nekādu stostīšanās vai žagas, ko es izpētīšu nedaudz vēlāk.

Pagaidām mēs joprojām atrodamies MainThread klasei, un mēs ignorēsim metodi no superklases. Šis ir skriet.

Un tas notiek mazliet šādi:

@Override public void run () {while (running) {canvas = null; izmēģiniet {canvas = this.surfaceHolder.lockCanvas (); sinhronizēts (surfaceHolder) {this.gameView.update (); this.gameView.draw (audekls); }} noķert (izņēmums e) {} beidzot {ja (audekls! = null) {izmēģināt {surfaceHolder.unlockCanvasAndPost (audekls); } nozveja (izņēmums e) {e.printStackTrace (); }}}}}

Jūs redzēsit daudz pasvītrojumu, tāpēc mums jāpievieno vēl daži mainīgie un atsauces. Dodieties atpakaļ uz augšu un pievienojiet:

privāts SurfaceHolder virsmas īpašnieks; privāts GameView gameView; privāta Būla skriešana; publiski statisks audekla audekls;

Atcerieties importēt kanvu. Audekls ir lieta, uz kuru mēs patiesībā balstīsimies. Kas attiecas uz “lockCanvas”, tas ir svarīgi, jo tas ir tas, kas būtībā sasaldē audekls, lai mēs varētu to uzzīmēt. Tas ir svarīgi, jo pretējā gadījumā jums varētu būt vairāki pavedieni, ar kuriem mēģināt uzzīmēt uzreiz. Vienkārši zināt, ka, lai rediģētu audekls, vispirms tas ir jādara atslēga audekls.

Atjaunināšana ir metode, kuru mēs izveidosim, un šeit vēlāk notiks jautras lietas.

mēģiniet un noķert tikmēr ir tikai Java prasības, kas parāda, ka mēs esam gatavi mēģināt rīkoties ar izņēmumiem (kļūdām), kas varētu rasties, ja audekls vēl nav gatavs utt.

Visbeidzot, mēs vēlamies, lai mēs varētu sākt savu pavedienu, kad tas mums vajadzīgs. Lai to izdarītu, šeit mums būs nepieciešama cita metode, kas ļauj mums sākt lietas kustībā. Tas ir tas, kas skriešana mainīgais ir paredzēts (ņemiet vērā, ka Būla ir mainīgo veids, kas vienmēr ir patiess vai nepatiess). Pievienojiet šo metodi MainThread klase:

public void setRunning (Būla isRunning) {darbojas = isRunning; }

Bet šobrīd vēl vajadzētu izcelt vienu lietu, un tas ir Atjaunināt. Tas ir tāpēc, ka mēs vēl neesam izveidojuši atjaunināšanas metodi. Tātad pop atpakaļ GameView un tagad pievienojiet metodi.

publisks nederīgs atjauninājums () {}

Mums arī tas jādara sākt pavediens! Mēs to darīsim savā virsmaizveidota metode:

@Override public void surfaceCreated (SurfaceHolder turētājs) {thread.setRunning (true); pavediens.starts (); }

Mums arī jāpārtrauc pavediens, kad virsma tiek iznīcināta. Kā jūs jau varējāt uzminēt, mēs to apstrādājam virsmaDieviesēts metode. Bet, tā kā patiesībā var būt nepieciešami vairāki mēģinājumi apturēt pavedienu, mēs to ievietosim cilpā un izmantosim mēģiniet un noķert atkal. Patīk:

@ Pārsniegt publisku tukšo virsmuDestroyed (SurfaceHolder turētājs) {Būla retry = true; while (atkārtot) {mēģiniet {thread.setRunning (false); pavediens.pievienoties (); } noķert (InterruptedException e) {e.printStackTrace (); } atkārtot = nepatiess; }}

Un, visbeidzot, dodieties pie konstruktora un pārliecinieties, ka esat izveidojis jaunu pavediena instanci, pretējā gadījumā jūs saņemsit nobijušo nulles rādītāja izņēmumu! Un tad mēs padarīsim GameView fokusējamu, tas nozīmē, ka tas var rīkoties ar notikumiem.

pavediens = jauns MainThread (getHolder (), šis); setFocusable (true);

Tagad Tu vari beidzot patiesībā pārbaudi šo lietu! Tas ir pareizi, noklikšķiniet uz palaist un tas vajadzētu faktiski darbojas bez kļūdām. Sagatavojieties, lai jūs varētu izpūst!

Tas ir… tas ir… tukšs ekrāns! Viss tas kods. Par tukšu ekrānu. Bet tas ir tukšs ekrāns iespēju. Lai apstrādātu notikumus, jūsu virsma ir izveidota un darbojas ar spēles cilpu. Tagad atliek tikai likt lietām notikt. Nav pat svarīgi, vai līdz šim jūs neizpildījāt visu mācību rokasgrāmatā. Lieta ir tāda, ka jūs varat vienkārši pārstrādāt šo kodu, lai sāktu veidot krāšņās spēles!

Daru grafiku

Pareizi, tagad mums ir tukšs ekrāns, uz kura zīmēt, viss, kas mums jādara, ir zīmēt uz tā. Par laimi, tā ir vienkāršā daļa. Viss, kas jums jādara, ir ignorēt izlozes metodi GameView klase un pēc tam pievienojiet dažus glītus attēlus:

@Override public void draw (Audekla audekls) {super.draw (audekls); if (audekls! = nulle) {canvas.drawColor (Color.WHITE); Paint paint = new Paint (); paint.setColor (Color.rgb (250, 0, 0)); canvas.drawRect (100, 100, 200, 200, krāsa); }}

Palaidiet to, un tagad jums vajadzētu būt diezgan sarkanam kvadrātam citādi balta ekrāna augšējā kreisajā stūrī. Tas noteikti ir uzlabojums.

Teorētiski jūs varētu izveidot diezgan daudz visu savu spēli, iestiprinot to šīs metodes iekšpusē (un pārspējot onTouchEvent rīkoties ar ievadi), taču tas nebūtu šausmīgi labs veids, kā rīkoties. Jaunas krāsas ievietošana mūsu cilpā ievērojami palēninās situāciju un pat ja mēs to ievietosim citur, pievienojot pārāk daudz koda zīmēt metode kļūtu neglīta un grūti izpildāma.

Tā vietā ir daudz jēga rīkoties ar spēļu objektiem ar savām klasēm. Mēs sāksim ar vienu, kas parāda rakstzīmi, un šī klase tiks saukta CharacterSprite. Iet uz priekšu un izdari to.

Šī klase uz audekla zīmēs sprite un izskatīsies šādi

publiskās klases CharacterSprite {privāts bitkartes attēls; publisks CharacterSprite (bitu karte bmp) {image = bmp; } public void draw (audekla audekls) {canvas.drawBitmap (attēls, 100, 100, null); }}

Tagad, lai to izmantotu, vispirms būs jāielādē bitkarte un pēc tam jāizsauc klase GameView. Pievienojiet atsauci uz privāts CharacterSprite characterSprite un pēc tam virsmaizveidota metodi, pievienojiet rindu:

characterSprite = jauns CharacterSprite (BitmapFactory.decodeResource (getResources (), R.dravable.avdgreen));

Kā redzat, bitkarte, kuru ielādējam, tiek saglabāta resursos un tiek saukta par avdgreen (tā bija no iepriekšējās spēles). Tagad viss, kas jums jādara, ir nodot šo bitmap jaunajai klasei zīmēt metode ar:

characterSprite.draw (audekls);

Tagad noklikšķiniet uz palaist, un ekrānā vajadzētu parādīties grafika! Tas ir BeeBoo. Es viņu savulaik zīmēju savas skolas mācību grāmatās.

Ko darīt, ja mēs gribētu, lai šis mazais puisis kustētos? Vienkārši: mēs vienkārši izveidojam x un y mainīgos lielumus viņa pozīcijām un pēc tam mainām šīs vērtības an Atjaunināt metode.

Tāpēc pievienojiet atsauces uz savu CharacterSprite un pēc tam uzzīmējiet savu bitkarti vietnē x, y. Šeit izveidojiet atjaunināšanas metodi, un tagad mēs tikai mēģināsim:

y ++;

Katru reizi, kad tiek palaista spēles cilpa, mēs pārvietojam rakstzīmi pa ekrānu. Atcerieties y koordinātas mēra no augšas tā 0 ir ekrāna augšdaļa. Protams, mums jāzvana Atjaunināt metode in CharacterSprite no Atjaunināt metode in GameView.

Nospiediet vēlreiz atskaņošanas taustiņu, un tagad jūs redzēsit, ka jūsu attēls lēnām izseko ekrānā. Pagaidām mēs neuzvarējam nevienu spēles balvu, bet tas ir sākums!

Labi, lai sakārto lietas nedaudz vēl interesantāk, es šeit vienkārši nometīšu kādu “bouncy ball” kodu. Tas padarīs mūsu grafisko atlēcienu ap ekrānu malās, tāpat kā vecos Windows ekrānsaudzētājus. Jūs zināt, savādi hipnotiski.

public void update () {x + = xVelocity; y + = yVelocity; if ((x> ekrāna platums - image.getWidth ()) || (x & lt; 0)) {xVelocity = xVelocity * -1; } ja ((y> screenHeight - image.getHeight ()) || (y & lt; 0)) {yVelocity = yVelocity * -1; }}

Jums būs jādefinē arī šie mainīgie:

privāts int xVelocity = 10; privātā int yelocity = 5; privāts int ekrāns platums = Resources.getSystem (). getDisplayMetrics (). privāts int screenHeight = Resursi.getSystem (). getDisplayMetrics (). augstumsPixels;

Optimizācija

Tur ir daudz vairāk šeit ienirt, sākot no atskaņotāja ievadīšanas un beidzot ar attēlu mērogošanu, līdz pārvaldībai, kurā daudz rakstzīmju vienlaikus pārvietojas pa visu ekrānu. Pašlaik varonis ir veselīgs, bet, ja paskatāsit ļoti cieši, ir neliela stostīšanās. Tas nav nekas briesmīgs, bet tas, ka varat to redzēt ar neapbruņotu aci, ir kaut kas brīdinošs. Ātrums arī emulatorā ļoti atšķiras, salīdzinot ar fizisku ierīci. Tagad iedomājieties, kas notiek, kad jums ir tonnas notiek uzreiz uz ekrāna!

Šai problēmai ir daži risinājumi. Sākumā es gribu izveidot privātu veselu skaitli MainThread un piezvani tam targetFPS. Tā vērtība būs 60.Es mēģināšu panākt, lai mana spēle ritētu šādā ātrumā, un tikmēr pārbaudīšu, vai tā ir. Tāpēc es gribu arī privātu dubultā izsaukumu vidējaisFPS.

Es arī atjaunināšu skriet metodi, lai izmērītu, cik ilgs laiks ir katrai spēles cilpai un pēc tam pauze šo spēles cilpu uz laiku, ja tā ir priekšā mērķa FPS. Pēc tam mēs aprēķināsim, cik ilgs tas būs tagad paņēma un pēc tam to izdrukāja, lai mēs to varētu redzēt žurnālā.

@Override public void run () {long startTime; ilgs laiksMillis; ilgs gaidīšanas laiks; garš kopējais laiks = 0; int frameCount = 0; garš targetTime = 1000 / targetFPS; kamēr (darbojas) {startTime = System.nanoTime (); audekls = nulle; izmēģiniet {canvas = this.surfaceHolder.lockCanvas (); sinhronizēts (surfaceHolder) {this.gameView.update (); this.gameView.draw (audekls); }} noķert (izņēmums e) {} beidzot {ja (audekls! = null) {izmēģināt {surfaceHolder.unlockCanvasAndPost (audekls); } nozveja (izņēmums e) {e.printStackTrace (); }}} timeMillis = (System.nanoTime () - startTime) / 1000000; waitTime = targetTime - timeMillis; mēģiniet {this.sleep (waitTime); } catch (izņēmums e) {} totalTime + = System.nanoTime () - startTime; frameCount ++; if (frameCount == targetFPS) {averageFPS = 1000 / ((totalTime / frameCount) / 1000000); frameCount = 0; totalTime = 0; System.out.println (vidējaisFPS); }}}

Tagad mūsu spēle mēģina bloķēt tās FPS līdz 60, un jums vajadzētu secināt, ka tā parasti mēra diezgan stabilu 58-62 FPS modernā ierīcē. Emulatorā jūs varētu iegūt atšķirīgu rezultātu.

Mēģiniet mainīt šo vērtību no 60 uz 30 un redzēt, kas notiek. Spēle palēninās, un tā vajadzētu tagad savā logcat izlasiet 30.

Domu noslēgšana

Ir arī dažas citas lietas, ko mēs varam darīt, lai optimizētu arī veiktspēju. Šeit ir lieliska emuāra ziņa par šo tēmu. Centieties atturēties no jaunu krāsas Paint vai bitkartes izveides cilpas iekšpusē un veiciet visu inicializēšanu ārpusē pirms spēles sākuma.

Ja plānojat izveidot nākamo populāro Android spēli, tad ir protams mūsdienās vieglākus un efektīvākus veidus. Bet noteikti joprojām pastāv scenāriji, kuros izmanto zīmējumu uz audekla, un tā ir ļoti noderīga prasme papildināt savu repertuāru. Es ceru, ka šī rokasgrāmata ir nedaudz palīdzējusi, un es vēlu veiksmi gaidāmajos kodēšanas pasākumos!

NākamaisIesācēja ceļvedis Java

Iepējam, ka tā nebū Zvaigžņu karu diena, taču mē nevarējām gaidīt līdz 4. maijam, lai parādītu jum ziņa par mūu jaunākai nerd atradum. Šonedēļ fanu zēni avu darbu var paveikt vienkāršāk nekā jebkad ag...

Šeit mum ir daudzveidīg peronāl. Mē eam no via paaule un mē izmantojam viu veidu tehnoloģija. Šī peronāla izvēle ērija parāda, kāda tehnoloģija mē izmantojam darbam, pēlei un veelībai....

Interesantas Publikācijas