본문 바로가기

카테고리 없음

Android Card Game example Part 11

Android Card Game example Part 11

카드게임에서 카드 섞기와 카드를 선택할 때 사운드를 추가한 예


CardGameActivity.java

package test.android.cardgame;


import android.app.Activity;


import android.os.Bundle;


public class CardGameActivity extends Activity {

    @Override

    public void onCreate(Bundle savedInstanceState) { 

        super.onCreate(savedInstanceState);

        CardGameView view = new CardGameView(this);

        setContentView(view); 

    }

}


CardGameView.java

package test.android.cardgame;


import java.util.Random;

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.Rect;

import android.media.AudioManager;

import android.media.SoundPool;

import android.util.Log;

import android.view.MotionEvent;

import android.view.View;


public class CardGameView extends View {


Bitmap bgImg;

Bitmap backsideImg;

Card [][] card = new Card[2][3];


int shuffleSound, cardTouchSound;

// 게임상태의 구분

int STATUS_INIT = 0;

int STATUS_READY = 1;

int STATUS_GAME_ON = 2;

int STATUS_END = 3;


int status; // 게임의 상태


Card selCard1, selCard2;


int cnt_fails;


long time_start, time_end;


boolean scoreCompleted;


SoundPool sp;

public CardGameView(Context context) {

super(context);

bgImg = BitmapFactory.decodeResource(getResources(), R.drawable.background);

sp = new SoundPool(5, AudioManager.STREAM_MUSIC,0);

shuffleSound = sp.load(getContext(), R.raw.shuffling, 1);

cardTouchSound = sp.load(getContext(), R.raw.card_touch,1);


shuffleCards(); // 카드 섞기


status = STATUS_INIT;


CardGameThread gameThread = new CardGameThread(this);

gameThread.start();

}




private void shuffleCards() { 

sp.play(shuffleSound, 1, 1, 0, 0, 1);

int[] src = {1,2,3,1,2,3};

int[] dest = new int[6];


int dst_idx = 0;

int n = src.length;


Random rd = new Random();


for(int i=0;i<src.length;i++) {

int tmp = rd.nextInt(n--);

dest[dst_idx++] = src[tmp];

for(int k=tmp;k<n;k++) {

src[k] = src[k+1];

}

}


card[0][0] = new Card(getContext(), dest[0]);

card[0][1] = new Card(getContext(), dest[1]);

card[0][2] = new Card(getContext(), dest[2]);

card[1][0] = new Card(getContext(), dest[3]);

card[1][1] = new Card(getContext(), dest[4]);

card[1][2] = new Card(getContext(), dest[5]);

}




@Override


protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawBitmap(bgImg, 0, 0, null);

for(int y=0;y<2;y++) {

for(int x=0;x<3;x++) {

card[y][x].draw(canvas, 35+x*90, 150+y*130);

}

}


if(status==STATUS_INIT){

Bitmap btnStart = BitmapFactory.decodeResource(getResources(), R.drawable.btn_start);

int bw = btnStart.getWidth();

int bh = btnStart.getHeight();

int cw = canvas.getWidth();

int ch = canvas.getHeight();

canvas.drawBitmap(btnStart, cw/2-(bw/2), ch/2-(bh/2), null);

}else if(status==STATUS_END) {

Bitmap restart = BitmapFactory.decodeResource(getResources(), R.drawable.restart);

int bw = restart.getWidth();

int bh = restart.getHeight();

int cw = canvas.getWidth();

int ch = canvas.getHeight();

canvas.drawBitmap(restart, cw/2-(bw/2), ch/2-(bh/2), null);

writeResult(canvas);

}

}


private void writeResult(Canvas canvas) {

Bitmap tgn = BitmapFactory.decodeResource(getResources(), R.drawable.typography_num);

int elapse = (int)((time_end - time_start)/1000);

String strElapse = String.valueOf(elapse);

Paint paint = new Paint();

paint.setTextSize(30);

paint.setColor(Color.RED);

canvas.drawText("Elapsed Time : ", 20, 30, paint);

for(int i=0;i<strElapse.length();i++) {

int num = Integer.valueOf(strElapse.charAt(i)+"");

num = num==0 ? 10 : num;

int endPx = num*26;

int beginPx = (num-1)*26;

int endPy = 42;

int beginPy = 0;


canvas.drawBitmap(tgn,new Rect(beginPx, beginPy, endPx, endPy), new Rect(i*26+220, 0, (i+1)*26+220, 42), null);

//Log.i("경과시간(초):", ""+elapse);

}

paint.setColor(Color.WHITE);

canvas.drawText("Fails : "+cnt_fails+" times", 20, 55, paint);

scoreCompleted = true;

}


@Override

public boolean onTouchEvent(MotionEvent event) {

sp.play(cardTouchSound, 1, 1, 0, 0, 1);

if(status==STATUS_INIT) {

startGame();

status=STATUS_READY;

}else if(status==STATUS_READY) {

//쓰레드를 이용하여 5초동안 카드의 앞면을  보여주고 이어서 카드의 뒷면이 보이도록 화면을 전환한다

//이 상태 동안은 이용자의 터치 이벤트에는 반응하지 않는다

}else if(status==STATUS_GAME_ON) {

int x = (int) event.getX();

int y = (int) event.getY();

Card card = touchedCard(x,y);

if(card==null) return false;

card.status = Card.STATUS_TMPSHOW;

if(selCard1==null) {

selCard1 = card;

}

else {

selCard2 = card;

}

}else if(status==STATUS_END) {

cnt_fails = 0;

time_start = time_end = 0;

scoreCompleted = false;

shuffleCards();

startGame();

status=STATUS_READY;

}

invalidate(); // 선택된 즉시 화면을 갱신하므로 2개의 카드가 서로 다르더라도 일단 카드의 앞면이 보이게 됨

return super.onTouchEvent(event);

}


public void startGame() {

for(int y=0;y<2;y++) {

for(int x=0;x<3;x++) {

card[y][x].status = Card.STATUS_SHOW;

}

}

}


public void upsideDown() {

for(int y=0;y<2;y++) {

for(int x=0;x<3;x++) {

card[y][x].status = Card.STATUS_CLOSE;

}

}

}


private Card touchedCard(int px, int py) {

for(int y=0;y<2;y++) {

for(int x=0;x<3;x++) {

if(card[y][x].isTouched(px, py)) return card[y][x];

}

}

return null;

}


public void checkMatch() {

if(status==STATUS_END || selCard1 == null || selCard2 == null) return;

if(selCard1.color == selCard2.color) {

selCard1.status = selCard2.status = Card.STATUS_MATCHED;

}else{ // 2개의 카드가 서로 일치하지 않을 경우 잠깐동안만 2개 카드의 앞면이 나타나도록 sleep 한다.

cnt_fails++;

try{

Thread.sleep(300);

}catch(InterruptedException ie){}

selCard1.status = selCard2.status = Card.STATUS_CLOSE;

}

selCard1 = selCard2 = null;

postInvalidate(); // User Thread가 UI Thread에게 화면갱신을 요청함

}


public boolean isAllMatch() {

if(status==STATUS_END) return true;

for(int y=0;y<2;y++) {

for(int x=0;x<3;x++) {

if(card[y][x].status != Card.STATUS_MATCHED) {

return false;

}

}

}

time_end = System.currentTimeMillis();

status = STATUS_END;

return true;

}

}


Card.java

package test.android.cardgame;


import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Rect;


public class Card {


static int COLOR_RED = 1;

static int COLOR_GREEN = 2;

static int COLOR_BLUE = 3;


static int STATUS_CLOSE = 1;

static int STATUS_SHOW = 2;

static int STATUS_TMPSHOW = 3;

static int STATUS_MATCHED = 4;


Bitmap backsideImg;

Bitmap bitmap;


int color;

int status;


Rect region = new Rect();

public Card(Context ctx, int color){

this.status = STATUS_CLOSE;

this.color = color;

if(backsideImg==null)

backsideImg = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.backside);

if(color==COLOR_RED)

bitmap = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.front_red);

else if(color==COLOR_GREEN)

bitmap = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.front_green);

else if(color==COLOR_BLUE)

bitmap = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.front_blue);

}


public void draw(Canvas c, int x, int y){

region.left = x;

region.top = y;

region.right = x + 80;

region.bottom = y + 115;


if(status != STATUS_CLOSE) c.drawBitmap(bitmap, x, y, null);

else c.drawBitmap(backsideImg, x, y, null);

}


public boolean isTouched(int x, int y) {

return region.contains(x, y);

}

}


CardGameThread.java

package test.android.cardgame;


public class CardGameThread extends Thread {

CardGameView view;

public CardGameThread(CardGameView view) {

this.view = view;

}


@Override

public void run() {

while(true) {

if(view.status==view.STATUS_READY){ // 게임 시작에 앞서 모든 카드 앞면이 5초간 보이게 한다.

try {

Thread.sleep(5000);

} catch (InterruptedException e) {

e.printStackTrace();

}

view.upsideDown();

view.status=view.STATUS_GAME_ON;

view.time_start = System.currentTimeMillis();

}

view.checkMatch();

view.isAllMatch();

view.postInvalidate();

}

}

}

사용된 사운드 파일

card_touch_mp3

shuffling_mp3