Mục tiêu của tư liệu lí giải chúng ta có tác dụng quen thuộc với một vài kỹ thuật đơn giản và dễ dàng vào xây dựng trò chơi 2D Android. Bao gồm:
Sử dụng SuffaceViewVẽ trên CanvasChuyển rượu cồn của những nhân thiết bị game.Tương tác với động tác cử chỉ của bạn chơi
Trong tài liệu này tôi vẫn trả lời các bạn lập trình sẵn mỗi bước, chính vì vậy bạn phải hiểu và thực hành từ bỏ bên trên xuống bên dưới. Chúng ta đã viết từng phiên bạn dạng của trò nghịch từ là một cho đến phiên bản sau cuối (Release).

Bạn đang xem: Hướng dẫn lập trình android game 2d cho người mới bắt đầu


*

*

*

*

*

Crúc ý rằng nhiều người đang chế tạo ra một trò nghịch 2D bên trên Android, cũng chính vì vậy hình ảnh của trò chơi nên vì bạn vẽ ra, bởi vì vậy các bạn ko đề xuất một file như là activity_main.xml.
Copy những hình họa này vào thư mục drawable của project. Tạo new thư mục raw, cùng copy file explosion.wavbackground.mp3 vào thư mục này.
Với trò chơi bạn cần phải sét đặt hình nền và một điều đặc trưng bạn cần phải sét chế độ FullScreen (Đầy màn hình).

package org.o7planning.android2dgame; import app android.ứng dụng.Activity;import app android.os.Bundle;import game android.view.Window;import game 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);
Tiếp theo sét đặt loại màn hình hiển thị nằm theo chiều ngang (Landscape). Quý Khách cần được sét đặt trong AndroidManifest.xml.
Tiếp theo bạn cần viết code nhằm hiển thị nhân thiết bị trò chơi bên trên màn hình hiển thị và dịch rời nó tự trái qua buộc phải theo một gia tốc như thế nào đó.
Với một nhân thứ vào trò chơi chúng ta chỉ gồm một file hình họa, dẫu vậy tệp tin hình họa được chia ra làm các vùng mô tả các hành động khác biệt của nhân trang bị.

Xem thêm: Hướng Dẫn Cách In Tài Liệu (Kèm Ảnh), Hướng Dẫn Cách In Văn Bản Tài Liệu Trong Word


Sử dụng code bạn có thể vẽ một vùng ảnh lên đối tượng người dùng Canvas của trò đùa, tại sinh sản độ x, y. Sử dụng vòng lặp for để thường xuyên vẽ lại trên Canvas chúng ta cũng có thể tạo sự hoạt động của nhân đồ.
Trong lúc lập trình Game chúng ta cũng rất cần phải tính đến hướng dịch rời của nhân thứ vào trò đùa, vận tốc của nhân trang bị.
package org.o7planning.android2dgame;import game 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(Bitmaps 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 Bitbản đồ createSubImageAt(int row, int col) // createBitmap(bitmap, x, y, width, height). Bitbản đồ subImage = Bitmaps.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;
package org.o7planning.android2dgame;import game android.graphics.Bitmap;import game 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; // Velothành phố 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, Bitmaps image, int x, int y) { super(image, 4, 3, x, y); this.gameSurface= gameSurface; this.topToBottoms = new Bitmap; // 3 this.rightToLefts = new Bitmap; // 3 this.leftToRights = new Bitmap; // 3 this.bottomToTops = new Bitmap; // 3 for(int col = 0; col= 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 this.gameSurface.getWidth() -width) this.x= this.gameSurface.getWidth()-width; this.movingVectorX = - this.movingVectorX; 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) 0 &và Math.abs(movingVectorX)
package org.o7planning.android2dgame;import app 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 & loông xã it. canvas = this.surfaceHolder.lockCanvas(); // Synchronized synchronized (canvas) this.gameSurface.update(); this.gameSurface.draw(canvas); catch(Exception e) // Do nothing. finally if(canvas!= null) // Unlochồng Canvas. this.surfaceHolder.unlockCanvasAndPost(canvas); long now = System.nanoTime() ; // Interval lớn redraw game // (Change nanoseconds to milliseconds) long waitTime = (now - startTime)/1000000; if(waitTime
Lớp GameSurface mô rộp cục bộ bề mặt của trò đùa, class này mở rộng tự SurfaceView, SurfaceView đựng một đối tượng người tiêu dùng Canvas, những đối tượng trong trò đùa sẽ được vẽ lên Canvas.
package org.o7planning.android2dgame;import game android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import game android.graphics.Canvas;import app android.view.SurfaceHolder;import game android.view.SurfaceView;public class GameSurface extends SurfaceView implements SurfaceHolder.Callbaông chồng private GameThread gameThread; private ChibiCharacter chibi1; public GameSurface(Context context) super(context); // Make trò chơi Surface focusable so it can handle events. . this.setFocusable(true); // Sét callbaông xã. 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.Callbaông chồng
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.Callbaông chồng
Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) // Implements method of SurfaceHolder.Callbachồng
Override public void surfaceDestroyed(SurfaceHolder holder) boolean retry= true; while(retry) try this.gameThread.setRunning(false); // Parent thread must wait until the over of GameThread. this.gameThread.join(); catch(InterruptedException e) e.printStackTrace(); retry= true;
package org.o7planning.android2dgame;import android.app.Activity;import app android.os.Bundle;import apk.view.Window;import game 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));
Tiếp theo các bạn có xử trí sự kiện lúc người tiêu dùng chạm vào màn hình hiển thị, nhân vật trò nghịch vẫn đuổi theo phía các bạn đang đụng. quý khách yêu cầu xử lý sự kiện này bên trên lớp GameSurface.
Overridepublic boolean onTouchEvent(MotionEvent event) if (sự kiện.getAction() == MotionEvent.ACTION_DOWN) int x= (int)event.getX(); int y = (int)sự kiện.getY(); int movingVectorX =x- this.chibi1.getX() ; int movingVectorY =y- this.chibi1.getY() ; this.chibi1.setMovingVector(movingVectorX,movingVectorY); return true; return false;
package org.o7planning.android2dgame;import android.nội dung.Context;import game android.graphics.Bitmap;import game android.graphics.BitmapFactory;import android.graphics.Canvas;import apk.view.MotionEvent;import game android.view.SurfaceHolder;import apk.view.SurfaceView;public class GameSurface extends SurfaceView implements SurfaceHolder.Callbaông chồng private GameThread gameThread; private ChibiCharacter chibi1; public GameSurface(Context context) super(context); // Make trò chơi Surface focusable so it can handle events. this.setFocusable(true); // Set callbachồng. 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)sự kiện.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.Callbaông chồng
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.Callbaông xã
Override public void surfaceDestroyed(SurfaceHolder holder) boolean retry= true; while(retry) try this.gameThread.setRunning(false); // Parent thread must wait until the over of GameThread. this.gameThread.join(); catch(InterruptedException e) e.printStackTrace(); retry= true;
quý khách hàng rất có thể tạo ra thêm những nhân thiết bị khác vào trò đùa, tại chỗ này tôi thêm 1 nhân thiết bị thứ hai. Sửa lại code của lớp GameSurface:
package org.o7planning.android2dgame;import android.content.Context;import apk.graphics.Bitmap;import app android.graphics.BitmapFactory;import game android.graphics.Canvas;import app android.view.MotionEvent;import app android.view.SurfaceHolder;import app android.view.SurfaceView;import java.util.ArrayList;import java.util.List;public class GameSurface extends SurfaceView implements SurfaceHolder.Callbaông xã private GameThread gameThread; private final List chibiList = new ArrayList(); public GameSurface(Context context) super(context); // Make trò chơi Surface focusable so it can handle events. this.setFocusable(true); // Set callbaông xã. 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)sự kiện.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) Bitmaps 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.Callbaông xã
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 over of GameThread. this.gameThread.join(); catch(InterruptedException e) e.printStackTrace(); retry= true;
Đôi khi bạn cần phải xử lý một vài hiệu ứng đến trò nghịch, ví dụ điển hình nhiều người đang điều khiển và tinh chỉnh một chiếc máy cất cánh, lúc nó rơi xuống khu đất thứ cất cánh tiếng nổ, vậy nổ là 1 trong hiệu ứng. Trong phần này tôi vẫn mô phỏng khi chúng ta đụng (click) vào nhân đồ gia dụng Chibi, nó đã tiếng nổ lớn.
Lớp Explosion mô rộp một vụ nổ, khi bạn clichồng vào nhân đồ Chibi, nó bị nockout ra khỏi trò chơi và một đối tượng người tiêu dùng Explosion được phân phối trò chơi tại địa điểm của nhân đồ dùng Chibi vừa bị loại bỏ quăng quật.
package org.o7planning.android2dgame; import apk.graphics.Bitmap;import apk.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, Bitmaps 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) Bitbản đồ bitmap= this.createSubImageAt(rowIndex,colIndex); canvas.drawBitmap(bitbản đồ, this.x, this.y,null); public boolean isFinish() return finish;
package org.o7planning.android2dgame;import game android.content.Context;import android.graphics.Bitmap;import app android.graphics.BitmapFactory;import app android.graphics.Canvas;import game android.view.MotionEvent;import game android.view.SurfaceHolder;import game android.view.SurfaceView;import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class GameSurface extends SurfaceView implements SurfaceHolder.Callbaông xã { private GameThread gameThread; private final List chibiList = new ArrayList(); private final List explosionList = new ArrayList(); public GameSurface(Context context) super(context); // Make trò chơi 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 iterator= this.chibiList.iterator(); while(iterator.hasNext()) ChibiCharacter chibi = iterator.next(); if( chibi.getX() iterator= this.explosionList.iterator(); while(iterator.hasNext()) Explosion explosion = iterator.next(); if(explosion.isFinish()) // If explosion finish, Remove the current element from the iterator & menu. 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.Callbachồng
Override public void surfaceCreated(SurfaceHolder holder) Bitmaps chibiBitmap1 = BitmapFactory.decodeResource(this.getResources(),R.drawable.chibi1); ChibiCharacter chibi1 = new ChibiCharacter(this,chibiBitmap1,100,50); Bitmaps 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.Callbachồng
Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) // Implements method of SurfaceHolder.Callbachồng
Override public void surfaceDestroyed(SurfaceHolder holder) boolean retry= true; while(retry) try this.gameThread.setRunning(false); // Parent thread must wait until the kết thúc of GameThread. this.gameThread.join(); catch(InterruptedException e) e.printStackTrace(); retry= true;
Tiếp theo bạn phải thêm cảm giác âm tkhô nóng vào trò nghịch, chẳng hạn âm tkhô cứng nền của trò chơi, âm tkhô nóng tiếng nổ lúc nhân thứ Chibi bị hủy hoại.
package org.o7planning.android2dgame;import game android.graphics.Bitmap;import apk.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 &và 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) Bitmaps bitmap= this.createSubImageAt(rowIndex,colIndex); canvas.drawBitmap(bitmaps, this.x, this.y,null); public boolean isFinish() return finish;
package org.o7planning.android2dgame;import app android.content.Context;import app android.graphics.Bitmap;import apk.graphics.BitmapFactory;import apk.graphics.Canvas;import game android.truyền thông.AudioAttributes;import android.truyền thông media.AudioManager;import game android.media.SoundPool;import game android.os.Build;import app android.view.MotionEvent;import android.view.SurfaceHolder;import app android.view.SurfaceView;import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class GameSurface extends SurfaceView implements SurfaceHolder.Callbachồng { private GameThread gameThread; private final List chibiList = new ArrayList(); private final List explosionList = new ArrayList(); 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 callbaông chồng. 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 iterator= this.chibiList.iterator(); while(iterator.hasNext()) ChibiCharacter chibi = iterator.next(); if( chibi.getX() iterator= this.explosionList.iterator(); while(iterator.hasNext()) Explosion explosion = iterator.next(); if(explosion.isFinish()) // If explosion finish, Remove the current element from the iterator & menu. 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.Callbaông xã
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.Callbaông chồng
Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) // Implements method of SurfaceHolder.Callbaông chồng
Override public void surfaceDestroyed(SurfaceHolder holder) boolean retry= true; while(retry) try this.gameThread.setRunning(false); // Parent thread must wait until the over of GameThread. this.gameThread.join(); catch(InterruptedException e) e.printStackTrace(); retry= true;