ABCene for Android-spillutvikling: Last inn og vis sprites

Målet med spillet vi utvikler i denne Android-app-utviklingsserien er å justere den flygende tallerkenens fart for å unngå å bli smadret til biter av asteroiden. Dette prosjektet inkluderer alle de viktigste aspektene ved et videospill: et lerret, sprites, animasjon, kollisjonsdeteksjon og brukerinput.

I del en laget vi en tegningsflate og et rammeverk for å kontrollere og oppdatere innholdet på lerretet. Vi malte romskalaen vår, smadret den med tilfeldige stjerner og fikk til og med disse stjernene til å pulsere. Det neste logiske trinnet i å bygge spillet vårt er lasting og visning av sprites. I denne sammenheng er en sprite "en datagrafikk som kan flyttes på skjermen og på annen måte manipuleres som en enhet."

I dokumentaren Indie Gamer beskriver en av utviklerne prosessen med å lage et videospill omtrent som det å lage en film i miniskala. Hvis du tenker på prosessen fra dette perspektivet, bygde vi i del en scenen eller settet vårt. Sprites er skuespillerne vi setter inn i en scene og instruerer dem til å gjøre noe interessant. For våre formål bruker vi bare to sprites: en UFO ( figur A ) og en asteroide ( figur B ). Figur A

Figur B

Merk: Bildene over ser ut til å være en del av det offentlige domene. Hvis du er kunstneren og vet annerledes, kan du kontakte meg, så gir jeg deg en attribusjon.

Laster og viser sprites

Denne opplæringen bygger på det vi opprettet i del en. For å virkelig forstå hva som skjer, hjelper det å se koden i sammenheng med helheten. Derfor vil kodelisten i opplæringen være vårt komplette arbeidsgrunnlag, med den nye koden kommentert på linje. Du kan følge med trinnvise instruksjoner eller laste ned og importere hele prosjektet til Eclipse.

1. Lag et nytt Android-prosjekt i Eclipse. Sørg for å målrette mot Android 2.1 eller nyere. Gi nytt navn til oppstartsaktiviteten til Main.java og den tilhørende layout-definisjonen til main.xml.

2. Endre filen AndroidManifest.xml for å overstyre standardhåndteringen av skjermretning.

AndroidMainfest.xml

 "http://schemas.android.com/apk/res/android" package = "com.authorwjf.gamedevtut02" android: versionCode = "1" android: versionName = "1.0" > 

android: minSdkVersion = "8"

android: targetSdkVersion = "15" />

android: icon = "@ drawable / ic_launcher"

android: label = "@ string / app_name"

android: theme = "@ style / AppTheme" >

android: screenOrientation = "portrett"

android: configChanges = "orientering | tastatur skjult "

android: name = ".Main"

android: label = "@ string / title_activity_main" >

"android.intent.action.MAIN" />

"android.intent.category.LAUNCHER" />

3. Selv om det ikke er gjort noen endringer i /res/layout/main.xml-definisjonen siden del 1, er det igjen for fullstendighetens skyld.

main.xml

 "http://schemas.android.com/apk/res/android" android: layout_width = "fill_parent" android: layout_height = "fill_parent" android: orientering = "vertikal" > 

android: layout_width = "wrap_content"

android: layout_height = "wrap_content"

android: layout_gravity = "topp | sentrum"

android: text = "ABC's of Android Game Dev" />

android: id = "@ + id / the_button"

android: layout_width = "wrap_content"

android: layout_height = "wrap_content"

android: layout_gravity = "sentrum"

android: gravitasjon = "sentrum"

android: enabled = "falsk"

android: text = "Reset" />

android: layout_width = "wrap_content"

android: layout_height = "wrap_content"

android: layout_gravity = "sentrum"

android: text = "Sprite Speed ​​(?, ?)"

android: id = "@ + id / the_label" />

android: layout_width = "wrap_content"

android: layout_height = "wrap_content"

android: layout_gravity = "sentrum"

android: text = "Last Collision XY (?, ?)"

android: id = "@ + id / the_other_label" />

android: layout_width = "fill_parent"

android: layout_height = "fill_parent"

android: layout_margin = "20dip"

android: id = "@ + id / the_canvas" />

4. Nå må vi lage en / res / drawable mappe. Her vil vi plassere bildene: ufo.png og asteroid.png. Mens jeg bruker en enkelt tegnbar mappe i denne demokoden, vil du, hvis du slipper et spill på markedet, lage flere versjoner av disse bildene i forskjellige oppløsninger og legge dem i ldpi, mdpi, hdpi og xhdpi som passende. Hvis dette er første gang du arbeider med Android-ressurser, anbefaler jeg på det sterkeste å lese Googles dokumentasjon om støtte for flere skjermer.

5. La oss se på endringene vi gjør i /src/GameBoard.Java-klassen. Husk fra første del, denne klassen eksisterer i sin egen pakke: com.authorwjf.drawing.

Først må vi legge til private variabler for å holde rede på sprite-posisjonene våre. Deretter vil vi eksponere disse egenskapene for kontrolleren (Main.java) ved å bruke en serie getters og setters. Deretter vil vi i konstruktøren vår laste inn bitmappbildene som representerer vår sprite. Til slutt, i trekksløyfen, vil vi male spritene på lerretet. Spritene må tegnes sist slik at bakgrunnen ikke skjuler dem.

Nedenfor er hele kildelisten for GameBoard-klassen, med koden spesifikk for denne opplæringen uthevet.

GameBoard.java

 pakke com.authorwjf.drawing; importer java.util.ArrayList; import java.util.List; importer java.util.Random; import com.authorwjf.gamedevtut02.R; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; offentlig klasse GameBoard utvider View { private Paint p; privat liste starField = null ; privat int starAlpha = 80; privat int starFade = 2; 

// Legg til private variabler for å følge med på sprittposisjon og størrelse

private Rect sprite1Bounds = new Rect (0, 0, 0, 0); private Rect sprite2Bounds = new Rect (0, 0, 0, 0); private Point sprite1; private Point sprite2;

// Bitmapp som inneholder de faktiske sprite-bildene

privat Bitmap bm1 = null ; privat Bitmap bm2 = null ; privat statisk endelig int NUM_OF_STARS = 25;

// La kontrolleren vår få og stille inn sprite-stillingene

// sprite 1 setter

synkronisert offentlig tomrom settSprite1 (punkt p) {

sprite1 = p;

}

// sprite 1 getter

synkronisert offentlig Point getSprite1 () { return sprite1;

}

// sprite 2 setter

synkronisert offentlig tomrom setSprite2 (punkt p) {

sprite2 = p;

}

// sprite 2 getter

synkronisert offentlig Point getSprite2 () { return sprite2;

}

synkronisert offentlig tomrom resetStarField () {starField = null ;

}

// utsett sprite grenser for kontrolleren

synkronisert offentlig int getSprite1Width () { return sprite1Bounds.width ();

}

synkronisert offentlig int getSprite1Height () { return sprite1Bounds.height ();

}

synkronisert offentlig int getSprite2Width () { return sprite2Bounds.width ();

}

synkronisert offentlig int getSprite2Height () { return sprite2Bounds.height ();

}

public GameBoard (Context context, AttributeSet aSet) { super (context, aSet); p = ny maling ();

// last inn bitmappene våre og sett grensene for kontrolleren

sprite1 = nytt punkt (-1, -1); sprite2 = nytt punkt (-1, -1); p = ny maling ();

bm1 = BitmapFactory. decodeResource (getResources (), R.drawable. asteroid );

bm2 = BitmapFactory. decodeResource (getResources (), R.drawable. ufo );

sprite1Bounds = new Rect (0, 0, bm1.getWidth (), bm1.getHeight ()); sprite2Bounds = new Rect (0, 0, bm2.getWidth (), bm2.getHeight ());

}

private void initializeStars ( int maxX, int maxY) {starField = new ArrayList (); for ( int i = 0; i < NUM_OF_STARS ; i ++) {Tilfeldig r = ny tilfeldig (); int x = r.nextInt (maxX-5 + 1) +5; int y = r.nextInt (maxY-5 + 1) +5; starField.add ( nytt punkt (x, y));

}

}

@Overstyring

synkronisert offentlig tomrom onDraw (Canvas canvas) {

p.setColor (farge. SVART );

p.setAlpha (255);

p.setStrokeWidth (1);

canvas.drawRect (0, 0, getWidth (), getHeight (), p);

if (starField == null ) {

initialisereStars (canvas.getWidth (), canvas.getHeight ());

}

p.setColor (farge. CYAN );

p.setAlpha (starAlpha + = starFade);

if (starAlpha> = 252 || starAlpha <= 80) starFade = starFade * -1;

p.setStrokeWidth (5);

for ( int i = 0; i < NUM_OF_STARS ; i ++) {

canvas.drawPoint (starField.get (i) .x, starField.get (i) .y, p);

}

// Nå tegner vi spritene våre. Elementer tegnet i denne funksjonen er stablet.

// Elementene som er tegnet øverst på løkken er på bunnen av z-ordren.

// Derfor tegner vi settet vårt, deretter skuespillerne våre, og til slutt enhver fx. if (sprite1.x> = 0) {canvas.drawBitmap (bm1, sprite1.x, sprite1.y, null );

}

if (sprite2.x> = 0) {canvas.drawBitmap (bm2, sprite2.x, sprite2.y, null );

}

}

}

6. Endre Main.java for å tilordne start x- og y-koordinater til sprites. Metoden getRandomPoint () returnerer en tilfeldig x og y som faller innenfor rammen av lerretet. Vi bruker deretter en stundsløyfe for å sikre at den innledende plasseringen av spritene ikke overlapper hverandre.

Main.java

 pakke com.authorwjf.gamedevtut02; importer java.util.Random; import com.authorwjf.drawing.GameBoard; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.app.Aktivitet; import android.graphics.Point; offentlig klasse Hoved utvider Aktivitetsredskaper OnClickListener { private Handler frame = new Handler (); 

// Del rammen med 1000 for å beregne hvor mange ganger i sekundet skjermen vil oppdatere.

privat statisk endelig int FRAME_RATE = 20; // 50 bilder per sekund

@Overstyring

public void onCreate (Bundle savedInstanceState) { super .onCreate (savedInstanceState);

setContentView (R.layout. main );

Handler h = new Handler (); ((Knapp) findViewById (R.id. The_button )). SetOnClickListener ( dette );

// Vi kan ikke initialisere grafikken umiddelbart fordi layout manager

// trenger å løpe først, og ring tilbake på et sekund. h.postDelayed ( new Runnable () {

@Overstyring

public void run () {

initGfx ();

}

}, 1000);

}

private Point getRandomPoint () {Tilfeldig r = ny Tilfeldig (); int minX = 0; int maxX = findViewById (R.id. the_canvas ) .getWidth () - ((GameBoard) findViewById (R.id. the_canvas )). getSprite1Width (); int x = 0; int minY = 0; int maxY = findViewById (R.id. the_canvas ) .getHeight () - ((GameBoard) findViewById (R.id. the_canvas )). getSprite1Height (); int y = 0;

x = r.nextInt (maxX-minX + 1) + minX;

y = r.nextInt (maxY-minY + 1) + minY;

returnere nytt punkt (x, y);

}

synkronisert offentlig tomrom initGfx () {

((GameBoard) findViewById (R.id. The_canvas )). ResetStarField ();

// Velg to tilfeldige punkter for vår første sprite-plassering.

// Løkken er bare for å sikre at vi ikke plukker ved et uhell

// to punkter som overlapper hverandre.

Punkt p1, p2;

gjør {

p1 = getRandomPoint ();

p2 = getRandomPoint ();

} while (Math. abs (p1.x - p2.x) <

((GameBoard) findViewById (R.id. The_canvas )). GetSprite1Width ());

((GameBoard) findViewById (R.id. The_canvas )). SetSprite1 (p1);

((GameBoard) findViewById (R.id. The_canvas )). SetSprite2 (p2);

((Knapp) findViewById (R.id. The_button )). SetEnabled ( true );

frame.removeCallbacks (frameUpdate);

frame.postDelayed (frameUpdate, FRAME_RATE );

}

@Overstyring

synkronisert offentlig tomrom onClick (View v) {

initGfx ();

}

private Runnable frameUpdate = new Runnable () {

@Overstyring

synkronisert offentlig tomgangskjøring () {

frame.removeCallbacks (frameUpdate);

// gjøre eventuelle oppdateringer til skjermobjekter her

// påkalle deretter trekningen ved å ugyldige lerretet

((GameBoard) findViewById (R.id. The_canvas )). Ugyldig ();

frame.postDelayed (frameUpdate, FRAME_RATE );

}

};

}

Spillkoden vår har nådd et godt stoppunkt. Du kan laste den inn på enheten din eller emulatoren. Denne gangen når du trykker på tilbakestillingsknappen, vil skuespillerne våre ta plassene sine.

Følg med på del tre av denne opplæringen, der regissøren vil rope "action", og vi vil begynne å animere spillobjektene.

© Copyright 2021 | pepebotifarra.com