Lag et puslespill for Android med Dolby Audio API

Create et puslespill for Android med Dolby Audio API
26
Del
7
Share < .no> Dette Cyber ​​mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.
Sponset Innhold

Dette sponset post har et produkt som er relevant for våre lesere mens møte våre redaksjonelle retningslinjer for å være objektiv og pedagogisk.

I denne opplæringen, vil jeg vise deg hvordan å bruke Dolby Audio API for å forbedre lyden i din Android-programmer. For å vise deg hvordan du bruker Dolby Audio API, vil vi lage en enkel, men morsomt puslespill.

Innledning

I dagens fylt mobilmarkedet, er det viktig å gjøre dine applikasjoner overbevisende som de kan muligens være. Styrking av et program audial erfaring kan være like attraktivt for brukeren som å ha et fantastisk brukergrensesnitt.

Lyden skapt av en søknad er en form for interaksjon mellom brukeren og programmet som er altfor ofte oversett. Men betyr dette at å tilby en stor audial erfaring kan hjelpe din søknad skiller seg ut fra mengden.

Dolby Digital Plus er et avansert audio codec som kan brukes i mobile applikasjoner ved hjelp av Dolby enkel å bruke Audio API . Dolby har gjort sin API tilgjengelig for flere plattformer, inkludert Android og Kindle Fire. I denne opplæringen, vil vi se på Android gjennomføringen av API.

The Dolby Audio API for Android er kompatibel med et bredt spekter av Android-enheter. Dette betyr at Android-programmer og spill kan nyte high-fidelity, oppslukende lyd med bare noen få minutters arbeid integrere Dolby Audio API. La oss utforske hva det tar å integrere API ved å lage et puslespill.

1. Oversikt

I den første delen av denne opplæringen, vil jeg vise deg hvordan du kan lage en morsom puslespill. Fordi fokus for denne opplæringen er å integrere den Dolby Audio API, vil jeg ikke gå inn i for mye detalj, og jeg forventer at du allerede er kjent med grunnleggende av Android utvikling. I den andre delen av denne artikkelen, vil vi zoome inn på integreringen av Dolby Audio API i en Android-applikasjon.

Vi kommer til å lage en tradisjonell oppgave lek for Android. Målet med spillet er å skyve et puslespill stykke inn i det tomme sporet i puslespillet styret å flytte brikkene rundt. Spilleren må gjenta denne prosessen til hver brikke i puslespillet er i riktig rekkefølge. Som du ser i skjermbildet nedenfor, har jeg lagt et nummer til hver puslespill brikke. Dette vil gjøre det lettere å holde styr på de bitene i puslespillet, og den rekkefølgen de er i.

For å gjøre spillet mer attraktivt, skal jeg vise deg hvordan du bruker egendefinerte bilder samt hvordan ta et bilde for å lage dine egne unike oppgaver. Vi vil også legge til en shuffle-knappen for å omorganisere bitene i puslespillet for å starte et nytt spill.

2. Komme i gang

Trinn 1

Det er ikke viktig hva IDE du bruker, men for denne opplæringen jeg skal bruke JetBrains IntelliJ Idea. Åpne din IDE valg og opprette et nytt prosjekt for din Android-applikasjon. Sørg for å skape en hovedaktivitet klasse og en XML-layout.

Trinn 2

La oss først konfigurere programmets manifest fil. I søknaden node av manifestfilen, satt hardwareAccelerated til sann. Dette vil øke gjengivelse programmets selv for 2D-spill som den vi er i ferd med å skape
android. HardwareAccelerated = "true"

I neste trinn, angir vi skjermstørrelse vår søknad vil støtte. For spill, jeg vanligvis fokuserer på enheter med større skjermer, men dette valget er helt opp til deg
< støtter-skjermer android. LargeScreens = "true" android: anyDensity = "true" android: normalScreens = "true" android: smallScreens = "false" android: xlargeScreens = "true" />

I aktiviteten node av manifestfilen, legge til en node kalt configChanges og sette verdien til orientering som vist nedenfor. Du kan finne mer informasjon om denne innstillingen på utvikleren nettstedet
android. ConfigChanges = "orientering"

Før vi går videre, legge to bruker-tillatelse noder for å aktivere vibrasjon og skrivetilgang for spillet vårt. Sett inn følgende biten før søknaden node i manifestfilen
< bruker-tillatelse android. Name = "android.permission.VIBRATE" /> < bruker-tillatelse android: name = "android.permission.ACCESS_NETWORK_STATE "/>
Trinn 3

La oss også legge til de ressursene som vi skal bruke senere i denne opplæringen. Begynn med å legge det bildet du ønsker å bruke for puslespillet. Legg det til teikne mappe for prosjektet. Jeg har valgt å legge bildet til teikne-hdpi mappe med prosjektet mitt.

Sist men ikke minst, legge til lydfiler som du vil bruke i spillet ditt. I prosjektets res mappen oppretter en ny katalog som heter rå og legge lydfilene til denne mappen. For hensikten med denne opplæringen, har jeg lagt til to lydfiler. Den første lyden spilles av når spilleren beveger seg en puslespillbrikke mens den andre lyden spilles når spillet er ferdig, det vil si når spilleren fullfører puslespillet. Begge lyder er tilgjengelig på SoundBible. Den første lyden er lisensiert under Creative Commons Attribution 3.0 lisens og ble spilt inn av Mike Koenig.

3. Opprette Brain of the Game

Som jeg nevnte tidligere, vil jeg ikke forklare spillet etableringen prosessen i detalj, siden fokus for denne opplæringen er å integrere den Dolby Audio API. I de neste trinnene, vil jeg gå gjennom trinnene du må ta for å lage puslespill.

Vi starter med å lage en ny klasse, SlidePuzzle, som vil være hjernen av spillet. Hver bevegelse gjort i puslespillet er behandlet og sporet av en forekomst av denne klassen bruker enkel matematikk.

Det er en viktig del av spillet som det vil avgjøre hvilke fliser kan flyttes og i hvilken retning. Klassen vil også varsle oss når puslespillet er ferdig
pakken com.dolby.DolbyPuzzle;. Public class SlidePuzzle {}

Vi starter med å erklære en rekke variabler som vi trenger litt senere. Ta en titt på den neste kodebiten som jeg erklærer variabler for de fire mulige retninger brikkene kan bevege seg i, to matriser av heltall for de horisontale og vertikale retninger, og en rekke av flisene i puslespillet. Vi erklærer også, og opprette en forekomst av Random klassen, som vi skal bruke senere i denne opplæringen
public static final int DIRECTION_LEFT = 0;. Public static final int DIRECTION_UP = 1; public static final int DIRECTION_RIGHT = 2; offentlig statisk final int DIRECTION_DOWN = 3; public static final int [] DIRECTION_X = {-1, 0, 1, 0}; public static final int [] DIRECTION_Y = {0, -1, 0, 1}; private int [] fliser; private int handleLocation, privat Random tilfeldig = new Random (); private int bredde; private int høyde;

Det neste trinnet er å opprette en init metode for SlidePuzzle klassen. Init-metoden godtar to argumenter som bestemmer bredden og høyden på SlidePuzzle objektet. Bruke bredde- og høydeinstansvariabler, instantiate vi fliser matrise og satt handleLocation som vist nedenfor.
public void init (int bredde, int høyde) {this.width = bredde; this.height = høyde; fliser = new int [bredde * høyde]; for (int i = 0; i < tiles.length; i ++) {fliser [i] = i; } HandleLocation = tiles.length - 1;}

SlidePuzzle klassen trenger også en setter og getter metode for fliser eiendommen. Deres implementeringer er ikke så komplisert som du kan se nedenfor
public void setTiles (int [] fliser) {this.tiles = fliser.; for (int i = 0; i < tiles.length; i ++) {if (fliser [i] == tiles.length - 1) {handleLocation = i; gå i stykker; }}} Public int [] getTiles () {return fliser;}

I tillegg til accessors for fliser eiendom, har jeg også laget en håndfull dagligvare metoder som vil komme godt med senere i denne opplæringen. De getColumnAt og getRowAt metoder, for eksempel returnere kolonnen og raden av et bestemt sted i puslespillet
public int getColumnAt (int plassering). {Return beliggenhet% bredde;} public int getRowAt (int plassering) {return plassering /bredde;} public int getWidth () {return bredde;} public int getHeight () {return høyde;}

Avstanden metode, en annen hjelper metode vi skal bruke i en liten stund, beregner avstanden mellom flisene ved hjelp av enkel matematikk . og fliser rekke
public int avstand () {int dist = 0; for (int i = 0; i < tiles.length; i ++) {dist + = Math.abs (i - fliser [i]); } Avkastning dist;}

Den neste metoden er getPossibleMoves, som vi vil bruke til å bestemme mulige posisjoner Brikkene kan flytte til. I det følgende skjermbilde, er det fire puslespillbrikker som kan flyttes til det tomme sporet av puslespillet styret. Bitene spilleren kan flytte er 5, 2, 8 og 4. Har jeg ikke fortelle deg tallene ville komme til nytte?


Gjennomføringen av getPossibleMoves kan virke skremmende i begynnelsen, men det er ikke noe mer enn grunnleggende matematikk
public int getPossibleMoves () {int x = getColumnAt (handleLocation.); int y = getRowAt (handleLocation); boolean venstre = x > 0; boolean høyre = x < bredde - 1; boolean opp = y > 0; boolean ned = y < høyde - 1; retur: | (venstre 1 <; < DIRECTION_LEFT 0?) |: (høyre 1 <; < DIRECTION_RIGHT 0?) (opptil 1 < < DIRECTION_UP: 0) | (ned 1 < < DIRECTION_DOWN: 0);}

I pickRandomMove metoden bruker vi den tilfeldig objekt vi opprettet tidligere. Som navnet tilsier, beveger pickRandomMove metoden en tilfeldig brikke i puslespillet. Random objektet brukes til å generere et vilkårlig helt tall, som er returnert av pickRandomMove metoden. Metoden aksepterer også ett argument, et tall, som er plasseringen vi ignorere, det vil si i det tomme sporet i puslespillet styret
private int pickRandomMove (int utelukke) {List. ≪ Integer > trekk = new Arraylist < Integer > (4); int possibleMoves = getPossibleMoves () & ~ utelukke; if ((possibleMoves & (1 < < DIRECTION_LEFT)) > 0) {moves.add (DIRECTION_LEFT); } If ((possibleMoves & (1 < < DIRECTION_UP)) > 0) {moves.add (DIRECTION_UP); } If ((possibleMoves & (1 < < DIRECTION_RIGHT)) > 0) {moves.add (DIRECTION_RIGHT); } If ((possibleMoves & (1 < < DIRECTION_DOWN)) > 0) {moves.add (DIRECTION_DOWN); } Avkastning moves.get (random.nextInt (moves.size ()));}

invertMove metoden, som brukes litt senere i shuffle metoden, inverterer heltall brukes til en valgt retning
privat. int invertMove (int flytte) {if (flytte == 0) {return 0; } If (trekk == 1 < < DIRECTION_LEFT) {return 1 < < DIRECTION_RIGHT; } If (trekk == 1 < < DIRECTION_UP) {return 1 < < DIRECTION_DOWN; } If (trekk == 1 < < DIRECTION_RIGHT) {return 1 < < DIRECTION_LEFT; } If (trekk == 1 < < DIRECTION_DOWN) {return 1 < < DIRECTION_UP; } Return 0;}

moveTile metoden godtar to heltall, som brukes til å beregne bevegelsene som trengs ved hjelp av enkel matematikk. Metoden returnerer sant eller usant
public boolean moveTile (int retning, int) {boolean kamp = false.; for (int i = 0; i < telle; i ++) {int targetLocation = handleLocation + DIRECTION_X [retning] + DIRECTION_Y [retning] * bredde; fliser [handleLocation] = fliser [targetLocation]; Kampen | = fliser [handleLocation] == handleLocation; fliser [targetLocation] = tiles.length - 1; //Håndtak flis handleLocation = targetLocation; } Returkampen;}

shuffle metoden brukes til å stokke bitene i puslespillet når et nytt spill begynner. Ta deg tid til å inspisere gjennomføringen som det er en viktig del av spillet. I blanding, vi bestemme grensen, basert på høyden og bredden av puslespillet. Som du kan se, bruker vi avstanden metode for å bestemme antall brikker som må flyttes
public void shuffle () {if. (Bredde < 2 || høyde < 2) {return; } Int limit = bredde * høyde * Math.max (bredde, høyde); int = 0 trekk; while (avstand () < grense) {move = pickRandomMove (invertMove (flytte)); moveTile (flytte, 1); }}

Det er to flere hjelpemetoder vi trenger for å implementere, getDirection og getHandleLocation. Den getDirection metoden returnerer den retningen som puslespillbiten på stedet er flyttet og getHandleLocation returnerer tomme sporet i puslespillet styret
public int getDirection (int plassering) {int delta = plassering - handleLocation.; if (delta% bredde == 0) {return delta < 0? DIRECTION_UP: DIRECTION_DOWN; } Else if (handleLocation /bredde == (handleLocation + delta) /bredde) {return delta < 0? DIRECTION_LEFT: DIRECTION_RIGHT; } Else {return -1; }} public int getHandleLocation () {return handleLocation;}
4. Opprette Puzzle Styret

Opprett en ny klasse og kaller det SlidePuzzleView. Denne klassen er utsikten i puslespillet bord, utvider den Vis klassen og vil ta opp hele skjermen på enheten. Klassen er ansvarlig for å tegne brikkene samt håndtering berørings hendelser.

I tillegg til Context objekt, konstruktøren av SlidePuzzleView godtar også en forekomst av SlidePuzzle klassen som du kan se nedenfor. Anmeldelser Pakken com.dolby.DolbyPuzzle, import android.content.Context, import android.view.View; public class SlidePuzzleView strekker Vis {public SlidePuzzleView (Context kontekst, SlidePuzzle slidePuzzle) {super (sammenheng); ...}} Public static enum ShowNumbers {NONE, NOEN, ALL}; private static final int FRAME_SHRINK = 1; private static lang slutt VIBRATE_DRAG = 5; private static lang slutt VIBRATE_MATCH = 50; private static lang slutt VIBRATE_SOLVED = 250; privat statisk final int COLOR_SOLVED = 0xff000000; private static final int COLOR_ACTIVE = 0xff303030; privat Bitmap bitmap, privat Rect sourceRect; privat RectF targetRect; privat SlidePuzzle slidePuzzle; private int targetWidth; private int targetHeight; private int targetOffsetX; private int targetOffsetY; private int puzzleWidth; private int puzzleHeight; private int targetColumnWidth; private int targetRowHeight; private int sourceColumnWidth; private int sourceRowHeight; private int sourceWidth; private int sourceHeight; privat Set < Integer > dregging = null; private int dragStartX; private int dragStartY; private int dragOffsetX; private int dragOffsetY; private int dragDirection; private ShowNumbers showNumbers = ShowNumbers.SOME; privat Paint textPaint; private int canvasWidth; private int canvasHeight; privat Paint framePaint; private boolean dragInTarget = false; private int [] fliser, privat Paint tilePaint, offentlig SlidePuzzleView (Context kontekst, SlidePuzzle slidePuzzle) {super (sammenheng); sourceRect = new Rect (); targetRect = new RectF (); this.slidePuzzle = slidePuzzle; tilePaint = new Paint (); tilePaint.setAntiAlias ​​(true); tilePaint.setDither (true); tilePaint.setFilterBitmap (true); textPaint = new Paint (); textPaint.setARGB (0xff, 0xff, 0xff, 0xff); textPaint.setAntiAlias ​​(true); textPaint.setTextAlign (Paint.Align.CENTER); textPaint.setTextSize (20); textPaint.setTypeface (Typeface.DEFAULT_BOLD); textPaint.setShadowLayer (1, 2, 2, 0xff000000); framePaint = new Paint (); framePaint.setARGB (0xff, 0x80, 0x80, 0x80); framePaint.setStyle (Style.STROKE);}

Vi styre klassens onSizeChanged metode og i denne metoden satt vi puzzleWidth og puzzleHeight til 0.
Overrideprotected void onSizeChanged (int w, int h, int oldw, int oldh ) {puzzleWidth = puzzleHeight = 0;}

refreshDimensions metoden startes når dimensjonene av endringen utsikt og puslespillet må gjenoppbygges. Denne metoden er påberopt i klassens onDraw metode
private void refreshDimensions () {targetWidth = canvasWidth.; targetHeight = canvasHeight; sourceWidth = bitmap.getWidth (); sourceHeight = bitmap.getHeight (); double targetRatio = (dobbel) targetWidth /(dobbel) targetHeight; double sourceRatio = (dobbel) sourceWidth /(dobbel) sourceHeight; targetOffsetX = 0; targetOffsetY = 0; if (sourceRatio > targetRatio) {int newTargetHeight = (int) (targetWidth /sourceRatio); int delta = targetHeight - newTargetHeight; targetOffsetY = delta /2; targetHeight = newTargetHeight; } Else if (sourceRatio < targetRatio) {int newTargetWidth = (int) (targetHeight * sourceRatio); int delta = targetWidth - newTargetWidth; targetOffsetX = delta /2; targetWidth = newTargetWidth; } PuzzleWidth = slidePuzzle.getWidth (); puzzleHeight = slidePuzzle.getHeight (); targetColumnWidth = targetWidth /puzzleWidth; targetRowHeight = targetHeight /puzzleHeight; sourceColumnWidth = sourceWidth /puzzleWidth; sourceRowHeight = sourceHeight /puzzleHeight;}

I onDraw metoden i SlidePuzzleView klassen, tar selve tegningen i puslespillet sted, inkludert tegning linjene i puslespillet bord, men vi har også satt dimensjonene brikkene for å være sikker de pent passe skjermen på enheten. Utsikten er SlidePuzzle eksempel hjelper oss å legge ut visningen som du kan se i gjennomføringen av onDraw nedenfor
Overrideprotected void onDraw (lerret lerret) {if (slidePuzzle == null || bitmap == null) {return.; } If (puzzleWidth = slidePuzzle.getWidth () || puzzleHeight = slidePuzzle.getHeight ()!) {RefreshDimensions (); } Boolean løst = slidePuzzle.isSolved (); canvas.drawColor:; (løst COLOR_SOLVED COLOR_ACTIVE?) int [] originalTiles = slidePuzzle.getTiles (); if (fliser == null || tiles.length = originalTiles.length!) {fliser = new int [originalTiles.length]; } For (int i = 0; i < tiles.length; i ++) {if (originalTiles [i] == originalTiles.length - 1) {fortsette; } If (dragInTarget & & dragging.contains (i)) {fliser [i - SlidePuzzle.DIRECTION_X [dragDirection] - puzzleWidth * SlidePuzzle.DIRECTION_Y [dragDirection]] = originalTiles [i]; } Else {fliser [i] = originalTiles [i]; }} Int delta =! DragInTarget? 0: (SlidePuzzle.DIRECTION_X [dragDirection] + puzzleWidth * SlidePuzzle.DIRECTION_Y [dragDirection]) * dragging.size (); int shownHandleLocation = slidePuzzle.getHandleLocation () + delta; fliser [shownHandleLocation] = tiles.length - 1; int emptyTile = tiles.length - 1; for (int i = 0; i < tiles.length; i ++) {if (løst &! & originalTiles [i] == emptyTile) {fortsette; } Int targetColumn = slidePuzzle.getColumnAt (i); int targetRow = slidePuzzle.getRowAt (i); int sourceColumn = slidePuzzle.getColumnAt (originalTiles [i]); int sourceRow = slidePuzzle.getRowAt (originalTiles [i]); targetRect.left = targetOffsetX + targetColumnWidth * targetColumn; targetRect.top = targetOffsetY + targetRowHeight * targetRow; targetRect.right = targetColumn < puzzleWidth - 1? targetRect.left + targetColumnWidth: targetOffsetX + targetWidth; targetRect.bottom = targetRow < puzzleHeight - 1? targetRect.top + targetRowHeight: targetOffsetY + targetHeight; sourceRect.left = sourceColumnWidth * sourceColumn; sourceRect.top = sourceRowHeight * sourceRow; sourceRect.right = sourceColumn < puzzleWidth - 1? sourceRect.left + sourceColumnWidth: sourceWidth; sourceRect.bottom = sourceRow < puzzleHeight - 1? sourceRect.top + sourceRowHeight: sourceHeight; boolean isDragTile = dra = null &! & dragging.contains (I); boolean matchLeft; boolean matchRight; boolean matchTop; boolean matchBottom; int di = i; if (dragInTarget & & dragging.contains (i)) {di = di - SlidePuzzle.DIRECTION_X [dragDirection] - puzzleWidth * SlidePuzzle.DIRECTION_Y [dragDirection]; } If (di == fliser [di]) {matchLeft = matchRight = matchTop = matchBottom = true; } Else {matchLeft = (di - 1) > = 0 & & di% puzzleWidth > 0 & & fliser [di]% puzzleWidth > 0 & & fliser [di - 1] == fliser [di] - 1; matchRight = fliser [di] + 1 < tiles.length - 1 & & (di + 1)% puzzleWidth > 0 & & (fliser [di] + 1)% puzzleWidth > 0 & & (di + 1) < tiles.length & & (di + 1)% puzzleWidth > 0 & & fliser [di + 1] == fliser [di] + 1; matchTop = (di - puzzleWidth) > = 0 & & fliser [di - puzzleWidth] == fliser [di] - puzzleWidth; matchBottom = fliser [di] + puzzleWidth < tiles.length - 1 & & (di + puzzleWidth) < tiles.length & & fliser [di + puzzleWidth] == fliser [di] + puzzleWidth; } If (matchLeft!) {SourceRect.left + = FRAME_SHRINK; targetRect.left + = FRAME_SHRINK; } If (matchRight!) {SourceRect.right - = FRAME_SHRINK; targetRect.right - = FRAME_SHRINK; } If (matchTop!) {SourceRect.top + = FRAME_SHRINK; targetRect.top + = FRAME_SHRINK; } If {sourceRect.bottom - = FRAME_SHRINK (matchBottom!); targetRect.bottom - = FRAME_SHRINK; } If (isDragTile) {targetRect.left + = dragOffsetX; targetRect.right + = dragOffsetX; targetRect.top + = dragOffsetY; targetRect.bottom + = dragOffsetY; } Canvas.drawBitmap (bitmap, sourceRect, targetRect, tilePaint); if (matchLeft!) {canvas.drawLine (targetRect.left, targetRect.top, targetRect.left, targetRect.bottom, framePaint); } If {canvas.drawLine (targetRect.right - 1, targetRect.top, targetRect.right - 1, targetRect.bottom, framePaint) (matchRight!); } If (matchTop!) {Canvas.drawLine (targetRect.left, targetRect.top, targetRect.right, targetRect.top, framePaint); } If {canvas.drawLine (targetRect.left, targetRect.bottom - 1, targetRect.right, targetRect.bottom - 1, framePaint) (matchBottom!); } If (løst &! &Amp; (showNumbers == ShowNumbers.ALL || (showNumbers == ShowNumbers.SOME & &! Di = fliser [di]))) {canvas.drawText (String.valueOf (originalTiles [ ,,,0],i] + 1), (targetRect.left + targetRect.right) /2, (targetRect.top + targetRect.bottom) /2 - (textPaint.descent () + textPaint.ascent ()) /2, textPaint); }}}

For å håndtere berørings hendelser, må vi overstyre klassens onTouchEvent metode. For å holde onTouchEvent konsis og lesbar, har jeg også erklært noen hjelpemetoder, finishDrag, doMove, startdrag, og updateDrag. Disse metodene hjelper implementere dra atferd
Overridepublic boolsk onTouchEvent (MotionEvent hendelse) {if (slidePuzzle == null || bitmap == null) {return false.; } If (slidePuzzle.isSolved ()) {return false; } If (event.getAction () == MotionEvent.ACTION_DOWN) {return startdrag (event); } Else if (event.getAction () == MotionEvent.ACTION_MOVE) {return updateDrag (event); } Else if (event.getAction () == MotionEvent.ACTION_UP) {return finishDrag (event); } Else {return false; }} private boolean finishDrag (MotionEvent hendelse) {if (dra == null) {return false; } UpdateDrag (event); if (dragInTarget) {doMove (dragDirection, dragging.size ()); } Else {vibrere (VIBRATE_DRAG); } DragInTarget = false; dra = null; ugyldig (); return true;} private void doMove (int dragDirection, int) {playSlide (); if (slidePuzzle.moveTile (dragDirection, telle)) {vibrere (slidePuzzle.isSolved () VIBRATE_SOLVED:? VIBRATE_MATCH); } Else {vibrere (VIBRATE_DRAG); } Ugyldig (); if (slidePuzzle.isSolved ()) {onFinish (); }} private boolean startdrag (MotionEvent hendelse) {if (! dra = null) {return false; } Int x = ((int) event.getX () - targetOffsetX) /targetColumnWidth; int y = ((int) event.getY () - targetOffsetY) /targetRowHeight; if (x < 0 || x > = puzzleWidth || y < 0 || y > = puzzleHeight) {return false; } Int retning slidePuzzle.getDirection = (x + puzzleWidth * y); if (retning > = 0) {dra = new HashSet < Integer > (); while (x + puzzleWidth * y = slidePuzzle.getHandleLocation ()) {dragging.add (x + puzzleWidth * y); dragStartX = (int) event.getX (); dragStartY = (int) event.getY (); dragOffsetX = 0; dragOffsetY = 0; dragDirection = retning; x - = SlidePuzzle.DIRECTION_X [retning]; y - = SlidePuzzle.DIRECTION_Y [retning]; }} DragInTarget = false; vibrere (VIBRATE_DRAG); return true;} private boolean updateDrag (MotionEvent hendelse) {if (dra == null) {return false; } Int directionX = SlidePuzzle.DIRECTION_X [dragDirection] * -1; int directionY = SlidePuzzle.DIRECTION_Y [dragDirection] * -1; if (directionX = 0) {dragOffsetX = (int) event.getX () - dragStartX; if (Math.signum (dragOffsetX) = directionX!) {dragOffsetX = 0; } Else if (Math.abs (dragOffsetX) > targetColumnWidth) {dragOffsetX = directionX * targetColumnWidth; }} If (directionY = 0) {dragOffsetY = (int) event.getY () - dragStartY; if (Math.signum (dragOffsetY) = directionY!) {dragOffsetY = 0; } Else if (Math.abs (dragOffsetY) > targetRowHeight) {dragOffsetY = directionY * targetRowHeight; }} DragInTarget = Math.abs (dragOffsetX) > targetColumnWidth /2 || Math.abs (dragOffsetY) > targetRowHeight /2; ugyldig (); return true;}

Jeg har også erklært getter metoder for targetWidth og targetHeight og accessors for bitmap
public int getTargetWidth () {return targetWidth;.} public int getTargetHeight () {return targetHeight;} public void SetBitmap ( Bitmap bitmap) {this.bitmap = bitmap; puzzleWidth = 0; puzzleHeight = 0;} public Bitmap getBitmap () {return bitmap;}
5. Opprette Aktivitetsklasse

Med gjennomføringen av SlidePuzzle og SlidePuzzleView klasser ferdig, er det på tide å fokusere på de viktigste aktivitet klassen som IDE opprettet for deg. Hovedaktiviteten klasse i dette eksempelet heter SlidePuzzleMain, men din kan være et annet navn. Den SlidePuzzleMain klassen vil samle alt som vi har laget så langt
pakken com.dolby.DolbyPuzzle;. Import android.app.Activity; public class SlidePuzzleMain strekker Aktivitet {Override beskyttet void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); ...}} Beskyttet statisk final int MENU_SCRAMBLE = 0; beskyttet statisk final int MENU_SELECT_IMAGE = 1; beskyttet statisk final int MENU_TAKE_PHOTO = 2; beskyttet statisk final int RESULT_SELECT_IMAGE = 0; beskyttet statisk final int RESULT_TAKE_PHOTO = 1; beskyttet statiske endelige String KEY_SHOW_NUMBERS = "showNumbers"; beskyttede statisk endelige String KEY_IMAGE_URI = "imageUri"; beskyttede statisk endelige String KEY_PUZZLE = "slidePuzzle"; beskyttet statisk endelige String KEY_PUZZLE_SIZE = "puzzleSize"; beskyttet statisk endelige String FILENAME_DIR = "dolby.digital.plus"; beskyttes statiske endelige String FILENAME_PHOTO_DIR = FILENAME_DIR + "/bilder"; beskyttet statisk endelige String FILENAME_PHOTO = "bilde.jpg"; beskyttet statisk final int DEFAULT_SIZE = 3; privat SlidePuzzleView view; privat SlidePuzzle slidePuzzle; private alternativer bitmapOptions; private int puzzleWidth = 1; private int puzzleHeight = 1; privat Uri imageUri; private boolean portrett, private boolean ekspert;

I aktivitetens onCreate metode, instantiate vi bitmapOptions protestere, sette sin inScaled attributt til false. Vi skaper også en forekomst av SlidePuzzle klasse og en forekomst av SlidePuzzleView klassen, passerer den aktiviteten som utsikten kontekst. Vi satt aktiviteten syn ved å påberope setContentView og bestått i visningen objektet.
bitmapOptions = nye BitmapFactory.Options (); bitmapOptions.inScaled = false; slidePuzzle = new SlidePuzzle (); view = ny SlidePuzzleView (dette, slidePuzzle); setContentView (vis);

I loadBitmap, vi laste bildet at du har lagt til prosjektet i begynnelsen av denne opplæringen, og at vi vil bruke for puslespillet. Metoden godtar plasseringen av bildet som sitt eneste argument, som den bruker til å hente bildet
beskyttet void loadBitmap (Uri uri) {try {Alternativer o = nye alternativer ().; o.inJustDecodeBounds = true; Input imageStream = getContentResolver () openInputStream (URI).; BitmapFactory.decodeStream (imageStream, null, o); int targetWidth = view.getTargetWidth (); int targetHeight = view.getTargetHeight (); if (o.outWidth > o.outHeight & & targetWidth < targetHeight) {int i = targetWidth; targetWidth = targetHeight; targetHeight = i; } If (targetWidth < o.outWidth || targetHeight < o.outHeight) {double widthRatio = (dobbel) targetWidth /(dobbel) o.outWidth; double heightRatio = (dobbel) targetHeight /(dobbel) o.outHeight; dobbel ratio = Math.max (widthRatio, heightRatio); o.inSampleSize = (int) Math.pow (2, (int) Math.round (Math.log (ratio) /Math.log (0,5))); } Else {o.inSampleSize = 1; } O.inScaled = false; o.inJustDecodeBounds = false; imageStream = getContentResolver () openInputStream (URI).; Bitmap bitmap = BitmapFactory.decodeStream (imageStream, null, o); if (bitmap == null) {Toast.makeText (dette, getString (R.string.error_could_not_load_image), Toast.LENGTH_LONG) .vis (); komme tilbake; } Int rotere = 0; Pekeren peker = getContentResolver () spørring (uri, new String [] {MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null.); if (! markøren = null) {try {if (cursor.moveToFirst ()) {rotere = cursor.getInt (0); if (rotere == -1) {rotere = 0; }}} Finally {cursor.close (); }} If (roter = 0) {Matrix matrise = new Matrix (); matrix.postRotate (rotere); bitmap = Bitmap.createBitmap (bitmap, 0, 0, bitmap.getWidth (), bitmap.getHeight (), matrise, true); } SetBitmap (bitmap); imageUri = uri; } Catch (FileNotFoundException ex) {Toast.makeText (dette, MessageFormat.format (getString (R.string.error_could_not_load_image_error), ex.getMessage ()), Toast.LENGTH_LONG) .vis (); komme tilbake; }}

I loadBitmap vi også påberope SetBitmap. Gjennomføringen av SetBitmap er vist nedenfor
private void SetBitmap (Bitmap bitmap) {portrett = bitmap.getWidth () <.; bitmap.getHeight (); view.setBitmap (bitmap); setPuzzleSize (Math.min (puzzleWidth, puzzleHeight), true); setRequestedOrientation (stående ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);}

For å gjøre puslespillet mer attraktivt for spilleren, vil vi legge et alternativ for å tilpasse spillet ved å la spilleren til å velge et bilde for puslespill fra brukerens bildegalleri eller ta en med enhetens kamera. Vi vil også opprette et menyvalg for hver metode.

For å gjøre alt dette arbeidet, vi gjennomføre to nye metoder, selectImage og takePicture, der vi skaper en intensjon om å hente bildet vi trenger. Den onActivityResult metoden håndterer resultatet av brukerens valg. Ta en titt på kodebiten nedenfor for å forstå helheten
private void selectImage () {Intent photoPickerIntent = new Intent (Intent.ACTION_PICK.); photoPickerIntent.setType ("image /*"); startActivityForResult (photoPickerIntent, RESULT_SELECT_IMAGE);} private void takePicture () {File dir = getSaveDirectory (); if (dir == null) {Toast.makeText (dette, getString (R.string.error_could_not_create_directory_to_store_photo), Toast.LENGTH_SHORT) .vis (); komme tilbake; } File fil = new File (dir, FILENAME_PHOTO); Intent photoPickerIntent = new Intent (MediaStore.ACTION_IMAGE_CAPTURE); photoPickerIntent.putExtra (MediaStore.EXTRA_OUTPUT, Uri.fromFile (fil)); return true; return true; return true;



Previous:
Next Page: