You are on page 1of 18

Pht trin ng

dng
Smartphone
Ti liu lu hnh ni b
y l ti liu tham kho s dng trong mn hc Lp trnh ng dng Smartphone Android
c tng hp, bin son t nhiu ngun bi cc thnh vin ca Nhm nghin cu v ng dng cng
ngh A106-i hc Hoa Sen.
Nhm A106-http://profiles. hoasen. edu. vn/groups/584/
Pht trin ng dng Smartphone Android



Pht trin ng
dng Smartphone

Phn 04: ha 2D
L c Huy
Email: leduchuy89vn@gmail.com
Pht trin ng dng Smartphone Android

Mc lc
1 Khi nim c bn .................................................................................................... 3
2 Xy dng CustomView ........................................................................................... 3
3 Lp trnh lung trong ha 2D ............................................................................. 8
4 Game vi SurfaceView ......................................................................................... 11


Pht trin ng dng Smartphone Android

1 Khi nim c bn
Trn Android, v bt th g ta cn phi c bn thnh phn c bn:
- Mt i tng kiu Bitmap gi cc pixel cn v.
- Mt i tng cha nt v cn v ra(C th l Rect, Path, Bitmap).
- Mt i tng kiu Paint dng nh ngha mu sc, style dng v ra mn hnh.
- Mt i tng Canvas dng thc thi lnh v.
lm r nhng khi nim trn ta tin hnh to mt lp CustomView ci t li lp View ca
Android nh ngha mt i tng ha mi. Trn i tng mi nh ngha ny, ta s t v ra
giao din m mnh mong mun.
2 Xy dng CustomView
to mt CustomView ta tin hnh to mt class vi ni dung nh sau:
package niit.android;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;

public class CustomView extends View{

public CustomView(Context context){
super(context);
}

public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
protected void onDraw(Canvas canvas) {

}

}
Lp CustomView s extend class View ca Android k tha li cc phng thc cng nh
cc thuc tnh ca lp View. Trong ta s ci t li 02 phng thc khi to cho lp CustomView
v ghi phng thc onDraw() ca lp View, y chnh l phng thc s v ra giao din ca
CustomView.
Pht trin ng dng Smartphone Android

Vi phng thc khi to public CustomView(Context context) ch nhn vo mt tham s l
mt i tng Context. y l i tng ny cho php truy xut n cc i tng cng nh cc dch
v ca h thng. i tng ny cn thit v mt giao din ra mn hnh thit b.
Vi phng thc khi to th hai: public CustomView(Context context, AttributeSet attrs) c
nhn vo thm mt tham s l AttributeSet attrs. y l i tng cha cc thuc tnh ca i tng
ha s c khi to. Vic to phng thc khi to th hai l cn thit nu bn mong mun s dng
i tng ha ny trong mt file giao din .xml c ch nh cc thuc tnh nh v d sau:
Cho mt file xml c ni dung nh sau:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<niit.android.CustomView
android:id="@+id/graphicView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
Trong file xml k trn ta c s dng mt th c tn niit.android.CustomView, y chnh l i
tng ha ta va to ra trn. Trong niit.android l package ca project hin ti. Th
CustomView trn c ba thuc tnh l android:id, android:layout_width v android:layout_height. Ta
c th to mt Activity c ni dung l file xml k trn:
public class main extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
Lc ny Android s t to ra i tng CustomView v s dng phng thc khi to public
CustomView(Context context, AttributeSet attrs) khi to i tng vi cc thuc tnh l
android:id, android:layout_width v android:layout_height c truyn vo thng qua i tng attrs.
n y ta to xong lp CustomView, tuy nhin nu chy chng trnh bc ny ta ch
c mt giao din trng rng. v giao din cho CustomView ta s tin hnh ci t phng thc
onDraw() vi ni dung nh sau:

Pht trin ng dng Smartphone Android

@Override
protected void onDraw(Canvas canvas) {
Paint cPaint = new Paint();
cPaint.setColor(Color.RED);

Path cPath = new Path();
cPath.addCircle(100, 100, 20, Direction.CW);

canvas.drawPath(cPath, cPaint);
}
Nh cp mc trn v ra mn hnh ta to mt i tng Paint c dng nh
ngha mu sc, style ta cn v ra. Gi phng thc setColor() gn mu sc ca nt v cn v ra.
Sau ta tin hnh khai bo mt i tng Path cha cc nt v v gi phng thc addCircle()
thm mt nt v hnh trn vo i tng cPath. Sau gi canvas.drawPath(cPath,cPaint) v ra
cc nt v c cha trong i tc cPath vi mu sc c nh ngha trong i tng cPaint. Khi
thc thi chng trnh ta s c kt qu nh sau:

n y ta c c mt CustomView theo mun ca mnh. Ngoi vic v ra cc nt v
n gin nh: ng thng, ng trn, hnh vung ta cn c th v file hnh nh bng cch sau:

Pht trin ng dng Smartphone Android

@Override
protected void onDraw(Canvas canvas) {
Paint bPaint = new Paint();

Bitmap bitmap=BitmapFactory.decodeResource(getResources(),
R.drawable.ball);
canvas.drawBitmap(bitmap, 100, 100,bPaint );
}
Vi trng hp mun v mt file hnh nh ln CustomView ta to mt i tng Bitmap
cha cc pixel cn v ln mn hnh. i tng Bitmap l mt kiu t chc b nh hoc nh dng tp
tin dng lu tr nh s. i tng Bitmap n gin l mt mng hai chiu, trong mi phn t
cha mt gi tr mu RGB tng ng vi mt im mu trn bc nh s hoc im mu c v ln
mn hnh.
Ta dng BitmapFactory.decodeResource() to i Bitmap t mt tp tin hnh nh lu
trong th mc drawable. Sau khi thc thi chng trnh ta s c kt qu nh sau:

Sau khi v c tri banh ra mn hnh ta s lm cho tri banh di chuyn trong phm vi i
tng CustomView. Khi tri banh chm bin ngang hay chm bin dc th tri banh s b di ngc li.
Ta b sung thm cc thuc tnh sau:
Public int x=0;
public int y=0;
private int Vx=1,Vy=1;
private int diameter = 30;
Pht trin ng dng Smartphone Android

Trong x, y l ta ca tri banh trn mn hnh. Vx, Vy ln lt l vn tc theo phng dc
v phng ngang ca tri banh. Sau ta b sung thm phng thc diChuyenBanh vi ni dung nh
sau:
protected void diChuyenBanh() {

x=x+Vx;
y=y+Vy;

if(x<=0||(x>=getWidth()-diameter))
{
Vx=-Vx;
}
if(y<=0||y>=getHeight()-diameter)
{
Vy =-Vy;
}
invalidate();
}
Phng thc ny s ln lt cng ta x, y ca tri banh vi Vx, Vy thay i v tr ca tri
banh. Sau khi thanh i ta x, y ca tri banh s tin hnh kim tra xem ta mi ca tri banh
vt qua bin ngang v bin dc ca CustomView cha. Nu ta mi vt qua bin dc v bin
ngang ca tri banh th i hng ca vect vn tc cho tri banh chuyn ng theo hng ngc
li (Cho tri banh di ngc li). Cui cng gi phng thc invalidate(), y l phng thc s gi li
phng thc onDraw v li giao din ca CustomView. CustomView c th chuyn ng ta tin
hnh thay i phng thc onDraw vi ni dung nh sau:
@Override
protected void onDraw(Canvas canvas) {

Paint bPaint = new Paint();

Bitmap bitmap=BitmapFactory.decodeResource(getResources(),
R.drawable.ball);
canvas.drawBitmap(bitmap, x, y,bPaint );
diChuyenBanh();

}
Vi phng thc onDraw c nh ngha nh trn y th CustomView s v ra mn hnh
tri banh ti v tr (x,y) vi gi tr mc nh (0,0). Sau gi phng thc di chuyn banh tnh ton
li ta (x,y) mi. Trong phng thc diChuyenBanh ta c gi phng thc invalidate(), y l mt
cch gin tip gi quy li onDraw. Bng cch ny CustomView s lin tc c v i v li vi
gi tr (x,y) thay i qua mi ln v li.
Pht trin ng dng Smartphone Android

3 Lp trnh lung trong ha 2D
lm game trn bt k nn tng no ta cng cn phi quen thuc vi khi nim lp trnh
lung. Khi nim lung n gin l vic giao mt cng vic cn thc hin cho mt i tng. Sau khi
giao cng vic cho i tng th n s c thc thi ng thi vi cc cng vic chnh ang c
thc hin. Bng cch ny, mt cng vic c th c thc thi ng thi vi cc cng vic khc m
khng phi ch i c thc thi tun t nh lp trnh truyn thng.
lm quen vi lung ta tin hnh thc hin v d sau:
Tin hnh b sung thm mt ng h m gi cho CustomView. Tin hnh m ngc t 30s
tr v 0 v in ra Thi gian: 29. Khi m n 0 th ngng khng in tri banh ra mn hnh na m thay
vo l in cu Bn thua ri!.
y ta c th thy c c hai cng vic ang c thc thi ng thi:
- Cng vic 01: V ra mn hnh on text: Thi gian XX v v ra tri banh ti ta (x,y).
- Cng vic 02: Tun t gim gi tr ca bin m mi ln mt n v. Sau khi gim gi tr th
ngng li 1 giy v thc hin li cng vic.
lm c vic ny ta b xung thm mt thuc tnh int count = 30; v mt lp ni trong
CustomView vi ni dung nh sau:
private class TimeCountThread extends Thread{
@Override
public void run() {
while(count>0){
try {
count--;
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}
Lp TimeCountThread extend lp Thread dng khai bo mt lung cho java. Lp ny ch c
mt phng thc chnh l run(). Phng thc ny s c thc thi khi lung c khi ng. Lung
c to ra t lp TimeCountThread lm nhim v m ngc bin count, mi ln m xong s ngng
li 1000 ms v thc hin li cng vic cho n khi count<=0.
B xung thm thuc tnh cho lp CustomView:
TimeCountThread timeCountThread = new TimeCountThread();
Pht trin ng dng Smartphone Android

Sau khi thc hin xong cc bc trn ta c mt lung tn l timeCountThread. Tuy nhin
n y th lung timeCountThread ny vn cha c khi ng. khi ng lung trn ta b xung
vo hai phng khi to ca CustomView sau khi khi to i tng xong s khi ng lung
timeCountThread. Ni dung thay i nh sau:
package niit.android;

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.util.AttributeSet;
import android.view.View;

public class CustomView extends View{

private int count = 30;

public int x=0;
public int y=0;
private int Vx=1,Vy=1;
private int diameter = 30;

TimeCountThread timeCountThread = new TimeCountThread();

public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
timeCountThread.start();
}

public CustomView(Context context){
super(context);
timeCountThread.start();
}

@Override
protected void onDraw(Canvas canvas) {

if(count>0)
{

Paint tPaint = new Paint();
tPaint.setColor(Color.RED);

canvas.drawText("Time: " + count, 5, 20, tPaint);
Pht trin ng dng Smartphone Android


Paint bPaint = new Paint();

Bitmap
bitmap=BitmapFactory.decodeResource(getResources(),
R.drawable.ball);
canvas.drawBitmap(bitmap, x, y,bPaint );

diChuyenBanh();

} else {
Paint tPaint = new Paint();
tPaint.setColor(Color.RED);

canvas.drawText("Bn thua ri",30,30,tPaint);
}

}

protected void diChuyenBanh() {

x=x+Vx;
y=y+Vy;

if(x<=0||(x>=getWidth()-diameter))
{
Vx=-Vx;
}
if(y<=0||y>=getHeight()-diameter)
{
Vy =-Vy;
}
invalidate();
}

private class TimeCountThread extends Thread{

@Override
public void run() {
while(count>0){
try {
sleep(1000);
count--;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Pht trin ng dng Smartphone Android

}

}

}
4 Game vi SurfaceView
SurfaceView l mt b mt chuyn s dng v. N l mt lp k tha t View v b sung
thm mt s phng thc cng nh tnh nng h tr cho vic v lin tc ln b mt. phn ny ca ti
liu ta s tin hnh to mt lp k tha t SurfaceView v ra mn hnh mt tri banh v cho n di
chuyn nh bi trc. bt u ta to mt lp mi vi ni dung nh sau:
package niit.android;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GamePanel extends SurfaceView implements
SurfaceHolder.Callback {
public GamePanel(Context context) {
super(context);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int
format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
Trn y ta nh ngha mt lp tn l GamePanel k tha SurfaceView v ci t li interface
SurfaceHolder.Callback. Trong c mt phng thc khi to v ba phng thc s l cc s kin:
surface c to ra, surface thay i cc thng s v khi surface b hy.
Sau khi to xong mt lp nh trn ta cn phi bo cho GamePanel bit i tng s s l cc s
kin nh surface c to ra, surface thay i cc thng s v khi surface b hy bng cch thay i
phng thc khi to vi ni dung nh sau:
Pht trin ng dng Smartphone Android

public GamePanel(Context context) {
super(context);
getHolder().addCallback(this);
}
Bng cch ny i tng GamePanel hin ti c ch nh s l cc s kin nh: surface
c to ra, surface thay i cc thng s v khi surface b hy. Khi mt trong trong cc s kin trn
din ra n s gi mt trong ba phng thc:
public void surfaceCreated(SurfaceHolder holder);
public void surfaceChanged(SurfaceHolder holder, int format, int
width, int height);
public void surfaceDestroyed(SurfaceHolder holder);
Ba phng thc ny ta s c ci t phn sau.
B sung thm lp Ball vi ni dung nh sau:
package niit.android;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;

public class Ball {
// Hai thuoc tinh chieu rong va chieu cao cua GamePanel.
private float gamePanelWidth = 0;
private float gamePanelHeight = 0;
// Hai thuoc tinh xac dinh toa do (x,y) hien tai cua trai
banh.
private float x;
private float y;
// Duong kinh trai banh.
private float diameter;
// Van toc theo phuong ngang va theo phuong doc cua trai
banh.
private float Vx;
private float Vy;
// Doi tuong Bitmap chua hinh anh trai banh.
private Bitmap bitmap;
// Hai phuong thuc set, get cua thuoc tinh Bitmap.
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap mBitmap) {
this.bitmap = mBitmap;
}
// Phuong thuc gan toa do cho trai banh.
Pht trin ng dng Smartphone Android

public void setPosition(float x, float y){
x = x;
y = y;
}
// Phuong thuc gan van toc cho trai banh.
public void setVelosity(float Vx, float Vy){
this.Vx = Vx;
this.Vy = Vy;
}
// Phuong thuc khoi tao trai banh.
public Ball(Resources res, float x, float y, float
gamePanelWidth,float gamePanelHeight) {
bitmap = BitmapFactory.decodeResource(res,
R.drawable.ball);
this.x = x;
this.y = y;
diameter = bitmap.getWidth();

Vx = 0;
Vy = 0;

this.gamePanelHeight = gamePanelHeight;
this.gamePanelWidth = gamePanelWidth;

}
// Phuong thuc ve trai banh bang doi tuong Canvas duoc
truyen vao duoi dang tham so.
public void drawBall(Canvas canvas) {
canvas.drawBitmap(bitmap, x, y, null);
}
// Phuong thuc di chuyen trai banh.
public void moveBall() {
x += Vx;
y += Vy;
checkBallPosition();
}
// Phuong thuc kiem tra vi tri trai banh, neu vuot qua bien
ngang hoac bien doc thi doi huong trai banh lai.
private void checkBallPosition() {
if(x<=0||(x>=gamePanelWidth-diameter))
{
Vx=-Vx;
}
if(y<=0||y>=gamePanelHeight-diameter)
{
Vy =-Vy;
}
Pht trin ng dng Smartphone Android

}
}
Lp Ball ny c phng thc drawBall() s dng v ra tri banh trn i tng
GamePanel. Vic v tri banh ln i tng GamePanel s thc hin thng qua i tng Canvas s
c cung cp bi GamePanel thng qua mt tham s.
n y ta cn dng li mt cht xem li nhng g c. Trc tin ta c mt i tng
GamePanel s l mt mn hnh game th hin mt tri banh di chuyn. i tng GamePanel s l i
tng n nhn cc s kin: ngi dng tng tc ln mn hnh, ngi dng nhn phm cng trn mn
hnh Nu giao vic v tri banh di chuyn cho i tng GamePanel lun th trong thi gian n thc
hin lnh v tri banh th n khng th cng lc s l lun c cc s kin ngi dng tng tc vi
mn hnh, bn phm Do ta s nh ngha mt Thread lin tc thc hin vic v tri banh ra mn
hnh. Tin hnh nh ngha mt lp GameThread nm trong GamePanel vi ni dung nh sau:
class GameThread extends Thread {
private SurfaceHolder mHolder;
private boolean mRun = false;

public GameThread() {
mHolder = GamePanel.this.getHolder();
}

public void setRunning(boolean run) {
mRun = run;
}

@Override
public void run() {
Canvas canvas = null;
while (mRun) {
canvas = mHolder.lockCanvas();
if (canvas != null) {
GamePanel.this.thayDoiManHinhGame();
GamePanel.this.veManHinhGame(canvas);
mHolder.unlockCanvasAndPost(canvas);
}
}
}
}
Lung GameThread trn ch c hai thuc tnh:
- SurfaceHolder mHolder: l i tng nm gi mt b mt hin th. y l b mt hin
th ca GamePanel.
- boolean mRun: l bin c dng iu khin vng lp while trong phng thc run ca
lung GameThread.
Pht trin ng dng Smartphone Android

Lp GameThread c mt phng thc dng dng gn gi tr cho i tng SurfaceHolder
mHolder bng i tng c tr v bng cch gi phng thc GamePanel.this.getHolder();. y l
cch gi phng thc getHolder ca lp GamePanel. Phng thc ny s tr v i tng nm gi mt
b mt hin th ca GamePanel.
Trn lp GameThread ta ghi li phng thc run(). y chnh l phng thc c thc
thi khi GameThread c khi ng. Phng thc run ca GameThread c mt vng lp while vi
iu kin lp l gi tr ca bin mRun. Trong vng lp while ny ta ln lt thc thi cc lnh:
canvas = mHolder.lockCanvas();
if (canvas != null) {
GamePanel.this.changeGamePanel();
GamePanel.this.drawGamePanel(canvas);
mHolder.unlockCanvasAndPost(canvas);
}
Nh gii thch trn, khi khi to i tng GameThread ta gn gi tr mHolder bng i
tng nm gi b mt hin th ca GamePanel. v ln b mt ca mHolder ta s cn phi s dng
mt i tng canvas. Tuy nhin m bo trong qu trnh GameThread v ln b mt mHolder
khng ai v ln na ta thc thi lnh lockCanvas(). Phng thc ny s tr v mt i tng
canvas. Ta c th dng i tng canvas ny v ln mHolder nh cch v ln CustomView mc 1
ca chng ny. Tin hnh gi GamePanel.this.changeGamePanel(); thay i v tr ca tri banh v
gi GamePanel.this.drawGamePanel(canvas); v tri banh ra phn mn hnh bng cch s dng i
tng canvas trn. Sau khi v xong tin hnh unclockCanvasAndPost it ng canvas ln mHolder
cc nt v trong canvas c th hin ln mn hnh mHolder ang nm gi.
Tin hnh b xung thm 02 phng thc nhc n trn:
public void drawGamePanel(Canvas canvas) {
canvas.drawColor(Color.BLACK);
synchronized (ball) {
ball.drawBall(canvas);
}
}
Phng thc drawGamePanel() s v li mn hnh GamePanel bng cch t mu ton b mn
hnh bng mu en v gi lnh ball.drawBall() truyn theo i tng canvas v. Bng cch ny
phng thc drawBall s s dng i tng canvas c cung cp di dng tham s v ra tri
banh ti v tr (x,y) l gi tr thuc tnh ca n.
public void changeGamePanel() {
synchronized (ball) {
ball.moveBall();
}
}
Pht trin ng dng Smartphone Android

Phng thc changeGamePanel() s gi ball.moveBall() di chuyn tri banh ti v tr mi
da vo vn tc theo phng dc v phng ngang ca tri banh hin ti.
n thi im hin ti, ta gn nh hon tt chng trnh theo yu cu t ra ban u. Tuy
nhin ta cn phi b sung thm mt cht bng cch ci t li cc phng thc sau:
@Override
public void surfaceCreated(SurfaceHolder holder) {

ball = new Banh(getResources(), 0, 0, this.getWidth(),
this.getHeight());
ball.ganVanToc(5, 5);

if (!gameThread.isAlive()) {
gameThread = new GameThread();
gameThread.setRunning(true);
gameThread.start();
}
}
Phng thc surfaceCreated() s c gi khi GamePanel c dng hon tt. y ta cn b
sung vi dng lnh to mi i tng ball cng nh khi ng gameThread tri banh bt u di
chuyn.
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (gameThread.isAlive()) {
gameThread.setRunning(false);
}
}
Phng thc surfaceDestroyed s c gi khi GamePanel hy xong. y n gin l ta
gn gi tr cho bin mRun bng false vng lp while trong phng thc run ca GameThread dng
khng lp tip. Khi GameThread s kt thc cng vic.
Lu : y c s dng hai i tng l ball v gameThread c khai bo nh l mt thuc
tnh ca GameThread:
private GameThread gameThread = new GameThread();
private Ball ball;


Pht trin ng dng Smartphone Android

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
{
lastX = event.getX();
lastY = event.getY();
synchronized (balls) {
newBall = new Ball(getResources(),lastX,lastY);

newBall.setPosition(lastX, lastY);
newBall.setVelocity(0,0);
balls.add(newBall);
}
}
return true;

case MotionEvent.ACTION_MOVE:
{
synchronized (newBall) {
newBall.setPosition(event.getX(), event.getY());
}
}
return true;

case MotionEvent.ACTION_UP:
{
if(newBall!=null)
{
synchronized (newBall) {
newBall.setVelocity((float)((event.getX()-
lastX)/10.0),(float)((event.getY()-lastY)/10.0));
}
}
}
return true;

default:

break;
}

return super.onTouchEvent(event);
}

You might also like