Bygge en spilleautomat i Android: ViewFlipper meet gest detector

Jeg har vært i Vegas noen ganger, selv om jeg ikke liker å spille. Den ene gangen jeg vant $ 150 fra en spilleautomat, innbetalte jeg øyeblikkelig og brukte pengene til å kjøpe seter på første rad til et magisk show i Penn & Teller. Den autograferte billettstubben er gjemt bort blant de mest verdsatte eiendelene mine - rett ved siden av Jayne-hatten jeg plukket opp da Adam Baldwin kom til Dallas Comic Con for noen år siden. Jeg kler av.

I forrige ukes innlegg brukte vi tid på å pirke på Android's gestdetektor. I mine avsluttende kommentarer foreslo jeg at gest-API-en kunne brukes til å snurre hjulene på en spilleautomat, og det fikk meg til å tenke. Mens mange av mine TechRepublic tutorials stammer fra utfordringer i det virkelige liv jeg møter som en del av fulltidens spillejobb som Android-konsulent, bruker jeg bloggen en gang for å prøve noe uten andre grunner enn at jeg tror det ville vært gøy.

Så mens jeg ikke liker å spille spilleautomater med mine egne penger, var ingeniøren i meg fascinert og litt spent på ideen om å kombinere Androids ViewFlipper-klasse med gestdetektoren for å simulere spinnhjulet på et sjansespill. Jeg trengte å finne en måte å bruke animasjonene dynamisk på, samt en algoritme for å beregne antall rotasjoner ... åh, og la oss ikke glemme en metode for å redusere hastigheten over tid basert på hvor raskt eller sakte brukeren slenger hjul. Jeg fortalte deg at det høres ut som moro.

Er du fortsatt med meg? Følg i så fall sammen med trinn-for-trinn-opplæringen nedenfor eller last ned og importer hele prosjektet direkte til Eclipse.

1. Lag et nytt prosjekt i Eclipse som målretter Android 1.6 eller nyere. Sørg for å gi nytt navn til oppstartsaktiviteten til Main.java.

2. Vi vil aldri at spilleautomat-appen vår skal kjøres i noe annet enn portrettmodus, så modifiser AndroidManifest.xml-filen for å svelge retningsendringer.

AndroidMainfest.xml

 "1.0" encoding = "utf-8" ?> 
 "Http://schemas.android.com/apk/res/android" 
 package = "com.authorwjf.slot" 
 android: versionCode = "1" 
 android: versionName = "1.0" > 
 "4" /> 
 android: icon = "@ drawable / ic_launcher" 
 android: label = "@ string / app_name" > 
 android: name = ".Main" 
 android: configChanges = "orientering" 
 android: screenOrientation = "portrett" 
 android: label = "@ string / app_name" > 
 "android.intent.action.MAIN" /> 
 "android.intent.category.LAUNCHER" /> 

3. Du må lage en / tegnbar mappe under katalogen / res og legge til tre PNG-bilder - noe frukt vil gjøre. Jeg fant bilder fra et offentlig kirsebær, en sitron og en pære. Mmmmm!

4. Å definere oppsettet for spilleautomaten vår er litt mer sammensatt enn hva jeg normalt prøver å gjøre i disse opplæringsprogrammene; grunnen er ViewFlipper. Den gode nyheten er fordi så mye av oppførselen til ViewFlipper er definert i XML, når vi kommer til å bruke den, er det nesten ingen kode knyttet til widgeten. For øyeblikket er det bare å åpne /res/layout/main.xml og lime inn i følgende oppsett.

main.xml

 "1.0" encoding = "utf-8" ?> 
 "Http://schemas.android.com/apk/res/android" 
 android: layout_width = "fill_parent" 
 android: layout_height = "fill_parent" 
 android: orientering = "vertikal" > 
 android: layout_width = "fill_parent" 
 android: layout_height = "wrap_content" 
 android: gravitasjon = "sentrum" 
 android: textSize = "28sp" 
 android: paddingTop = "10dip" 
 android: textColor = "# 00ff00" 
 android: text = "Spilleautomateksempel" 
 android: paddingBottom = "50dip" /> 
 android: layout_margin = "6dip" 
 android: id = "@ + id / view_flipper" 
 android: layout_width = "wrap_content" 
 android: layout_height = "wrap_content" 
 android: layout_gravity = "sentrum" 
 android: gravitasjon = "sentrum" > 
 android: layout_width = "fill_parent" 
 android: layout_height = "fill_parent" 
 android: orientering = "vertikal" 
 android: layout_gravity = "sentrum" 
 android: gravitasjon = "sentrum" > 
 android: layout_height = "wrap_content" 
 android: layout_width = "fill_parent" 
 android: layout_gravity = "sentrum" 
 android: gravitasjon = "sentrum" 
 android: src = "@ trekkbar / pære" /> 
 android: layout_width = "fill_parent" 
 android: layout_height = "fill_parent" 
 android: orientering = "vertikal" 
 android: layout_gravity = "sentrum" 
 android: gravitasjon = "sentrum" > 
 android: layout_height = "wrap_content" 
 android: layout_width = "fill_parent" 
 android: layout_gravity = "sentrum" 
 android: src = "@ drawable / cherry" /> 
 android: layout_width = "fill_parent" 
 android: layout_height = "fill_parent" 
 android: orientering = "vertikal" 
 android: layout_gravity = "sentrum" 
 android: gravitasjon = "sentrum" > 
 android: layout_height = "wrap_content" 
 android: layout_width = "fill_parent" 
 android: layout_gravity = "sentrum" 
 android: src = "@ trekkbar / sitron" /> 
 android: layout_width = "fill_parent" 
 android: layout_height = "wrap_content" 
 android: id = "@ + id / hastighet" 
 android: gravitasjon = "sentrum" /> 
 android: layout_width = "fill_parent" 
 android: layout_height = "wrap_content" 
 android: id = "@ + id / teller" 
 android: gravitasjon = "sentrum" /> 
 android: layout_width = "fill_parent" 
 android: layout_height = "wrap_content" 
 android: id = "@ + id / hastighet" 
 android: gravitasjon = "sentrum" /> 

5. Nå er det på tide å få koding! I mappen / src åpner du Main.java og begynner med å lage noen klassevariabler og initialisere dem i overstyring på opprett.

 Main.java 
 pakke com.authorwjf.slot; 
 import android.app.Aktivitet; 
 import android.os.Bundle; 
 import android.os.Handler; 
 import android.view.GestureDetector; 
 import android.view.MotionEvent; 
 import android.view.GestureDetector.OnGestureListener; 
 import android.view.animation.AccelerateInterpolator; 
 import android.view.animation.Animation; 
 import android.view.animation.TranslateAnimation; 
 import android.widget.TextView; 
 import android.widget.ViewFlipper; 
 public class Main utvider aktivitetsredskaper OnGestureListener { 
 privat ViewFlipper mViewFlipper; 
 private GestureDetector mDetector; 
 privat int mSpeed; 
 privat int mCount; 
 privat int mFactor; 
 private boolske mAnimating; 
 @Overstyring 
 public void onCreate (Bundle savedInstanceState) { 
 super .onCreate (savedInstanceState); 
 setContentView (R.layout. main ); 
 mViewFlipper = (ViewFlipper) findViewById (R.id. view_flipper ); 
 mDetector = ny GestureDetector ( dette ); 
 mAnimating = falsk ; 
 mCount = 0; 
 mSpeed ​​= 0; 
 } 
 } 

6. Hvis du husker fra forrige uke, betyr det å la hovedaktiviteten implementere on-gest lytter, at vi må legge til syv tilbakeringingsfunksjoner - hvorav fem bare lar Android Eclipse-plugin-modulen generere for oss.

 @Overstyring 
 public void onLongPress (MotionEvent arg0) { 
 // TODO Auto-generert metodestub 
 } 
 @Overstyring 
 offentlig boolsk onScroll (MotionEvent arg0, MotionEvent arg1, float arg2, 
 float arg3) { 
 // TODO Auto-generert metodestub 
 return falsk ; 
 } 
 @Overstyring 
 public void onShowPress (MotionEvent arg0) { 
 // TODO Auto-generert metodestub 
 } 
 @Overstyring 
 offentlig boolsk onSingleTapUp (MotionEvent arg0) { 
 // TODO Auto-generert metodestub 
 return falsk ; 
 } 
 @Overstyring 
 offentlig boolsk onDown (MotionEvent arg0) { 
 // TODO Auto-generert metodestub 
 return falsk ; 
 } 

7. De gjenværende bevegelsesrelaterte overstyringene krever tilpasset kode. Den første forplanter berøringshendelsen til bevegelsesdetektoren, mens den andre implementerer vår på sleng-logikk. Det kan hende du må lese igjennom loggen på nettet et par ganger; det er ansvarlig for å sette i gang et antall rotasjoner, så vel som starthastigheten og den tidsbestemte reduksjonsfaktoren, basert på det første vertikale hastighetsargumentet. Try / fangst forhindrer en skillet med null feil som kan oppstå hvis en bruker sveipet skjermen smertefullt sakte og dermed får en hastighet på nesten null. Siden vi snakker om Y-aksen, regnes alt mer enn 0 som en sveip nedover; ellers antar vi det.

 @Overstyring 
 offentlig boolsk onTouchEvent (MotionEvent me) { 
 returner mDetector.onTouchEvent (meg); 
 } 
 @Overstyring 
 offentlig boolsk onFling (MotionEvent start, MotionEvent finish, float xVelocity, float yVelocity) { 
 prøv { 
 hvis (mAnimating) returnere true ; 
 mAnimating = true ; 
 mCount = ( int ) Matematikk. abs (yVelocity) / 300; 
 mFactor = ( int ) 300 / mCount; 
 mSpeed ​​= mFactor; 
 if (yVelocity> 0) { 
 //ned 
 Handler h = new Handler (); 
 h.postDelayed (r2, mSpeed); 
 } annet { 
 //opp 
 Handler h = new Handler (); 
 h.postDelayed (r1, mSpeed); 
 } 
 ((TextView) findViewById (R.id. Hastighet )). SetText ("VELOCITY =>" + Float. ToString (yVelocity)); 
 } fangst (ArithmeticException e) { 
 // sveipes for sakte registrerer ikke 
 mAnimating = falsk ; 
 } 
 return true ; 
 } 

8. Som ofte er tilfelle med Android, kommer noen av de vanskeligste logikkene inn når du bruker animasjoner. For dette formålet har jeg ansatt to matchende rutiner. For å håndtere oppbevegelsen har jeg en kjørbar sammen med de dynamiske animasjonene. Siden animasjonstimingen ikke trenger å være nøyaktig, bruker jeg en behandler og lenker innlegg.

 privat Runnable r1 = new Runnable () { 
 @Overstyring 
 public void run () { 
 opp(); 
 if (mCount <1) { 
 mAnimating = falsk ; 
 } annet { 
 Handler h = new Handler (); 
 h.postDelayed (r1, mSpeed); 
 } 
 } 
 }; 
 privat tomrom opp () { 
 mCount--; 
 mSpeed ​​+ = mFactor; 
 Animasjon inFromBottom = new TranslateAnimation ( 
 Animasjon. RELATIVE_TO_PARENT, 0.0f, 
 Animasjon. RELATIVE_TO_PARENT, 0.0f, 
 Animasjon. RELATIVE_TO_PARENT, 1.0f, 
 Animasjon. RELATIVE_TO_PARENT, 0, 0f); 
 inFromBottom.setInterpolator ( ny AccelerateInterpolator ()); 
 inFromBottom.setDuration (mSpeed); 
 Animasjon outToTop = ny TranslateAnimation ( 
 Animasjon. RELATIVE_TO_PARENT, 0.0f, 
 Animasjon. RELATIVE_TO_PARENT, 0.0f, 
 Animasjon. RELATIVE_TO_PARENT, 0.0f, 
 Animasjon. RELATIVE_TO_PARENT, -1.0f); 
 outToTop.setInterpolator ( ny AccelerateInterpolator ()); 
 outToTop.setDuration (mSpeed); 
 mViewFlipper.clearAnimation (); 
 mViewFlipper.setInAnimation (inFromBottom); 
 mViewFlipper.setOutAnimation (outToTop); 
 if (mViewFlipper.getDisplayedChild () == 0) { 
 mViewFlipper.setDisplayedChild (2); 
 } annet { 
 mViewFlipper.showPrevious (); 
 } 
 ((TextView) findViewById (R.id. Counter )). SetText ("COUNTER =>" + Heltall. ToString (mCount)); 
 ((TextView) findViewById (R.id. Hastighet )). SetText ("SPEED =>" + Heltall. ToString (mSpeed)); 
 } 

9. I motsetning til retningen har vi to nesten identiske funksjoner for å håndtere en nedadgående sving på hjulet.

 privat Runnable r2 = new Runnable () { 
 @Overstyring 
 public void run () { 
 ned(); 
 if (mCount <1) { 
 mAnimating = falsk ; 
 } annet { 
 Handler h = new Handler (); 
 h.postDelayed (r2, mSpeed); 
 } 
 } 
 }; 
 privat tomrom ned () { 
 mCount--; 
 mSpeed ​​+ = mFactor; 
 Animasjon outToBottom = ny TranslateAnimation ( 
 Animasjon. RELATIVE_TO_PARENT, 0.0f, 
 Animasjon. RELATIVE_TO_PARENT, 0.0f, 
 Animasjon. RELATIVE_TO_PARENT, 0.0f, 
 Animasjon. RELATIVE_TO_PARENT, 1.0f); 
 outToBottom.setInterpolator ( ny AccelerateInterpolator ()); 
 outToBottom.setDuration (mSpeed); 
 Animasjon inFromTop = new TranslateAnimation ( 
 Animasjon. RELATIVE_TO_PARENT, 0.0f, 
 Animasjon. RELATIVE_TO_PARENT, 0.0f, 
 Animasjon. RELATIVE_TO_PARENT, -1.0f, 
 Animasjon. RELATIVE_TO_PARENT, 0, 0f); 
 inFromTop.setInterpolator ( ny AccelerateInterpolator ()); 
 inFromTop.setDuration (mSpeed); 
 mViewFlipper.clearAnimation (); 
 mViewFlipper.setInAnimation (inFromTop); 
 mViewFlipper.setOutAnimation (outToBottom); 
 if (mViewFlipper.getDisplayedChild () == 0) { 
 mViewFlipper.setDisplayedChild (2); 
 } annet { 
 mViewFlipper.showPrevious (); 
 } 
 ((TextView) findViewById (R.id. Counter )). SetText ("COUNTER =>" + Heltall. ToString (mCount)); 
 ((TextView) findViewById (R.id. Hastighet )). SetText ("SPEED =>" + Heltall. ToString (mSpeed)); 
 } 

Jackpot! Mens den endelige løsningen endte opp med å være mer kode enn jeg forestilte meg ved begynnelsen, er ingeniøren i meg fornøyd med resultatene. Animasjonen er ganske glatt på Nexus S som kjører Jelly Bean. Hvis du har en eldre telefon, vil jeg være nysgjerrig på å vite hvordan det ser ut. Husk å legge inn tanker om dette emnet i diskusjonstråden. I mellomtiden skal jeg snurre hjulet noen ganger til og deretter melde meg av.

© Copyright 2021 | pepebotifarra.com