- Die Vorstellung
- Ein Game Project erstellen
- Das Image und den Ton vorbereiten
- Den Modul Full-Screen (Version:1) einstellen
- Den Charakter auf Game (Version:2) anzeigen
- Die Interaktion mit dem Spieler (Version: 3)
- Der Spiel mit mehren Charakter (Version: 4)
- Die Effekte im Spiel (Version: 5)
- Die Soundeffekte im Spiel (Version: Release)
Die Anleitung zum Android 2D Game für den Anfänger
1. Die Vorstellung
Das Dokument wird nach der Quelle ... geschrieben:
Android Studio 3.6.1
Das Ziel des Dokument ist die Hilfe, einige einfachen Technik in der Programmierung von Game 2D Android kennenzulernen. Es umfasst:
- SuffaceView benutzen
- Aufs Canvas malen
- Die Bewegung der Gamefiguren.
- Die Interaktion mit der Geste von dem Spieler
Im Dokument führe ich Sie schrittweise bei der Programmierung, deshalb sollen Sie vom oben nach unten lesen und praktizieren. Wir werden jede Version des Spiel zur letzten Version schreiben (Release).
2. Ein Game Project erstellen
In Android Studio erstellen Sie ein neues Projekt:
- Name: Android2DGame
- Package name: org.o7planning.android2dgame
OK, Ihr Project wird erstellt
Zunächst sollen Sie ein Activity erstellen. In Android Studio wählen Sie:
- File > New > Activity > Empty Activity
- Activity Name: MainActivity
Beachten Sie, dass Sie gerade ein 2D-Game auf Android erstellen. So wird die Interface des Games selbst von Ihnen gemacht. Deshalb brauchen Sie die File wie activity_main.xml.nicht
3. Das Image und den Ton vorbereiten
Sie brauchen einige Foto-File
chibi1.png | chibi2.png |
explosion.png |
Das Audio für die Explosion
Das Audio für den Hintergrund
Klicken Sie mit der rechten Maustaste auf den Ordner "res" vom Projekt und wählen Sie:
- New > Folder > Raw Resource Folder
Kopieren Sie diese Fotos in dem Ordnen drawable des Projekt. Erstellen Sie einen Ordnen raw,und kopieren Sie die File explosion.wav & background.mp3 in diesem Ordnen
4. Den Modul Full-Screen (Version:1) einstellen
Mit dem Game brauchen Sie das Hintergrundbild setzen und es ist wichtig, das Modus Fullscreen zu setzen
Die Klasse MainActivity von Ihnen mussen aus der Klasse Activity.verlängern (extend)
MainActivity.java (Version: 1)
package org.o7planning.android2dgame;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set fullscreen
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Set No Title
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
}
}
Zum nächsten setzen Sie das Bildschirm in dem Modus von Landscape. Sie sollen in AndroidManifest.xml.setzen
** AndroidManifest.xml **
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.o7planning.android2dgame">
<application
android:screenOrientation="landscape"
... >
...
</application>
</manifest>
Führen Sie das Demo der Applikation durch
Notiz: Auf Windows können Sie das Emulatorgerät durch den Befehl Ctrl + F11.drehen
5. Den Charakter auf Game (Version:2) anzeigen
Zum nächsten sollen Sie die Kode schreiben um die Figure des Games auf dem Bildschirm anzuzeigen und sie von links nach rechts mit einer Geschwindigkeit zu bewegen
Eine Figur im Games hat nur eine Foto-File. Aber die Foto-File wird in vielen Bezeichnung der unterschiedlichen Aktionen der Figur geteilt
Durch die Kodierung können Sie einen Bildbereich auf dem Projekt Canvas des Games bei der Koordinaten von x,y. Benutzen Sie die Schleife for zum ständigen Malen auf Canvas , damit Sie die Bewegung der Figur machen
Bei der Game-Programmierung sollen Sie die Richtung der Bewegung der Figur im Game, die Geschwindigkeit der Figur nachdenken
Erstellen Sie die Klasse GameObject, und die Objekte des Games verlängern aus diese Klasse
GameObject.java (Version: Release)
package org.o7planning.android2dgame;
import android.graphics.Bitmap;
public abstract class GameObject {
protected Bitmap image;
protected final int rowCount;
protected final int colCount;
protected final int WIDTH;
protected final int HEIGHT;
protected final int width;
protected final int height;
protected int x;
protected int y;
public GameObject(Bitmap image, int rowCount, int colCount, int x, int y) {
this.image = image;
this.rowCount= rowCount;
this.colCount= colCount;
this.x= x;
this.y= y;
this.WIDTH = image.getWidth();
this.HEIGHT = image.getHeight();
this.width = this.WIDTH/ colCount;
this.height= this.HEIGHT/ rowCount;
}
protected Bitmap createSubImageAt(int row, int col) {
// createBitmap(bitmap, x, y, width, height).
Bitmap subImage = Bitmap.createBitmap(image, col* width, row* height ,width,height);
return subImage;
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
}
Die Klasse ChibiCharactor simuliert eine Figur im Game.
ChibiCharacter.java (Version: 2)
package org.o7planning.android2dgame;
import android.graphics.Bitmap;
import android.graphics.Canvas;
public class ChibiCharacter extends GameObject {
private static final int ROW_TOP_TO_BOTTOM = 0;
private static final int ROW_RIGHT_TO_LEFT = 1;
private static final int ROW_LEFT_TO_RIGHT = 2;
private static final int ROW_BOTTOM_TO_TOP = 3;
// Row index of Image are being used.
private int rowUsing = ROW_LEFT_TO_RIGHT;
private int colUsing;
private Bitmap[] leftToRights;
private Bitmap[] rightToLefts;
private Bitmap[] topToBottoms;
private Bitmap[] bottomToTops;
// Velocity of game character (pixel/millisecond)
public static final float VELOCITY = 0.1f;
private int movingVectorX = 10;
private int movingVectorY = 5;
private long lastDrawNanoTime =-1;
private GameSurface gameSurface;
public ChibiCharacter(GameSurface gameSurface, Bitmap image, int x, int y) {
super(image, 4, 3, x, y);
this.gameSurface= gameSurface;
this.topToBottoms = new Bitmap[colCount]; // 3
this.rightToLefts = new Bitmap[colCount]; // 3
this.leftToRights = new Bitmap[colCount]; // 3
this.bottomToTops = new Bitmap[colCount]; // 3
for(int col = 0; col< this.colCount; col++ ) {
this.topToBottoms[col] = this.createSubImageAt(ROW_TOP_TO_BOTTOM, col);
this.rightToLefts[col] = this.createSubImageAt(ROW_RIGHT_TO_LEFT, col);
this.leftToRights[col] = this.createSubImageAt(ROW_LEFT_TO_RIGHT, col);
this.bottomToTops[col] = this.createSubImageAt(ROW_BOTTOM_TO_TOP, col);
}
}
public Bitmap[] getMoveBitmaps() {
switch (rowUsing) {
case ROW_BOTTOM_TO_TOP:
return this.bottomToTops;
case ROW_LEFT_TO_RIGHT:
return this.leftToRights;
case ROW_RIGHT_TO_LEFT:
return this.rightToLefts;
case ROW_TOP_TO_BOTTOM:
return this.topToBottoms;
default:
return null;
}
}
public Bitmap getCurrentMoveBitmap() {
Bitmap[] bitmaps = this.getMoveBitmaps();
return bitmaps[this.colUsing];
}
public void update() {
this.colUsing++;
if(colUsing >= this.colCount) {
this.colUsing =0;
}
// Current time in nanoseconds
long now = System.nanoTime();
// Never once did draw.
if(lastDrawNanoTime==-1) {
lastDrawNanoTime= now;
}
// Change nanoseconds to milliseconds (1 nanosecond = 1000000 milliseconds).
int deltaTime = (int) ((now - lastDrawNanoTime)/ 1000000 );
// Distance moves
float distance = VELOCITY * deltaTime;
double movingVectorLength = Math.sqrt(movingVectorX* movingVectorX + movingVectorY*movingVectorY);
// Calculate the new position of the game character.
this.x = x + (int)(distance* movingVectorX / movingVectorLength);
this.y = y + (int)(distance* movingVectorY / movingVectorLength);
// When the game's character touches the edge of the screen, then change direction
if(this.x < 0 ) {
this.x = 0;
this.movingVectorX = - this.movingVectorX;
} else if(this.x > this.gameSurface.getWidth() -width) {
this.x= this.gameSurface.getWidth()-width;
this.movingVectorX = - this.movingVectorX;
}
if(this.y < 0 ) {
this.y = 0;
this.movingVectorY = - this.movingVectorY;
} else if(this.y > this.gameSurface.getHeight()- height) {
this.y= this.gameSurface.getHeight()- height;
this.movingVectorY = - this.movingVectorY ;
}
// rowUsing
if( movingVectorX > 0 ) {
if(movingVectorY > 0 && Math.abs(movingVectorX) < Math.abs(movingVectorY)) {
this.rowUsing = ROW_TOP_TO_BOTTOM;
}else if(movingVectorY < 0 && Math.abs(movingVectorX) < Math.abs(movingVectorY)) {
this.rowUsing = ROW_BOTTOM_TO_TOP;
}else {
this.rowUsing = ROW_LEFT_TO_RIGHT;
}
} else {
if(movingVectorY > 0 && Math.abs(movingVectorX) < Math.abs(movingVectorY)) {
this.rowUsing = ROW_TOP_TO_BOTTOM;
}else if(movingVectorY < 0 && Math.abs(movingVectorX) < Math.abs(movingVectorY)) {
this.rowUsing = ROW_BOTTOM_TO_TOP;
}else {
this.rowUsing = ROW_RIGHT_TO_LEFT;
}
}
}
public void draw(Canvas canvas) {
Bitmap bitmap = this.getCurrentMoveBitmap();
canvas.drawBitmap(bitmap,x, y, null);
// Last draw time.
this.lastDrawNanoTime= System.nanoTime();
}
public void setMovingVector(int movingVectorX, int movingVectorY) {
this.movingVectorX= movingVectorX;
this.movingVectorY = movingVectorY;
}
}
GameThread ist ein Thread zur Steuerung der Aktuallisierung der Gamesinterface
GameThread.java (Version: Release)
package org.o7planning.android2dgame;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class GameThread extends Thread {
private boolean running;
private GameSurface gameSurface;
private SurfaceHolder surfaceHolder;
public GameThread(GameSurface gameSurface, SurfaceHolder surfaceHolder) {
this.gameSurface= gameSurface;
this.surfaceHolder= surfaceHolder;
}
@Override
public void run() {
long startTime = System.nanoTime();
while(running) {
Canvas canvas= null;
try {
// Get Canvas from Holder and lock it.
canvas = this.surfaceHolder.lockCanvas();
// Synchronized
synchronized (canvas) {
this.gameSurface.update();
this.gameSurface.draw(canvas);
}
}catch(Exception e) {
// Do nothing.
} finally {
if(canvas!= null) {
// Unlock Canvas.
this.surfaceHolder.unlockCanvasAndPost(canvas);
}
}
long now = System.nanoTime() ;
// Interval to redraw game
// (Change nanoseconds to milliseconds)
long waitTime = (now - startTime)/1000000;
if(waitTime < 10) {
waitTime= 10; // Millisecond.
}
System.out.print(" Wait Time="+ waitTime);
try {
// Sleep.
this.sleep(waitTime);
} catch(InterruptedException e) {
}
startTime = System.nanoTime();
System.out.print(".");
}
}
public void setRunning(boolean running) {
this.running= running;
}
}
Die Klasse GameSurface bezeichnet die ganze Oberfläche des Game, Die Klasse wird aus SurfaceView erweitert, SurfaceView enthaltet ein Objekt Canvas,. Die Objekte im Game werden auf Canvas.gemalt
GameSurface.java (Version: 2)
package org.o7planning.android2dgame;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameSurface extends SurfaceView implements SurfaceHolder.Callback {
private GameThread gameThread;
private ChibiCharacter chibi1;
public GameSurface(Context context) {
super(context);
// Make Game Surface focusable so it can handle events. .
this.setFocusable(true);
// Sét callback.
this.getHolder().addCallback(this);
}
public void update() {
this.chibi1.update();
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
this.chibi1.draw(canvas);
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceCreated(SurfaceHolder holder) {
Bitmap chibiBitmap1 = BitmapFactory.decodeResource(this.getResources(),R.drawable.chibi1);
this.chibi1 = new ChibiCharacter(this,chibiBitmap1,100,50);
this.gameThread = new GameThread(this,holder);
this.gameThread.setRunning(true);
this.gameThread.start();
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry= true;
while(retry) {
try {
this.gameThread.setRunning(false);
// Parent thread must wait until the end of GameThread.
this.gameThread.join();
}catch(InterruptedException e) {
e.printStackTrace();
}
retry= true;
}
}
}
MainActivity.java (Version: Release)
package org.o7planning.android2dgame;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set fullscreen
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Set No Title
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.setContentView(new GameSurface(this));
}
}
OK, die 2. Version ist fertig. Sie können das Game starten
6. Die Interaktion mit dem Spieler (Version: 3)
Zunächst behandeln Sie das Ereignis wenn der Benutzer auf dem Bildchirm berührt. Die Figur des Game wird nach der berührten Richtung bewegen. Sie sollen das Ereignis auf die Klasse GameSurface.behandeln
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int x= (int)event.getX();
int y = (int)event.getY();
int movingVectorX =x- this.chibi1.getX() ;
int movingVectorY =y- this.chibi1.getY() ;
this.chibi1.setMovingVector(movingVectorX,movingVectorY);
return true;
}
return false;
}
Die volle Kode sehen
GameSurface.java (Version: 3)
package org.o7planning.android2dgame;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameSurface extends SurfaceView implements SurfaceHolder.Callback {
private GameThread gameThread;
private ChibiCharacter chibi1;
public GameSurface(Context context) {
super(context);
// Make Game Surface focusable so it can handle events.
this.setFocusable(true);
// Set callback.
this.getHolder().addCallback(this);
}
public void update() {
this.chibi1.update();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int x= (int)event.getX();
int y = (int)event.getY();
int movingVectorX =x- this.chibi1.getX() ;
int movingVectorY =y- this.chibi1.getY() ;
this.chibi1.setMovingVector(movingVectorX,movingVectorY);
return true;
}
return false;
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
this.chibi1.draw(canvas);
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceCreated(SurfaceHolder holder) {
Bitmap chibiBitmap1 = BitmapFactory.decodeResource(this.getResources(),R.drawable.chibi1);
this.chibi1 = new ChibiCharacter(this,chibiBitmap1,100,50);
this.gameThread = new GameThread(this,holder);
this.gameThread.setRunning(true);
this.gameThread.start();
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry= true;
while(retry) {
try {
this.gameThread.setRunning(false);
// Parent thread must wait until the end of GameThread.
this.gameThread.join();
}catch(InterruptedException e) {
e.printStackTrace();
}
retry= true;
}
}
}
Das Game wieder durchführen
7. Der Spiel mit mehren Charakter (Version: 4)
Sie können die anderen Figuren im Game machen. Hier mache ich eine 2. Figur. und ändere die Kode der Klasse GameSurface:
GameSurface.java (Version: 4)
package org.o7planning.android2dgame;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.ArrayList;
import java.util.List;
public class GameSurface extends SurfaceView implements SurfaceHolder.Callback {
private GameThread gameThread;
private final List<ChibiCharacter> chibiList = new ArrayList<ChibiCharacter>();
public GameSurface(Context context) {
super(context);
// Make Game Surface focusable so it can handle events.
this.setFocusable(true);
// Set callback.
this.getHolder().addCallback(this);
}
public void update() {
for(ChibiCharacter chibi: chibiList) {
chibi.update();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int x= (int)event.getX();
int y = (int)event.getY();
for(ChibiCharacter chibi: chibiList) {
int movingVectorX =x- chibi.getX() ;
int movingVectorY =y- chibi.getY() ;
chibi.setMovingVector(movingVectorX, movingVectorY);
}
return true;
}
return false;
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
for(ChibiCharacter chibi: chibiList) {
chibi.draw(canvas);
}
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceCreated(SurfaceHolder holder) {
Bitmap chibiBitmap1 = BitmapFactory.decodeResource(this.getResources(),R.drawable.chibi1);
ChibiCharacter chibi1 = new ChibiCharacter(this,chibiBitmap1,100,50);
Bitmap chibiBitmap2 = BitmapFactory.decodeResource(this.getResources(),R.drawable.chibi2);
ChibiCharacter chibi2 = new ChibiCharacter(this,chibiBitmap2,300,150);
this.chibiList.add(chibi1);
this.chibiList.add(chibi2);
this.gameThread = new GameThread(this,holder);
this.gameThread.setRunning(true);
this.gameThread.start();
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry= true;
while(retry) {
try {
this.gameThread.setRunning(false);
// Parent thread must wait until the end of GameThread.
this.gameThread.join();
}catch(InterruptedException e) {
e.printStackTrace();
}
retry= true;
}
}
}
Das Game wieder durchführen
8. Die Effekte im Spiel (Version: 5)
Manchmal sollen Sie einige Effekte des Games behandeln, zum Beispiel: Bei der Steuerung eines Flug ist der Flug auf dem Boden gefallen und sendet er einen Explosionton aus. So ist die Explosion ein Effekt. In diesem Teil simuliere ich dass, wenn Sie auf die Figur Chibi klicken, wird die Explosion ausgesendet
Die Klasse Explosion simuliert eine Explosion wenn Sie auf die Figur Chibi klicken, wird sie dann aus dem Game entfernt und ein Objekt Explosion wird in die Position, wo die Figur Chibi entfernt wird, hingefügt
Explosion.java (Version: 5)
package org.o7planning.android2dgame;
import android.graphics.Bitmap;
import android.graphics.Canvas;
public class Explosion extends GameObject {
private int rowIndex = 0 ;
private int colIndex = -1 ;
private boolean finish= false;
private GameSurface gameSurface;
public Explosion(GameSurface GameSurface, Bitmap image, int x, int y) {
super(image, 5, 5, x, y);
this.gameSurface= GameSurface;
}
public void update() {
this.colIndex++;
if(this.colIndex >= this.colCount) {
this.colIndex =0;
this.rowIndex++;
if(this.rowIndex>= this.rowCount) {
this.finish= true;
}
}
}
public void draw(Canvas canvas) {
if(!finish) {
Bitmap bitmap= this.createSubImageAt(rowIndex,colIndex);
canvas.drawBitmap(bitmap, this.x, this.y,null);
}
}
public boolean isFinish() {
return finish;
}
}
Sie brauchen die Kodierung der Klasse GameSurface:zu ändern
GameSurface.java (Version: 5)
package org.o7planning.android2dgame;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class GameSurface extends SurfaceView implements SurfaceHolder.Callback {
private GameThread gameThread;
private final List<ChibiCharacter> chibiList = new ArrayList<ChibiCharacter>();
private final List<Explosion> explosionList = new ArrayList<Explosion>();
public GameSurface(Context context) {
super(context);
// Make Game Surface focusable so it can handle events.
this.setFocusable(true);
// Sét callback.
this.getHolder().addCallback(this);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int x= (int)event.getX();
int y = (int)event.getY();
Iterator<ChibiCharacter> iterator= this.chibiList.iterator();
while(iterator.hasNext()) {
ChibiCharacter chibi = iterator.next();
if( chibi.getX() < x && x < chibi.getX() + chibi.getWidth()
&& chibi.getY() < y && y < chibi.getY()+ chibi.getHeight()) {
// Remove the current element from the iterator and the list.
iterator.remove();
// Create Explosion object.
Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(),R.drawable.explosion);
Explosion explosion = new Explosion(this, bitmap,chibi.getX(),chibi.getY());
this.explosionList.add(explosion);
}
}
for(ChibiCharacter chibi: chibiList) {
int movingVectorX =x- chibi.getX() ;
int movingVectorY =y- chibi.getY() ;
chibi.setMovingVector(movingVectorX, movingVectorY);
}
return true;
}
return false;
}
public void update() {
for(ChibiCharacter chibi: chibiList) {
chibi.update();
}
for(Explosion explosion: this.explosionList) {
explosion.update();
}
Iterator<Explosion> iterator= this.explosionList.iterator();
while(iterator.hasNext()) {
Explosion explosion = iterator.next();
if(explosion.isFinish()) {
// If explosion finish, Remove the current element from the iterator & list.
iterator.remove();
continue;
}
}
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
for(ChibiCharacter chibi: chibiList) {
chibi.draw(canvas);
}
for(Explosion explosion: this.explosionList) {
explosion.draw(canvas);
}
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceCreated(SurfaceHolder holder) {
Bitmap chibiBitmap1 = BitmapFactory.decodeResource(this.getResources(),R.drawable.chibi1);
ChibiCharacter chibi1 = new ChibiCharacter(this,chibiBitmap1,100,50);
Bitmap chibiBitmap2 = BitmapFactory.decodeResource(this.getResources(),R.drawable.chibi2);
ChibiCharacter chibi2 = new ChibiCharacter(this,chibiBitmap2,300,150);
this.chibiList.add(chibi1);
this.chibiList.add(chibi2);
this.gameThread = new GameThread(this,holder);
this.gameThread.setRunning(true);
this.gameThread.start();
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry= true;
while(retry) {
try {
this.gameThread.setRunning(false);
// Parent thread must wait until the end of GameThread.
this.gameThread.join();
}catch(InterruptedException e) {
e.printStackTrace();
}
retry= true;
}
}
}
Starten Sie Ihr Game wieder
9. Die Soundeffekte im Spiel (Version: Release)
Zunächst sollen Sie die Audion-Effekte im Game einfügen- z.B das Hintergrundaudio des Games, das Explosionsaudio wenn die Figur Chibi zerstört wird
Explosion.java (Version: Release)
package org.o7planning.android2dgame;
import android.graphics.Bitmap;
import android.graphics.Canvas;
public class Explosion extends GameObject {
private int rowIndex = 0 ;
private int colIndex = -1 ;
private boolean finish= false;
private GameSurface gameSurface;
public Explosion(GameSurface GameSurface, Bitmap image, int x, int y) {
super(image, 5, 5, x, y);
this.gameSurface= GameSurface;
}
public void update() {
this.colIndex++;
// Play sound explosion.wav.
if(this.colIndex==0 && this.rowIndex==0) {
this.gameSurface.playSoundExplosion();
}
if(this.colIndex >= this.colCount) {
this.colIndex =0;
this.rowIndex++;
if(this.rowIndex>= this.rowCount) {
this.finish= true;
}
}
}
public void draw(Canvas canvas) {
if(!finish) {
Bitmap bitmap= this.createSubImageAt(rowIndex,colIndex);
canvas.drawBitmap(bitmap, this.x, this.y,null);
}
}
public boolean isFinish() {
return finish;
}
}
GameSurface.java (Version: Release)
package org.o7planning.android2dgame;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class GameSurface extends SurfaceView implements SurfaceHolder.Callback {
private GameThread gameThread;
private final List<ChibiCharacter> chibiList = new ArrayList<ChibiCharacter>();
private final List<Explosion> explosionList = new ArrayList<Explosion>();
private static final int MAX_STREAMS=100;
private int soundIdExplosion;
private int soundIdBackground;
private boolean soundPoolLoaded;
private SoundPool soundPool;
public GameSurface(Context context) {
super(context);
// Make Game Surface focusable so it can handle events.
this.setFocusable(true);
// Sét callback.
this.getHolder().addCallback(this);
this.initSoundPool();
}
private void initSoundPool() {
// With Android API >= 21.
if (Build.VERSION.SDK_INT >= 21 ) {
AudioAttributes audioAttrib = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
SoundPool.Builder builder= new SoundPool.Builder();
builder.setAudioAttributes(audioAttrib).setMaxStreams(MAX_STREAMS);
this.soundPool = builder.build();
}
// With Android API < 21
else {
// SoundPool(int maxStreams, int streamType, int srcQuality)
this.soundPool = new SoundPool(MAX_STREAMS, AudioManager.STREAM_MUSIC, 0);
}
// When SoundPool load complete.
this.soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
soundPoolLoaded = true;
// Playing background sound.
playSoundBackground();
}
});
// Load the sound background.mp3 into SoundPool
this.soundIdBackground= this.soundPool.load(this.getContext(), R.raw.background,1);
// Load the sound explosion.wav into SoundPool
this.soundIdExplosion = this.soundPool.load(this.getContext(), R.raw.explosion,1);
}
public void playSoundExplosion() {
if(this.soundPoolLoaded) {
float leftVolumn = 0.8f;
float rightVolumn = 0.8f;
// Play sound explosion.wav
int streamId = this.soundPool.play(this.soundIdExplosion,leftVolumn, rightVolumn, 1, 0, 1f);
}
}
public void playSoundBackground() {
if(this.soundPoolLoaded) {
float leftVolumn = 0.8f;
float rightVolumn = 0.8f;
// Play sound background.mp3
int streamId = this.soundPool.play(this.soundIdBackground,leftVolumn, rightVolumn, 1, -1, 1f);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int x= (int)event.getX();
int y = (int)event.getY();
Iterator<ChibiCharacter> iterator= this.chibiList.iterator();
while(iterator.hasNext()) {
ChibiCharacter chibi = iterator.next();
if( chibi.getX() < x && x < chibi.getX() + chibi.getWidth()
&& chibi.getY() < y && y < chibi.getY()+ chibi.getHeight()) {
// Remove the current element from the iterator and the list.
iterator.remove();
// Create Explosion object.
Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(),R.drawable.explosion);
Explosion explosion = new Explosion(this, bitmap,chibi.getX(),chibi.getY());
this.explosionList.add(explosion);
}
}
for(ChibiCharacter chibi: chibiList) {
int movingVectorX =x- chibi.getX() ;
int movingVectorY =y- chibi.getY() ;
chibi.setMovingVector(movingVectorX, movingVectorY);
}
return true;
}
return false;
}
public void update() {
for(ChibiCharacter chibi: chibiList) {
chibi.update();
}
for(Explosion explosion: this.explosionList) {
explosion.update();
}
Iterator<Explosion> iterator= this.explosionList.iterator();
while(iterator.hasNext()) {
Explosion explosion = iterator.next();
if(explosion.isFinish()) {
// If explosion finish, Remove the current element from the iterator & list.
iterator.remove();
continue;
}
}
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
for(ChibiCharacter chibi: chibiList) {
chibi.draw(canvas);
}
for(Explosion explosion: this.explosionList) {
explosion.draw(canvas);
}
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceCreated(SurfaceHolder holder) {
Bitmap chibiBitmap1 = BitmapFactory.decodeResource(this.getResources(),R.drawable.chibi1);
ChibiCharacter chibi1 = new ChibiCharacter(this,chibiBitmap1,100,50);
Bitmap chibiBitmap2 = BitmapFactory.decodeResource(this.getResources(),R.drawable.chibi2);
ChibiCharacter chibi2 = new ChibiCharacter(this,chibiBitmap2,300,150);
this.chibiList.add(chibi1);
this.chibiList.add(chibi2);
this.gameThread = new GameThread(this,holder);
this.gameThread.setRunning(true);
this.gameThread.start();
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
// Implements method of SurfaceHolder.Callback
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry= true;
while(retry) {
try {
this.gameThread.setRunning(false);
// Parent thread must wait until the end of GameThread.
this.gameThread.join();
}catch(InterruptedException e) {
e.printStackTrace();
}
retry= true;
}
}
}
OK, Jetzt können Sie das Game wieder spielen und das Audio-Effekte des Games hören
Beachten Sie: Sie sollen das Dokument über die Audio-Effekte bei .... lesen
Anleitungen Android
- Konfigurieren Sie Android Emulator in Android Studio
- Die Anleitung zu Android ToggleButton
- Erstellen Sie einen einfachen File Finder Dialog in Android
- Die Anleitung zu Android TimePickerDialog
- Die Anleitung zu Android DatePickerDialog
- Was ist erforderlich, um mit Android zu beginnen?
- Installieren Sie Android Studio unter Windows
- Installieren Sie Intel® HAXM für Android Studio
- Die Anleitung zu Android AsyncTask
- Die Anleitung zu Android AsyncTaskLoader
- Die Anleitung zum Android für den Anfänger - Grundlegende Beispiele
- Woher weiß man die Telefonnummer von Android Emulator und ändere es
- Die Anleitung zu Android TextInputLayout
- Die Anleitung zu Android CardView
- Die Anleitung zu Android ViewPager2
- Holen Sie sich die Telefonnummer in Android mit TelephonyManager
- Die Anleitung zu Android Phone Calls
- Die Anleitung zu Android Wifi Scanning
- Die Anleitung zum Android 2D Game für den Anfänger
- Die Anleitung zu Android DialogFragment
- Die Anleitung zu Android CharacterPickerDialog
- Die Anleitung zum Android für den Anfänger - Hello Android
- Verwenden des Android Device File Explorer
- Aktivieren Sie USB Debugging auf einem Android-Gerät
- Die Anleitung zu Android UI Layouts
- Die Anleitung zu Android SMS
- Die Anleitung zu Android SQLite Database
- Die Anleitung zu Google Maps Android API
- Text zu Sprache in Android
- Die Anleitung zu Android Space
- Die Anleitung zu Android Toast
- Erstellen Sie einen benutzerdefinierten Android Toast
- Die Anleitung zu Android SnackBar
- Die Anleitung zu Android TextView
- Die Anleitung zu Android TextClock
- Die Anleitung zu Android EditText
- Die Anleitung zu Android TextWatcher
- Formatieren Sie die Kreditkartennummer mit Android TextWatcher
- Die Anleitung zu Android Clipboard
- Erstellen Sie einen einfachen File Chooser in Android
- Die Anleitung zu Android AutoCompleteTextView und MultiAutoCompleteTextView
- Die Anleitung zu Android ImageView
- Die Anleitung zu Android ImageSwitcher
- Die Anleitung zu Android ScrollView und HorizontalScrollView
- Die Anleitung zu Android WebView
- Die Anleitung zu Android SeekBar
- Die Anleitung zu Android Dialog
- Die Anleitung zu Android AlertDialog
- Die Anleitung zu Android RatingBar
- Die Anleitung zu Android ProgressBar
- Die Anleitung zu Android Spinner
- Die Anleitung zu Android Button
- Die Anleitung zu Android Switch
- Die Anleitung zu Android ImageButton
- Die Anleitung zu Android FloatingActionButton
- Die Anleitung zu Android CheckBox
- Die Anleitung zu Android RadioGroup und RadioButton
- Die Anleitung zu Android Chip und ChipGroup
- Verwenden Sie Image Asset und Icon Asset von Android Studio
- Richten Sie die SDCard für den Emulator ein
- ChipGroup und Chip Entry Beispiel
- Hinzufügen externer Bibliotheken zu Android Project in Android Studio
- Wie deaktiviere ich die Berechtigungen, die der Android-Anwendung bereits erteilt wurden?
- Wie entferne ich Anwendungen aus dem Android Emulator?
- Die Anleitung zu Android LinearLayout
- Die Anleitung zu Android TableLayout
- Die Anleitung zu Android FrameLayout
- Die Anleitung zu Android QuickContactBadge
- Die Anleitung zu Android StackView
- Die Anleitung zu Android Camera
- Die Anleitung zu Android MediaPlayer
- Die Anleitung zu Android VideoView
- Spielen Sie Sound-Effekte in Android mit SoundPool
- Die Anleitung zu Android Networking
- Die Anleitung zu Android JSON Parser
- Die Anleitung zu Android SharedPreferences
- Die Anleitung zu Android Internal Storage
- Die Anleitung zu Android External Storage
- Die Anleitung zu Android Intents
- Beispiel für eine explizite Android Intent, nennen Sie eine andere Intent
- Beispiel für implizite Android Intent, Öffnen Sie eine URL, senden Sie eine Email
- Die Anleitung zu Android Services
- Die Anleitung zu Android Notifications
- Die Anleitung zu Android DatePicker
- Die Anleitung zu Android TimePicker
- Die Anleitung zu Android Chronometer
- Die Anleitung zu Android OptionMenu
- Die Anleitung zu Android ContextMenu
- Die Anleitung zu Android PopupMenu
- Die Anleitung zu Android Fragment
- Die Anleitung zu Android ListView
- Android ListView mit Checkbox verwenden ArrayAdapter
- Die Anleitung zu Android GridView
Show More