Paano isulat ang iyong unang laro sa Android sa Java

May -Akda: John Stephens
Petsa Ng Paglikha: 1 Enero 2021
I -Update Ang Petsa: 19 Mayo 2024
Anonim
Full House Tonight: Ang mga gutom na Sang’gre
Video.: Full House Tonight: Ang mga gutom na Sang’gre

Nilalaman


Maraming mga paraan upang lumikha ng isang laro para sa Android at isang mahalagang paraan ay gawin ito mula sa simula sa Android Studio na may Java. Nagbibigay ito sa iyo ng pinakamataas na kontrol sa kung paano mo nais na tumingin at kumilos ang iyong laro at ang proseso ay magturo sa iyo ng mga kasanayan na maaari mong magamit sa isang hanay ng iba pang mga sitwasyon - kung gumagawa ka rin ng isang splash screen para sa isang app o nais mo lamang magdagdag ng ilang mga animation. Sa isip, ang tutorial na ito ay magpapakita sa iyo kung paano lumikha ng isang simpleng laro ng 2D gamit ang Android Studio at ang Java. Maaari mong mahanap ang lahat ng mga code at mga mapagkukunan sa Github kung nais mong sundin.

Inaayos

Upang lumikha ng aming laro, kakailanganin nating harapin ang ilang mga tiyak na konsepto: mga loop ng laro, mga thread at canvases. Upang magsimula sa, simulan ang Android Studio. Kung hindi mo ito mai-install pagkatapos suriin ang aming buong pagpapakilala sa Android Studio, na napupunta sa proseso ng pag-install. Magsimula ka ngayon ng isang bagong proyekto at tiyaking pinili mo ang template na 'Walang laman ang Aktibidad'. Ito ay isang laro, kaya syempre hindi mo na kailangan ang mga elemento tulad ng pindutan ng FAB na nakakatulong sa mga bagay.


Ang unang bagay na nais mong gawin ay ang magbago AppCompatActivity sa Aktibidad. Nangangahulugan ito na hindi namin ginagamit ang mga tampok ng aksyon sa bar.

Katulad nito, nais din naming gawing buong screen ang aming laro. Idagdag ang sumusunod na code sa onCreate () bago ang tawag upang i-setContentView ():

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

Tandaan na kung sumulat ka ng ilang code at ito ay nagiging may salungguhit, marahil nangangahulugang kailangan mong mag-import ng isang klase. Sa madaling salita, kailangan mong sabihin sa Android Studio na nais mong gumamit ng ilang mga pahayag at gawing magagamit ang mga ito. Kung mag-click ka kahit saan sa salitang may salungguhit at pagkatapos ay pindutin ang Alt + Enter, pagkatapos iyon ay gagawin para sa iyo awtomatiko!


Lumilikha ng iyong view ng laro

Maaaring magamit ka sa mga app na gumagamit ng isang XML script upang tukuyin ang layout ng mga view tulad ng mga pindutan, larawan at label. Ito ang linya setContentView ay ginagawa para sa amin.

Ngunit muli, ito ay isang laro na nangangahulugang hindi nito kailangang magkaroon ng mga window ng browser o pag-scroll ng mga view ng recycler. Sa halip na iyon, nais naming magpakita ng isang canvas sa halip. Sa Android Studio ang isang canvas ay pareho lamang sa sining: ito ay isang daluyan na maaari nating iguhit.

Kaya baguhin ang linya na iyon upang mabasa nang gayon:

setContentView (bagong GameView (ito))

Malalaman mo na ito ay muling naka-underline na pula. Ngunit ngayon kung pinindot mo ang Alt + Enter, wala kang pagpipilian na mag-import ng klase. Sa halip, mayroon kang pagpipilian upang lumikha Klase. Sa madaling salita, gagawa kami ng aming sariling klase na tukuyin kung ano ang pupunta sa canvas. Ito ang magbibigay-daan sa amin upang gumuhit sa screen, kaysa sa pagpapakita lamang ng mga yari na tanawin.

Kaya mag-right click sa pangalan ng package sa iyong hierarchy sa kaliwa at pumili Bago> Klase. Magpakita ka na ngayon ng isang window upang lumikha ng iyong klase at tatawagin mo ito GameView. Sa ilalim ng SuperClass, isulat: android.view.SurfaceView na nangangahulugang ang klase ay magmamana ng mga pamamaraan - ang mga kakayahan nito - mula sa SurfaceView.

Sa kahon ng Interface (mga), magsusulat ka android.view.SurfaceHolder.Callback. Tulad ng anumang klase, kailangan nating lumikha ng aming tagapagtayo. Gamitin ang code na ito:

pribadong MainThread thread; pampublikong GameView (Konteksto ng konteksto) {super (konteksto); getHolder (). addCallback (ito); }

Sa bawat oras na tinawag ang aming klase na gumawa ng isang bagong bagay (sa kasong ito ang aming ibabaw), tatakbo ito ng tagapagtayo at gagawa ito ng isang bagong ibabaw. Ang linya na 'super' ay tumatawag sa superclass at sa aming kaso, iyon ang SurfaceView.

Sa pamamagitan ng pagdaragdag ng Callback, nakakapag-agaw kami ng mga kaganapan.

Ngayon ay i-override ang ilang mga pamamaraan:

@Override public void surfaceChanged (SurfaceHolder holder, int format, int width, int height) {} @Override public void surfaceCreated (SurfaceHolder holder) {} @Override public void surfaceDestroyed (SurfaceHolder holder) {}

Ang mga ito ay nagbibigay-daan sa amin na mag-override (samakatuwid ang pangalan) na mga pamamaraan sa superclass (SurfaceView). Dapat ay wala na kang mga red underlines sa iyong code. Masarap.

Lumikha ka lamang ng isang bagong klase at sa bawat oras na tinutukoy namin iyon, bubuo ito ng canvas para sa iyong laro upang ipinta sa. Mga Klase lumikha bagay at kailangan namin ng isa pa.

Paglikha ng mga thread

Tatawagin ang aming bagong klase MainThread. At ang trabaho nito ay upang lumikha ng isang thread. Ang isang thread ay mahalagang tulad ng isang kahanay na tinidor ng code na maaaring tumakbo nang sabay-sabay sa tabi ng pangunahing bahagi ng iyong code. Maaari kang magkaroon ng maraming mga thread na tumatakbo nang sabay-sabay, sa gayon pinapayagan ang mga bagay na mangyari nang sabay-sabay kaysa sa pagsunod sa isang mahigpit na pagkakasunud-sunod. Mahalaga ito para sa isang laro, dahil kailangan nating tiyakin na patuloy itong tumatakbo nang maayos, kahit na maraming nangyayari.

Lumikha ng iyong bagong klase tulad ng ginawa mo dati at sa oras na ito ay papalawakin Thread. Sa konstruksyon kami ay tatawag lamang sobrang (). Tandaan, iyon ang sobrang klase, na Thread, at maaaring gawin ang lahat ng mabibigat na pag-aangat para sa amin. Ito ay tulad ng paglikha ng isang programa upang hugasan ang mga pinggan na tumatawag lamang washing machine().

Kapag tinawag ang klase na ito, lilikha ng isang hiwalay na thread na tumatakbo bilang isang pag-alis ng pangunahing bagay. At galing ito dito na nais naming lumikha ng aming GameView. Nangangahulugan ito na kailangan din nating i-refer ang klase ng GameView at gumagamit din kami ng SurfaceHolder na naglalaman ng canvas. Kaya kung ang canvas ay ang ibabaw, ang SurfaceHolder ay ang easel. At ang GameView ay kung ano ang magkasama.

Ang buong bagay ay dapat magmukhang ganito:

pampublikong klase MainThread ay umaabot ng Thread {pribadong SurfaceHolder ibabawHolder; pribadong larong GameView; pampublikong MainThread (SurfaceHolder surfaceHolder, GameView gameView) {super (); this.surfaceHolder = surfaceHolder; ito.gameView = laroView; }}

Schweet. Mayroon kaming isang GameView at isang thread!

Paglikha ng laro ng loop

Mayroon kaming ngayon ng mga hilaw na materyales na kailangan naming gawin ang aming laro, ngunit walang nangyayari. Ito ay kung saan ang game loop ay pumapasok. Talaga, ito ay isang loop ng code na lumibot at ikot at sinusuri ang mga input at variable bago ilabas ang screen. Ang layunin namin ay gawin itong pare-pareho hangga't maaari, upang walang mga stutter o hiccups sa framerate, na kakailanganin kong galugarin nang kaunti.

Sa ngayon, nasa loob pa rin kami MainThread klase at lalampasan namin ang isang pamamaraan mula sa superclass. Ang isang ito ay tumakbo.

At napupunta ito ng isang maliit na bagay na katulad nito:

@Override pampublikong walang bisa run () {habang (tumatakbo) {canvas = null; subukan ang {canvas = this.surfaceHolder.lockCanvas (); naka-synchronize (surfaceHolder) {this.gameView.update (); ito.gameView.draw (canvas); }} mahuli (Pagbubukod e) {} sa wakas {kung (canvas! = null) {subukan {surfaceHolder.unlockCanvasAndPost (canvas); } mahuli (Pagbubukod e) {e.printStackTrace (); }}}}}

Marami kang makikitang salungguhit, kaya kailangan nating magdagdag ng ilang mga variable at sanggunian. Tumungo pabalik sa tuktok at idagdag:

pribadong SurfaceHolder ibabawHolder; pribadong larong GameView; tumatakbo ang pribadong boolean; pampublikong static na canvas;

Tandaan na mag-import ng Canvas. Ang Canvas ay ang bagay na aktwal na gaguguhit namin. Tulad ng para sa 'lockCanvas', mahalaga ito sapagkat ito ang mahalagang pag-freeze ng canvas upang pahintulutan kaming gumuhit dito. Mahalaga iyon sapagkat kung hindi man, maaari kang magkaroon ng maraming mga thread na tinatangkang iguhit ito nang sabay-sabay. Basta alam na upang mai-edit ang canvas, dapat mo munang kandado ang canvas.

Ang pag-update ay isang pamamaraan na lilikha namin at ito ay kung saan ang masasayang bagay ay mangyayari sa susunod.

Ang subukan at mahuli Samantala, ang mga kinakailangan lamang ng Java na nagpapakita na handa kaming subukan at mahawakan ang mga eksepsiyon (error) na maaaring mangyari kung hindi handa ang canvas atbp.

Sa wakas, nais naming magawang simulan ang aming sinulid kapag kailangan namin ito. Upang gawin ito, kakailanganin namin ang isa pang pamamaraan dito na nagpapahintulot sa amin na itakda ang paggalaw. Iyon ang tumatakbo variable ay para sa (tandaan na ang isang Boolean ay isang uri ng variable na kailanman ay totoo o hindi totoo). Idagdag ang pamamaraang ito sa MainThread klase:

pampublikong walang bisa setRunning (boolean isRunning) {tumatakbo = isRunning; }

Ngunit sa puntong ito, dapat pa ring i-highlight ang isang bagay at iyon pag-update. Ito ay dahil hindi pa namin nilikha ang paraan ng pag-update. Kaya pop pabalik sa GameView at ngayon magdagdag ng paraan.

pampublikong walang bisa na pag-update () {}

Kailangan din natin magsimula ang sinulid! Gagawin namin ito sa aming ibabawCreated pamamaraan:

@Override pampublikong walang bisa na ibabawCreated (may hawak ng SurfaceHolder) {thread.setRunning (totoo); thread.start (); }

Kailangan din nating ihinto ang thread kapag nawasak ang ibabaw. Tulad ng maaari mong mahulaan, hawakan namin ito sa ibabawDestroyed pamamaraan. Ngunit ang nakikita dahil maaari itong tumagal ng maraming pagtatangka upang ihinto ang isang thread, ilalagay namin ito sa isang loop at gamitin subukan at mahuli muli. Tulad ng:

@Override pampublikong walang laman na ibabawDestroyed (SurfaceHolder holder) {boolean retry = totoo; habang (muling subukan) {subukan {thread.setRunning (maling); thread.join (); } mahuli (InterruptedException e) {e.printStackTrace (); } retry = maling; }}

At sa wakas, magtungo sa tagabuo at tiyaking lumikha ng bagong halimbawa ng iyong sinulid, kung hindi, makakakuha ka ng natatakot na null pointer na pangitain! At pagkatapos ay gagawa kami ng GameView na nakatuon, nangangahulugang maaari nitong hawakan ang mga kaganapan.

thread = bagong MainThread (getHolder (), ito); naka-setFocusable (totoo);

Ngayon ay maaari ka sa wakas talagang subukan ang bagay na ito! Tama iyon, i-click ang run at ito dapat talagang tumakbo nang walang anumang mga pagkakamali. Maghanda na iputok!

Ito ... ito ... isang blangko na screen! Lahat ng code na iyon. Para sa isang blangko na screen. Ngunit, ito ay isang blangko na screen ng pagkakataon. Nakakuha ka ng iyong ibabaw at nagpapatakbo ng isang laro loop upang mahawakan ang mga kaganapan. Ngayon lahat ng naiwan ay nagaganap ang mga bagay-bagay. Hindi man mahalaga kung hindi mo sinusunod ang lahat sa tutorial hanggang sa puntong ito. Ang punto ay, maaari mo lamang ulitin ang code na ito upang simulan ang paggawa ng maluwalhating mga laro!

Ang paggawa ng isang graphic

Sa ngayon, mayroon kaming isang blangko na screen upang iguhit, ang kailangan lamang gawin ay gumuhit dito. Sa kabutihang palad, iyon ang simpleng bahagi. Ang kailangan mo lang gawin ay mapalampas ang paraan ng pagguhit sa amin GameView klase at pagkatapos ay magdagdag ng ilang mga magagandang larawan:

@Override pampublikong walang bisa draw (Canvas canvas) {super.draw (canvas); kung (canvas! = null) {canvas.drawColor (Kulay.WHITE); Kulayan ng pintura = bagong Pagpinta (); pintura.setColor (Kulay.rgb (250, 0, 0)); canvas.drawRect (100, 100, 200, 200, pintura); }}

Patakbuhin ito at dapat mayroon ka ngayong isang medyo pulang parisukat sa tuktok na kaliwa ng isang kung hindi man-puting screen. Ito ay tiyak na isang pagpapabuti.

Maaari mong teoryang lumikha ng halos lahat ng iyong buong laro sa pamamagitan ng pagdikit nito sa loob ng pamamaraang ito (at overriding onTouchEvent upang mahawakan ang input) ngunit hindi iyon magiging isang napakagandang paraan upang magawa ang mga bagay. Ang paglalagay ng mga bagong Pintura sa loob ng aming loop ay magpapabagal sa mga bagay at kahit na ilagay namin ito sa ibang lugar, pagdaragdag ng masyadong maraming code sa gumuhit ang paraan ay makakakuha ng pangit at mahirap sundin.

Sa halip, gumagawa ng mas maraming kahulugan upang hawakan ang mga laro ng laro sa kanilang sariling mga klase. Magsisimula kami sa isa na nagpapakita ng isang character at tatawagin ang uring ito CharacterSprite. Sige at gawin mo na.

Ang klase na ito ay gumuhit ng isang sprite papunta sa canvas at magiging ganito

pampublikong klase na CharacterSprite {pribadong imahe ng Bitmap; pampublikong CharacterSprite (Bitmap bmp) {image = bmp; } pampublikong walang bisa draw (Canvas canvas) {canvas.drawBitmap (imahe, 100, 100, null); }}

Ngayon upang magamit ito, kakailanganin mong i-load muna ang bitmap at pagkatapos ay tawagan ang klase mula sa GameView. Magdagdag ng isang sanggunian sa pribadong CharacterSprite characterSprite at pagkatapos ay sa ibabawCreated paraan, idagdag ang linya:

characterSprite = bagong CharacterSprite (BitmapFactory.decodeResource (getRes Source (), R.drawable.avdgreen));

Tulad ng nakikita mo, ang bitmap na aming naglo-load ay naka-imbak sa mga mapagkukunan at tinawag na avdgreen (mula ito sa nakaraang laro). Ngayon ang kailangan mo lang gawin ay ipasa ang bitmap sa bagong klase sa gumuhit paraan na may:

characterSprite.draw (canvas);

Ngayon mag-click run at dapat mong makita ang iyong graphic na lilitaw sa iyong screen! Ito ang BeeBoo. Dati ko siyang iginuhit sa aking mga aklat-aralin sa paaralan.

Paano kung nais naming gawin ang maliit na taong ito? Simple: lumikha lamang kami ng mga variable na x at y para sa kanyang mga posisyon at pagkatapos ay baguhin ang mga halagang ito sa isang pag-update pamamaraan.

Kaya idagdag ang mga sanggunian sa iyong CharacterSprite at pagkatapos ay iguhit ang iyong bitmap sa x, y. Lumikha ng paraan ng pag-update dito at sa ngayon susubukan na lang natin:

y ++;

Sa bawat oras na tumatakbo ang laro loop, maililipat namin ang character sa screen. Tandaan, y ang mga coordinate ay sinusukat mula sa itaas kaya 0 ay ang tuktok ng screen. Siyempre kailangan nating tawagan ang pag-update pamamaraan sa CharacterSprite galing sa pag-update pamamaraan sa GameView.

Pindutin muli ang pag-play at ngayon makikita mo na ang iyong imahe ay dahan-dahang nakalusot sa screen. Hindi pa kami nanalo ng anumang mga parangal sa laro ngunit nagsisimula ito!

Okay, upang gumawa ng mga bagay bahagyang mas kawili-wili, bababa lang ako ng ilang 'bouncy ball' code dito. Gagawin nito ang aming graphic bounce sa paligid ng screen sa mga gilid, tulad ng mga lumang screensaver ng Windows. Alam mo, ang mga kakaibang hypnotic.

pampublikong walang bisa na pag-update () {x + = xVelocity; y + = yVelocity; kung ((x & gt; screenWidth - image.getWidth ()) || (x & lt; 0)) {xVelocity = xVelocity * -1; } kung ((y & gt; screenHeight - image.getHeight ()) || (y & lt; 0)) {yVelocity = yVelocity * -1; }}

Kailangan mo ring tukuyin ang mga variable na ito:

pribadong int xVelocity = 10; pribadong int yVelocity = 5; pribadong int screenWidth = Resources.getSystem (). getDisplayMetrics () lapadPixels; pribadong int screenHeight = Resources.getSystem (). getDisplayMetrics () taasPixels;

Pag-optimize

Mayroong maraming higit pa upang matuklasan dito, mula sa paghawak ng input ng player, sa mga imahe ng pag-scale, upang pamamahala ng pagkakaroon ng maraming mga character na lahat ng gumagalaw sa paligid ng screen nang sabay-sabay. Sa ngayon, ang character ay nagba-bounce ngunit kung titingnan mo nang malapit mayroong bahagyang pagkagulat. Hindi kahila-hilakbot ngunit ang katotohanan na maaari mong makita ito sa hubad na mata ay isang bagay na isang tanda ng babala. Ang bilis ay nag-iiba din sa emulator kumpara sa isang pisikal na aparato. Ngayon isipin kung ano ang mangyayari kapag mayroon ka tonelada pagpunta sa screen nang sabay-sabay!

Mayroong ilang mga solusyon sa problemang ito. Ang nais kong gawin upang magsimula sa, ay upang lumikha ng isang pribadong integer sa MainThread at tumawag na targetFPS. Magkakaroon ito ng halaga ng 60.Pupunta ako at susubukan ang aking laro na tumakbo sa bilis na ito at pansamantala, susuriin ko upang matiyak ito. Para rito, gusto ko rin ng isang pribadong dobleng tinawag averageFPS.

Pupunta din ako upang i-update ang tumakbo paraan upang masukat kung gaano katagal ang bawat laro ng loop ay tumatagal at pagkatapos ay huminto pansamantalang ang loop ng laro kung ito ay nauna sa targetFPS. Pagkatapos namin makalkula kung gaano katagal ito ngayon kinuha at pagkatapos ay i-print ito upang makita natin ito sa log.

@Override pampublikong walang bisa run () {long startTime; mahabang orasMillis; mahabang paghihintayTime; mahabang kabuuanTime = 0; int frameCount = 0; mahabang targetTime = 1000 / targetFPS; habang (tumatakbo) {startTime = System.nanoTime (); canvas = null; subukan ang {canvas = this.surfaceHolder.lockCanvas (); naka-synchronize (surfaceHolder) {this.gameView.update (); ito.gameView.draw (canvas); }} mahuli (Pagbubukod e) {} sa wakas {kung (canvas! = null) {subukan {surfaceHolder.unlockCanvasAndPost (canvas); } mahuli (Pagbubukod e) {e.printStackTrace (); }}} orasMillis = (System.nanoTime () - startTime) / 1000000; waitTime = targetTime - orasMillis; subukan {ito.sleep (waitTime); } mahuli (Pagbubukod e) {} totalTime + = System.nanoTime () - startTime; frameCount ++; kung (frameCount == targetFPS) {averageFPS = 1000 / ((totalTime / frameCount) / 1000000); frameCount = 0; totalTime = 0; System.out.println (averageFPS); }}}

Ngayon tinatangka ng aming laro na i-lock ito ng FPS sa 60 at dapat mong makita na sa pangkalahatan ay sinusukat nito ang isang medyo matatag 58-62 FPS sa isang modernong aparato. Sa emulator kahit na maaaring makakuha ka ng ibang resulta.

Subukang baguhin ang 60 hanggang 30 at tingnan kung ano ang mangyayari. Ang laro ay nagpapabagal at ito dapat basahin ngayon ang 30 sa iyong logcat.

Pagwawakas ng Kaisipan

Mayroong iba pang mga bagay na maaari nating gawin upang mai-optimize din ang pagganap. Mayroong isang mahusay na post sa blog sa paksa dito. Subukang pigilin mula sa kailanman lumikha ng mga bagong pagkakataon ng Kulayan o bitmaps sa loob ng loop at gawin ang lahat ng pag-uumpisa sa labas bago magsimula ang laro.

Kung nagpaplano ka sa paglikha ng susunod na hit sa laro ng Android pagkatapos ay mayroong tiyak mas madali at mas mahusay na mga paraan upang mapunta ito sa mga araw na ito. Ngunit tiyak na mayroon pa ring mga sitwasyon sa paggamit para sa pag-iguhit sa isang canvas at ito ay lubos na kapaki-pakinabang na kasanayan upang idagdag sa iyong repertoire. Inaasahan ko na ang gabay na ito ay nakatulong nang medyo at nais mo ang pinakamahusay na swerte sa iyong paparating na mga coding venture!

SusunodIsang gabay ng nagsisimula sa Java

Inilunad ng Android Auto limang taon na ang nakalilipa, at ito ay iang puwera a pagmamaneho a likod ng mga bagong pagbili ng kote mula pa noon. Mahalaga ang mga ytem ng infotainment a mga tao kapag pu...

Ang Android ay nagbago nang malaki a mga nakaraang taon, na nagpapakilala a mga bagong dienyo ng UI at pagkakaroon ng maraming mga natatanging tampok at pag-optimize a kahabaan. Gayunpaman, tulad ng p...

Kamangha-Manghang Mga Artikulo