Androidプログラミング日記 (仮)  

神経衰弱

あなたは

人目のプログラマーだよ。

Androidプログラミング日記 (仮).

 

 

 

 

神経衰弱

パズル系を作成したくなって、やっぱし暇つぶしといったらトランプかなと思い、一番簡単にできそうなものは何かと考えた所、神経衰弱じゃないかなと思い作成してみました。

作りは雑です。何が大変だったって、画像作成が一番骨が折れました。めんどくさくて・・・

でも一度画像を用意すれば使い回しが効きますからいい感じです。

使用画像 前回と変わらず
 

ファイル名「Tramp1Activity.java」 ここもそのまま

package and.roid.tramp1;

import android.app.Activity;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.Display;
import android.view.Window;
import android.view.WindowManager;

public class Tramp1Activity extends Activity {
	public float disp_w,disp_h;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFormat(PixelFormat.TRANSLUCENT);
        Window window = getWindow();
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        WindowManager manager = window.getWindowManager();
        Display disp = manager.getDefaultDisplay();
        disp_w = disp.getWidth();
        disp_h = disp.getHeight();

        setContentView(new MainLoop(this));
        //setContentView(R.layout.main);
    }
}

                            
 

Activityファイルは、一番下の段のコードがたまに変わるだけでいつもこのまま使っています。

完全フルスクリーン仕様&画面の幅、高さを取得しています。

 

ファイル名「MainLoop.java」

package and.roid.tramp1;

import java.util.ArrayList;
import java.util.Date;
import java.util.Random;

import android.content.Context;
import android.content.res.Resources;
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.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MainLoop extends SurfaceView implements SurfaceHolder.Callback,Runnable{
	public static final int GAME_START = 0;//ゲーム状態固定値
	public static final int GAME_PLAY = 1;//ゲーム状態固定値
	public static final int GAME_CLEAR = 2;
	private int game_state;//ゲーム状態決定変数
	private Thread thread;
	private SurfaceHolder holder;
	private float disp_w,disp_h;//画面の幅高さ
	private Tramp1Activity Card1;//Activityクラス登録
	private int sleep;//遅延時間

	//変数設定

	public static final int MAX_MAISUU = 52;//カード枚数
	public static final int SYURUI = 4;//カード種類の数
	public static final int MAISUU = 13;//カード1種類の枚数

	private Card buck;//背景画像
	private Drawable[] card_img;//52枚カード
	private Drawable[] card_img2;//カード裏、使わないけどジョーカー用
	private ArrayList<Card> card = new ArrayList();//カード用オブジェクト
	private Rect[] card_xy;//カード座標用

	private boolean tap_rect = false;//1枚目タップ用
	private Card tap;//タップしたら色変更用
	private Rect tap_rect_old = new Rect(0,0,0,0);//1枚目タップカード座標
	private boolean tap_tap = false;//2枚目タップしたかどうか
	private int tap_one,tap_two;//1、2枚目タップのオブジェクト位置
	private int hantei_count = 0;//すぐ判定せずにカウントさせる用

	private int card_count = 0;//52枚めくれたかどうか用


	//変数設定ここまで

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

	public void init(Context context){
		holder = getHolder();
		holder.addCallback(this);
		holder.setFixedSize(getWidth(), getHeight());
		Card1 = (Tramp1Activity)context;
		disp_w = Card1.disp_w;//画面幅取得
		disp_h = Card1.disp_h;//画面高さ取得
		game_state = 1;//ゲーム状態

		//ここから初期化

		this.setSleep(0);//ループ中遅延時間

		buck = new Card(disp_w,disp_h);
		buck.Rectinit(0, 0, (int)disp_w, (int)disp_h, Color.BLACK,100);
		tap = new Card(disp_w,disp_h);
		tap.Rectinit(0,0,100,100, Color.RED,30);

		Resources resources = context.getResources();//画像登録準備
		card_img = new Drawable[MAX_MAISUU];
		Bitmap img= BitmapFactory.decodeResource(resources,R.drawable.card);
		card_xy = new Rect[MAX_MAISUU];
		for(int i=0;i<SYURUI;i++){
			for(int j=0;j<MAISUU;j++){
				card_img[j+i*MAISUU] = new BitmapDrawable(
					Bitmap.createBitmap(img,j*(img.getWidth()/MAISUU),i*(img.getHeight()/SYURUI),
							img.getWidth()/MAISUU,img.getHeight()/SYURUI));
				card_xy[j+i*MAISUU] = new Rect(j*(int)(disp_w/MAISUU),i*(int)(disp_h/SYURUI),
						(int)(disp_w/MAISUU),(int)(disp_h/SYURUI));
			}
		}
		card_img2 = new Drawable[2];
		img= BitmapFactory.decodeResource(resources,R.drawable.sonota);
		for(int i=0;i<2;i++){
			card_img2[i] = new BitmapDrawable(
					Bitmap.createBitmap(img,i*(img.getWidth()/2),0,
							img.getWidth()/2,img.getHeight()));
		}

		for(int i=0;i<MAX_MAISUU;i++){
			card.add(new Card(disp_w,disp_h));//カードをオブジェクト登録
			card.get(i).Cardinit(card_img[i],card_img2[1], 0, 0, 70, 105);//カードを初期設定
			card.get(i).setCardRect(card_xy[i]);
		}
		for(int i=0;i<SYURUI;i++){
			for(int j=0;j<MAISUU;j++){
				card.get(j+i*MAISUU).setCardEl(j+1, i);
			}}
		Syokika();

		//初期化ここまで

	}
	//クリア後ここを呼び出せばリスタート
	private void Syokika(){
		for(int i=0;i<MAX_MAISUU;i++){
			card.get(i).setCardDraw(true);
			card.get(i).setObjState(1);
		}
		Shuffle();
	}

	//カードシャッフル処理
	public void Shuffle(){
		Random r = new Random(new Date().getTime());
		Rect c = new Rect();
		for(int i=0;i<1000;i++){
			int a = r.nextInt(MAX_MAISUU);
			int b = r.nextInt(MAX_MAISUU);
			c = card_xy[a];
			card_xy[a] = card_xy[b];
			card_xy[b] = c;
		}
		for(int i=0;i<MAX_MAISUU;i++){
			card.get(i).setCardRect(card_xy[i]);
		}
	}

	//メインループ
	public void run() {
		Canvas c;
		Paint p = new Paint();
		p.setAntiAlias(true);

		while(thread != null){
			c = holder.lockCanvas();

			//ゲーム状態によってスイッチ処理
			switch(game_state){
			case GAME_START:
				StartDraw(c,p);
				break;
			case GAME_PLAY:
				PlayDraw(c,p);
				break;
			case GAME_CLEAR:
				drawString("GAME CLEAR!",10,200,60,Color.BLUE,c,p);
				break;
			}
			holder.unlockCanvasAndPost(c);

			try {
				Thread.sleep(sleep);
			} catch (Exception e){}
		}
	}
	//タッチ処理
	public boolean onTouchEvent(MotionEvent event){
		int action = event.getAction();
		int x = (int)event.getX();
		int y = (int)event.getY();
		switch(action){
		case MotionEvent.ACTION_DOWN:
			switch(game_state){
			case GAME_START:
				break;
			case GAME_PLAY:
				if(tap_tap==false)RectTap(x,y);
				break;
			case GAME_CLEAR:
				Syokika();
				game_state=1;
				break;
			}
			break;
		case MotionEvent.ACTION_UP:
			switch(game_state){
			case GAME_START:
				break;
			case GAME_PLAY:
				break;
			}
			break;
		case MotionEvent.ACTION_MOVE:
			switch(game_state){
			case GAME_START:
				break;
			case GAME_PLAY:
				break;
			}
			break;
		}
		return true;
	}

	//タップ位置をカード位置比較用、範囲内ならtrue
	public boolean RectTap(int x,int y,Rect gazou){
		return gazou.left < x && gazou.top < y && gazou.right > x && gazou.bottom > y;
	}

	//今回は未使用
	public void StartDraw(Canvas c,Paint p){
	}
	//game_stateが1ならここをループ
	public void PlayDraw(Canvas c,Paint p){
		//プレイ画面表示
		//背景表示黒く塗りつぶすだけ
		buck.Rectdraw(c, p);

		//カード52枚表示
		for(int i=0;i<card.size();i++){
			card.get(i).Carddraw(c, p);
		}
		//カードをタップすると短形表示
		if(tap_rect == true){
			tap.Rectdraw(c, p);
		}
		//2枚目タップしていればカウント+1
		if(tap_tap==true) ++hantei_count;
		//2枚目タップしててカウントが5になれば判定
		//ここで2枚めくったらすぐ消えたりするのを防いでいます
		if(tap_tap==true && hantei_count == 5){
			Hantei();hantei_count=0;
			//52枚めくれたらクリア
			if(card_count == 52) game_state = 2;
		}

	}
	//タップした時の処理
	public void RectTap(int x,int y){
		//すでにタップしていて同じカードをタップした場合
		if(RectTap(x,y,tap_rect_old) == true){
			tap_rect = false;
			tap_rect_old = new Rect(0,0,0,0);
			card.get(tap_one).setObjState(1);
			}else
		//始めてカードをタップした場合
		if(tap_rect == false){
			for(int i=0;i<card.size();i++){
				if(card.get(i).getCardDraw() == true && RectTap(x,y,card.get(i).getCardRect()) == true){
					tap.getsetCardRect(card.get(i).getCardRect());
					tap_rect_old = card.get(i).getCardRect();
					tap_rect = true;
					card.get(i).setObjState(0);
					tap_one = i;
				}
			}
		}else
		//2枚目のカードをタップした場合
		if(tap_rect == true){
			for(int i=0;i<card.size();i++){
				if(card.get(i).getCardDraw() == true && tap_tap == false && tap_one != i &&
						RectTap(x,y,card.get(i).getCardRect()) == true){
					tap.getsetCardRect(card.get(i).getCardRect());
					card.get(i).setObjState(0);
					tap_two = i;
					tap_tap=true;
				}
			}
		}
	}

	//二回目のタップの時だけ2枚の数字が同じか判定
	//同じならその2枚は表示させないようにする
	public void Hantei(){
		if(card.get(tap_one).getSuuji() == card.get(tap_two).getSuuji()){
			card.get(tap_one).setCardDraw(false);
			card.get(tap_two).setCardDraw(false);
			tap_tap = false;
			tap_rect = false;
			tap_rect_old = new Rect(0,0,0,0);
			card_count += 2;
		}else{
			card.get(tap_one).setObjState(1);
			card.get(tap_two).setObjState(1);
			tap_tap = false;
			tap_rect = false;
			tap_rect_old = new Rect(0,0,0,0);
		}
	}
	//テスト表示用
	public void drawString(String str,int x,int y,int size,int col,Canvas c,Paint p){
		p.setColor(col);
		p.setTextSize(size);
		c.drawText(str, x, y, p);
	}

	public void setSleep(int s){sleep=s;}
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {}

	public void surfaceCreated(SurfaceHolder arg0) {thread = new Thread(this);thread.start();}

	public void surfaceDestroyed(SurfaceHolder arg0) {thread = null;}
}




						                        
 

ここが心臓部となっています。別のファイルでまとめてみる練習とかしてみてもいいかもしれないくらい、心臓部はコードが短いです。

タップした時になにかするだけで他はなにもないですね。

 

ファイル名「Card.java」

package and.roid.tramp1;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;

public class Card {

	private double disp_w,disp_h;//ディスプレイ大きさ

	public float px,py;	//オブジェクト座標
	private int w,h;	//オブジェクトの横幅縦幅
	private Rect rect;	//オブジェクトのRect
	private int alpha;	//オブジェクトの透過度
	private int objs_state;//カード表示裏か表か
	private int col;//オブジェクトカラー
	private Drawable[] obj = new Drawable[2];//カード画像、表、裏
	private int suuji,syurui;//カード数字と種類
	private boolean card_draw = true;//カードを表示させるかどうか

	//コンストラクタ
	public Card(){}
	public Card(double ww,double hh){
		disp_w = ww;disp_h=hh;
	}

	//カード初期化
	public void Cardinit(Drawable img, Drawable img2,float px,float py,int w, int h){
		this.obj[0] = img;
		this.obj[1] = img2;
		this.px = px;
		this.py = py;
		this.w = w;
		this.h = h;
		objs_state = 1;
		setgetDrawableSize();

	}
	//カードに数字と種類の要素代入
	public void setCardEl(int suu,int syu){
		suuji = suu;
		syurui = syu;
	}
	//カード表示
	public void Carddraw(Canvas c,Paint p){
		if(card_draw == true){
		rect = new Rect((int)(px), (int)(py), (int)(px+w), (int)(py+h));
		obj[objs_state].setBounds(rect);
		obj[objs_state].draw(c);
		}
	}
	//短形初期化
	public void Rectinit(float px,float py,int w, int h,int col,int al){
		this.px = px;
		this.py = py;
		this.w = w;
		this.h = h;
		this.col = col;
		this.alpha = al;
		setgetDrawableSize();
		rect = new Rect((int)(px), (int)(py), (int)(px+w), (int)(py+h));
	}
	//短形表示
	public void Rectdraw(Canvas c,Paint p){
		p.setColor(col);
		p.setAlpha(alpha);
		c.drawRect(rect, p);
	}
	//カード座標代入
	public void setCardRect(Rect rect1){
		px = rect1.left;
		py = rect1.top;
		w = rect1.right;
		h = rect1.bottom;
		setgetDrawableSize();
	}
	public boolean getCardDraw(){return card_draw;}
	public void setCardDraw(boolean t){card_draw=t;}
	public int getSuuji(){return suuji;}
	public void setObjState(int o){objs_state = o;}
	public void getsetCardRect(Rect rect1){rect = rect1;}
	public Rect getCardRect(){return rect;}
	//テスト用
	public void drawString(String str,int x,int y,int size,int col,Canvas c,Paint p){
		p.setColor(col);
		p.setTextSize(size);
		c.drawText(str, x, y, p);
	}
	//どのスマホの機種でもうまく表示出来るように、座標変換
	public void setgetDrawableSize(){
		double dw = disp_w / 854f;
		double dh = disp_h / 480f;

		px *= dw;
		py *= dh;
		w *= dw;
		h *= dh;
	}
}



						
 

Cardクラスです。

今回はカードというオブジェクトと、色付きの四角短形しか使用しないので一緒にしました。

やっぱり、オブジェクト的なクラスを考えて作成しているときがわたしはなぜか楽しいです。

 
実行結果

1枚目タップして、もう一度同じカードをタップすると選択のキャンセルができます。なので全部見ることができちゃいます。その仕様もそのメソッドだけ消してしまえばできなくなります。

一応、ゲームになってはいるのですが問題点がたくさんあります。

1、表示がなぜか重い。よく見るとちょっとカード画像がぼやけていますよね。当初、画像の大きさは52枚で1950×750くらいあったのですがエラーが出まして、やむなく縮小しました。もうちょっとそのあたりの仕様をしっかり把握しないといけないみたいです。

2、反応がちょっと遅い。これのおかげでループ遅延のsleepを0にしてみています。しかしそれでもちょっと重い感じです。軽快な動作にする工夫などが今後の課題ですね。

 

 
 

 

 

 

Androidプログラミング日記 (仮) | サイトマップ | 個人情報保護方針 | 応援メールテヘペロ | ©2012 Japan  相互リンク大募集中です