Hogyan írhatom le az első Android játékod Java-ban

Szerző: John Stephens
A Teremtés Dátuma: 1 Január 2021
Frissítés Dátuma: 19 Lehet 2024
Anonim
Hogyan írhatom le az első Android játékod Java-ban - Alkalmazások
Hogyan írhatom le az első Android játékod Java-ban - Alkalmazások

Tartalom


Számosféle módon hozhat létre játékot az Android számára, és egyik fontos módja az, hogy a semmiből kell megtenni az Android Stúdióban, a Java segítségével. Ez maximális irányítást biztosít a játék kinézetének és viselkedésének felett, és a folyamat megtanítja képességeit, amelyeket számos más forgatókönyvben is használhat - akár splash képernyőt hoz létre egy alkalmazás számára, akár csak adj hozzá néhány animációt. Ezt szem előtt tartva, ez az oktatóprogram bemutatja, hogyan lehet egyszerű 2D játékot létrehozni az Android Studio és a Java segítségével. Az összes kódot és forrást megtalálhatja a Githubon, ha követni szeretné.

Felállítása

A játék létrehozásához néhány konkrét koncepcióval kell foglalkoznunk: játék hurkokkal, szálakkal és vászonokkal. Először indítsa el az Android Studio alkalmazást. Ha még nincs telepítve, akkor nézd meg az Android Studio teljes bevezetőjét, amely a telepítési folyamaton megy keresztül. Most indítson el egy új projektet, és feltétlenül válassza ki az 'Üres tevékenység' sablont. Ez egy játék, így természetesen nincs szüksége olyan elemekre, mint a FAB gomb, ami bonyolítja az ügyeket.


Az első dolog, amit meg akarsz csinálni, az változtatni AppCompatActivity nak nek Tevékenység. Ez azt jelenti, hogy nem használjuk a cselekvési sáv funkcióit.

Hasonlóképpen, azt is szeretnénk, hogy a játék teljes képernyős. Adja hozzá a következő kódot az onCreate () -hez a setContentView () hívás előtt:

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

Vegye figyelembe, hogy ha kiír valamilyen kódot, amely piros színű aláhúzással szerepel, akkor ez valószínűleg azt jelenti, hogy be kell importálnia egy osztályt. Más szavakkal, el kell mondania az Android Studio-nak, hogy bizonyos utasításokat szeretne használni, és elérhetővé tenni. Ha rákattint valamelyik pontra az aláhúzott szóval, majd nyomja meg az Alt + Enter billentyűket, akkor ez automatikusan megtörténik!


A játék nézetének létrehozása

Lehet, hogy hozzászokik az alkalmazásokhoz, amelyek XML-parancsfájlt használnak a nézetek, például gombok, képek és címkék elrendezésének meghatározására. Ez a vonal setContentView értünk tesz.

De ismét, ez egy játék, azaz nincs szüksége böngészőablakokra vagy gördülő újrahasznosító nézetekre. Ehelyett a vászon megjelenítését akarjuk. Az Android Stúdióban a vászon pontosan ugyanaz, mint a művészetben: ez egy közeg, amelyre tudunk támaszkodni.

Tehát változtassa meg ezt a sort úgy, hogy így legyen:

setContentView (új GameView (ez))

Megállapíthatja, hogy ez ismét piros aláhúzású. De Most ha megnyomja az Alt + Enter billentyűket, akkor nincs lehetősége az osztály importálására. Ehelyett lehetősége van teremt osztály. Más szavakkal, elkészítjük a saját osztályunkat, amely meghatározza, hogy mi megy a vászonra. Ez lehetővé teszi számunkra, hogy felhívjunk a képernyőre, ahelyett, hogy csak a kész nézeteket mutatnánk.

Tehát jobb egérgombbal kattintson a csomag nevére a bal oldali hierarchiában, és válassza a lehetőséget Új> Osztály. Most egy ablakot fognak kapni az osztály létrehozásához, és meg fogja hívni GameView. A SuperClass alatt írja: android.view.SurfaceView ami azt jelenti, hogy az osztály a módszereket - képességeit - örököli a SurfaceView-tól.

Az Interfész (ek) mezőbe írni fogod android.view.SurfaceHolder.Callback. Mint minden osztályban, most létre kell hoznunk kivitelezőnket. Használja ezt a kódot:

privát MainThread szál; nyilvános GameView (kontextus-kontextus) {szuper (kontextus); getHolder (). addCallback (e); }

Minden alkalommal, amikor osztályunkat új objektum (ebben az esetben a felületünk) elkészítésére hívják fel, az kivitelezi a konstruktort, és új felületet fog létrehozni. A „szuper” sor a szuperosztályt hívja, esetünkben a SurfaceView.

A visszahívás hozzáadásával képeket tudunk tartani az eseményekről.

Most felülírja néhány módszert:

@A nyilvános érvénytelen felület megváltoztatása (SurfaceHolder tartó, int formátum, int szélesség, int magasság) {} @A nyilvános érvénytelen felület felülírásaCreatated (SurfaceHolder tartó) {} @Orderálása nyilvános érvénytelen felületDestroyed (SurfaceHolder tartó) {}

Ezek alapvetően lehetővé teszik számunkra, hogy felülírjuk a (tehát a név) módszereket a szuperosztályban (SurfaceView). Most már nem szabad több piros aláhúzás a kódban. Szép.

Éppen most hozott létre egy új osztályt, és minden alkalommal, amikor erre utalunk, megépíti a játék vászonját, amelyre festeni lehet. osztályok teremt tárgyak, és szükségünk van még egyre.

Szálak létrehozása

Új osztályunkat felhívjuk MainThread. És a feladata egy szál létrehozása. A szál lényegében olyan, mint egy párhuzamos kódvilla, amely egyidejűleg futhat a fő- a kód része. Sok szála futhat egyszerre, ezáltal lehetővé válik, hogy a dolgok egyszerre történjenek, ahelyett, hogy szigorú sorrendet követnének. Ez egy játék szempontjából fontos, mert meg kell győződnünk arról, hogy az továbbra is zavartalanul működik, még akkor is, ha sok történik.

Hozza létre az új osztályt, ahogy korábban is tette, és ezúttal meghosszabbodik cérna. A kivitelezőben csak hívni fogunk szuper(). Ne feledje, hogy ez a szuper osztály, amely a Thread, és amely mindent megtehet nekünk. Ez olyan, mint egy program létrehozása az ételek mosására, amely csak hív mosógép().

Amikor ezt az osztályt meghívják, külön szálat fog létrehozni, amely a legfontosabb rész kivezetéseként fut. És innen származik itt hogy létre akarjuk hozni a GameView-t. Ez azt jelenti, hogy hivatkoznunk kell a GameView osztályra, és a SurfaceHolder-et is használjuk, amely a vászonot tartalmazza. Tehát ha a vászon a felület, a SurfaceHolder a festőállvány. És ezt a GameView teszi össze.

A teljes dolognak így kell kinéznie:

a nyilvános osztályú MainThread kiterjeszti a szálat {private SurfaceHolder surfaceHolder; privát GameView gameView; nyilvános MainThread (SurfaceHolder surfaceHolder, GameView gameView) {super (); this.surfaceHolder = surfaceHolder; this.gameView = gameView; }}

Schweet. Most van egy GameView és egy szál!

A játék hurok létrehozása

Megvan a nyersanyag, amire szükségünk van a játékunkhoz, de semmi sem történik. Itt jön be a játék hurok. Alapvetően ez egy olyan kód hurok, amely körbe-körbe megy, és a képernyő rajzolása előtt ellenőrzi a bemeneteket és a változókat. Célunk, hogy ezt a lehető legkövetkezetesebbé tegyük, hogy ne legyen dadogás vagy csuklás a képkocka sebességében, amit kicsit később meg fogok vizsgálni.

Jelenleg még mindig a MainThread osztály, és felülbírálunk egy módszert a szuperosztályból. Ez az fuss.

És egy kicsit így megy:

@A nyilvános érvénytelen futtatás felülírása () {míg (futás) {vászon = null; próbáld ki a {canvas = this.surfaceHolder.lockCanvas () elemet; szinkronizált (surfaceHolder) {this.gameView.update (); this.gameView.draw (vászon); }} fogás (e kivétel) {} végül {if (vászon! = null) {próbáld meg {surfaceHolder.unlockCanvasAndPost (vászon); } fogás (e kivétel) {e.printStackTrace (); }}}}}

Sok aláhúzást fog látni, ezért még néhány változót és hivatkozást hozzá kell adnunk. Menj vissza a tetejére, és add hozzá:

privát SurfaceHolder felülettartó; privát GameView gameView; privát logikai futás; statikus vászon;

Ne felejtsd el importálni a vászonot. A vászon az a dolog, amellyel valójában rajzolni fogunk. Ami a „lockCanvas” -t illeti, ez azért fontos, mert alapvetően lefagyasztja a vászonot, hogy rajzolhassuk. Ez azért fontos, mert egyébként több szál is megkísérelheti rajzolni egyszerre. Csak tudd, hogy a vászon szerkesztéséhez először meg kell tennie zár a vászon.

A frissítést olyan módszerrel fogjuk létrehozni, amelyre később kerül sor.

A próbálja meg és fogás közben a Java követelményei csak azt mutatják, hogy hajlandóak vagyunk megkísérelni kezelni azokat a kivételeket (hibákat), amelyek akkor fordulhatnak elő, ha a vászon még nem áll készen stb.

Végül azt akarjuk, hogy elindíthassuk a szálat, amikor erre szükségünk van. Ehhez szükségünk lesz egy másik módszerre, amely lehetővé teszi számunkra, hogy a dolgokat mozgásba hozzuk. Erről van szó futó a változó for (vegye figyelembe, hogy a logikai érték olyan változó, amely mindig is igaz vagy hamis). Adja hozzá ezt a módszert a MainThread osztály:

public void setRunning (logikai isRunning) {fut = isRunning; }

De ezen a ponton még egy dolgot ki kell emelni, és az frissítés. Ennek oka az, hogy még nem hoztuk létre a frissítési módszert. Tehát pop vissza GameView és most adjunk hozzá egy módszert.

nyilvános érvénytelen frissítés () {}

Szükségünk van rá Rajt a szál! Ezt megtesszük a sajátunkban surfaceCreated eljárás:

@A nyilvános void felülbírálása felületre létrehozva (SurfaceHolder tartó) {thread.setRunning (true); thread.start (); }

A menetet le kell állítanunk, amikor a felület megsemmisül. Mint talán kitaláltad, ezt a surfaceDestroyed eljárás. De látva, mivel valójában többszörös kísérlet is igénybe vehet egy szál leállítását, ezt egy hurokba tesszük és felhasználjuk próbálja meg és fogás újra. Tetszik:

@A nyilvános érvénytelen felület felülírása (SurfaceHolder tartó) {logikai újrapróbálkozás = igaz; while (újrapróbálkozás) {try {thread.setRunning (false); thread.join (); } fogás (InterruptedException e) {e.printStackTrace (); } újra = hamis; }}

És végül, menjen fel a kivitelezőhöz, és győződjön meg arról, hogy elkészíti a szál új példányát, különben a rettegett null-mutató kivétel lesz! És akkor a GameView fókuszálhatóvá válik, azaz képes kezelni az eseményeket.

szál = új MainThread (getHolder (), ez); setFocusable (true);

Most már tudod végül valójában tesztelje ezt a dolgot! Így van, kattintson a Futtatás gombra, kellene valójában hiba nélkül fut. Készülj fel arra, hogy elfújják!

Ez ... ez egy üres képernyő! Az egész kód. Üres képernyőhöz. De ez egy üres képernyő a lehetőség. Fel van állítva a felülettel, és egy játékhurokkal fut az események kezelésére. Most már csak az marad, hogy a dolgok megtörténjenek. Nem is számít, ha eddig nem követte-e el az oktatóanyag mindent. A lényeg az, hogy egyszerűen újrahasznosíthatja ezt a kódot, hogy dicsőséges játékokat készítsen!

Grafika készítése

Rendben, most van egy üres képernyő, amellyel rajzolhatunk, csak annyit kell tennünk, hogy rajzolunk rajta. Szerencsére ez az egyszerű rész. Csak annyit kell tennie, hogy felülírja a sorsolás módszerét GameView osztályba, majd adj hozzá néhány csinos képet:

@A nyilvános érvénytelen rajzolás felülírása (vászon vászon) {szuper rajz (vászon); if (vászon! = null) {canvas.drawColor (Color.WHITE); Festékfesték = új Festék (); paint.setColor (Color.rgb (250, 0, 0)); canvas.drawRect (100, 100, 200, 200, festék); }}

Futtassa ezt, és most egy szép piros négyzettel kell rendelkeznie az egyébként fehér képernyő bal felső sarkában. Ez minden bizonnyal javulás.

Elméletileg az egész játékot elkészítheted, ha ebbe a módszerbe ragadsz (és felülbírálsz) onTouchEvent az input kezelésére), de ez nem lenne rettenetes mód a dolgok megválaszolására. Az új festék behelyezése a hurokba jelentősen lelassítja a dolgokat, és még ha máshol is tegyük, akkor túl sok kódot adunk a húz A módszer csúnyavá válna és nehéz követni.

Ehelyett sokkal értelmesebb a játékobjektumok kezelése a saját osztályukkal. Azzal kezdjük, amely egy karaktert mutat, és ezt az osztályt hívják CharacterSprite. Menj, és csináld ezt.

Ez az osztály fog rajzot készíteni a vászonra, és így néz ki

nyilvános osztályú CharacterSprite {privát Bitmap kép; public CharacterSprite (bitmap bmp) {image = bmp; } nyilvános void rajzolás (vászon vászon) {canvas.drawBitmap (kép, 100, 100, null); }}

Most ennek használatához először be kell töltenie a bitképet, majd fel kell hívnia az osztályt GameView. Adjon hozzá egy hivatkozást private CharacterSprite karakterSprite majd a surfaceCreated módszer, adja hozzá a sort:

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

Mint láthatja, a betöltött bitképet erőforrásokban tárolják, és avdgreennek hívják (ez egy korábbi játékból származott). Most csak annyit kell tennie, hogy átadja ezt a bitképet az új osztálynak a húz módszer:

characterSprite.draw (vászon);

Most kattintson a Futtatás gombra, és látnia kell a grafikát a képernyőn! Ez a BeeBoo. Rajzoltam őt az iskolai tankönyvekbe.

Mi lenne, ha meg akarnánk mozgatni ezt a kis fickót? Egyszerű: csak x és y változókat hozunk létre a pozícióihoz, majd ezeket az értékeket an-ban megváltoztatjuk frissítés eljárás.

Tehát adja hozzá a hivatkozásokat a CharacterSprite majd rajzolja meg a bitképet a x, y. Hozzon létre itt egy frissítési módszert, és most csak megpróbáljuk:

y ++;

Minden alkalommal, amikor a játék hurok fut, áthelyezzük a karaktert a képernyőn lefelé. Emlékezik, y a koordinátákat felülről mérik, tehát 0 a képernyő teteje. Természetesen fel kell hívnunk a frissítés módszer in CharacterSprite tól frissítés módszer in GameView.

Nyomja meg ismét a lejátszás gombot, és most látni fogja, hogy a képe lassan nyomon követi a képernyőt. Még nem nyerünk játékdíjakat, de ez a kezdete!

Oké, dolgozni némileg még érdekesebb, hogy csak itt dobok el egy „pattogó labda” kódot. Ez megkönnyíti a grafikánknak a képernyő körül a szélektől való visszapattanását, mint például a régi Windows képernyővédőket. Tudod, a furcsa hipnotikusok.

public void update () {x + = xVelocity; y + = yVelocity; if ((x> képernyőszélesség - image.getWidth ()) || (x <0)) {xVelocity = xVelocity * -1; } if ((y> screenHeight - image.getHeight ()) || (y <0)) {yVelocity = yVelocity * -1; }}

Meg kell határoznia ezeket a változókat:

magán int xVelocity = 10; magán int yelocity = 5; privát int képernyőszélesség = Resources.getSystem (). getDisplayMetrics (). widthPixels; private int screenHeight = Resources.getSystem (). getDisplayMetrics (). heightPixels;

Optimalizálás

Van bőven többet itt belemerülni, a lejátszó bevitelétől kezdve a képek méretezéséig, a képernyőn lévő karakterek kezelésének kezeléséig. Jelenleg a karakter pattogó, de ha nagyon alaposan megnézed, akkor enyhén dadog. Nem szörnyű, de az a tény, hogy szabad szemmel láthatja, figyelmeztető jel. A sebesség az emulátoron is nagyon változik, összehasonlítva a fizikai eszközzel. Képzelje el, mi történik, ha van tonna azonnal a képernyőn!

Van néhány megoldás erre a problémára. Amit kezdeni szeretnék, egy magán egész szám létrehozása az MainThread és hívja fel targetFPS. Ennek értéke 60 lesz.Megpróbálom megszerezni a játékomat ezen a sebességen, és közben ellenőrizni fogom, hogy biztosan működjön-e. Ehhez szeretnék egy privát dupla hívást is averageFPS.

Én is frissíteni fogom a fuss módszer annak mérésére, hogy az egyes játékhurokok mennyi ideig tartanak, majd azt követően szünet átmenetileg ezt a játékhurkot, ha megelőzi a targetFPS-t. Ezután kiszámoljuk, mennyi ideig tart Most elvette, majd kinyomtatta, így láthatjuk a naplóban.

@A nyilvános érvénytelen futtatás felülírása () {long startTime; hosszú ideigMillis; hosszú várakozási idő; hosszú totalTime = 0; int frameCount = 0; hosszú targetTime = 1000 / targetFPS; míg (fut) {startTime = System.nanoTime (); vászon = null; próbáld ki a {canvas = this.surfaceHolder.lockCanvas () elemet; szinkronizált (surfaceHolder) {this.gameView.update (); this.gameView.draw (vászon); }} fogás (e kivétel) {} végül {if (vászon! = null) {próbáld ki {surfaceHolder.unlockCanvasAndPost (vászon); } fogás (e kivétel) {e.printStackTrace (); }}} timeMillis = (System.nanoTime () - startTime) / 1000000; waitTime = targetTime - timeMillis; próbáld meg {this.sleep (waitTime); } fogás (e kivétel) {} totalTime + = System.nanoTime () - startTime; frameCount ++; if (frameCount == targetFPS) {averageFPS = 1000 / ((totalTime / frameCount) / 1000000); frameCount = 0; totalTime = 0; System.out.println (averageFPS); }}}

Most a játékunk megpróbálja lezárni az FPS-jét 60-ra, és meg kell találnia, hogy általában egy meglehetősen állandó 58-62 FPS-t mér egy modern eszközön. Az emulátoron bár lehet, hogy más eredményt kap.

Próbáld meg változtatni ezt a 60-tól 30-ig, és nézd meg, mi történik. A játék lelassul, és ez kellene most olvassa el a 30. oldalt a logcatben.

Záró gondolatok

Van néhány más dolog is, amit a teljesítmény optimalizálása érdekében megtehetünk. Itt található egy nagyszerű blogbejegyzés a témáról. Próbáljon meg tartózkodni attól, hogy új Paint példányokat vagy bitképeket hozzon létre a hurokban, és végezzen minden inicializálást kívül a játék kezdete előtt.

Ha azt tervezi, hogy létrehozza a következő slágeres Android játékot, akkor vannak biztosan könnyebb és hatékonyabb módszerek a napjainkban. De határozottan vannak olyan esetek, amelyekben vászonra lehet rajzolni, és nagyon hasznos képesség a repertoár hozzáadása. Remélem, hogy ez az útmutató kissé segített, és sok szerencsét kívánok neked a következő kódolási vállalkozásokhoz!

KövetkezőA Java kezdő útmutatója

Négy hónappal ezelőtt a Google I / O 2019-ben tett bejelentée után a Google Net Hub Max végre eladára került. Mától elérhető a Google tore-ból &#...

A Google Net Hub Max alig egy hete történt kiadáa után nemrégiben került forgalomba a Rakuten.com oldalon. Az ezköz általában 229 dollárért vizon...

Válassza Az Adminisztráció Lehetőséget