ページ 11

Android:イライラ棒をレイアウトにはめ込む

Posted: 2013年7月07日(日) 20:09
by (略して)将軍
新しくいい所を見つけてお世話になってます、(略して)将軍と申します
最近SurfaceVIewを使っておらず、改めて勉強しなおそうとイライラ棒作り始めました
書いてあることそのままにやってみて、上手い具合に動き始めたのですが
出来たものを、xmlのレイアウトにはめ込もうとするとsetcontentviewでエラーを吐かれてしまいます
以前作った物は、ちゃんと動いているのですが……これって、レイアウトにはめ込めるのでしょうか?
・アクティビティ

コード:

package syougun.pack.pantschecker;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;


public class MainActivity extends Activity {


	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//setContentView( new PantsView(this) );  //こちらはきちんと動作する
		setContentView( R.layout.activity_main );
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_main, menu);
		return true;
	}

}

・レイアウト

コード:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <syougun.pack.pantschecker.PantsView
        android:id="@+id/MainSurfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#000000" />

</RelativeLayout>

Re: Android:イライラ棒をレイアウトにはめ込む

Posted: 2013年7月07日(日) 22:52
by ISLe
Viewを継承した自作クラスをレイアウトに使用すること自体は可能ですが。
エラーを吐くとはどんなエラーですか。

Re: Android:イライラ棒をレイアウトにはめ込む

Posted: 2013年7月07日(日) 23:03
by (略して)将軍
返信どうもありがとうございます。
エラーの内容ですが、強制終了してアプリが『予期せず停止しました。やりなおしてください』【強制終了】と出ます。
自作ビューの名前、パッケージ名も確認したのですが、アクティビティとレイアウト以外に、弄っておく箇所等はあるのでしょうか?

Re: Android:イライラ棒をレイアウトにはめ込む

Posted: 2013年7月08日(月) 00:04
by ISLe
それはsetContentViewのエラーではないと思いますが。
デバッガで強制終了する箇所までトレースすれば根本原因が分かるのではないでしょうか。

このサイトのイライラ棒を元にしているのですよね。
想像ですが、ContextをActivityにキャストして使っている箇所で落ちているかもしれません。

Re: Android:イライラ棒をレイアウトにはめ込む

Posted: 2013年7月08日(月) 00:33
by (略して)将軍
普通にやると、setContentViewで止まってしまうので、ここから先が終えない状況なのですね……

コード:

	public GameView(Context context, AttributeSet attrs) {
		super(context, attrs);
             }
コンストラクタにこっちを加えると通るのですが、スレッドはしらなくなってしまうんですよね……結果、何も表示されず……
Viewは、以下の通りになります、なおイライラ棒の再序盤だけベースにしている練習用の為、中身は大幅に異なります。

コード:


package syougun.pack.pantschecker;

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.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

class PantsView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
        Thread _thread;

        //ランダム関数
    	Random rnd = new Random();

    	int score;
        int width;
        int height;

        int level;
        int Scene;
        int count;
        Rect back_rect;
        Rect logo_rect;
        Rect chara_rect[] = new Rect[5];
        Bitmap logo;
        Bitmap back;
        Bitmap chara[] = new Bitmap[5];
        Bitmap cloth;
        Bitmap pants;
        int pants_alpha;
        int pants_hit;

        public PantsView(Context context) {
            super(context);
            Init(context);
        }


        void Init(Context context) {
                getHolder().addCallback(this);
                Resources r = context.getResources();
                logo = BitmapFactory.decodeResource(r,R.drawable.logo);
                back = BitmapFactory.decodeResource(r,R.drawable.schoolgate);
                pants = BitmapFactory.decodeResource(r,R.drawable.pants_00);
                cloth = BitmapFactory.decodeResource(r,R.drawable.pants_99);
                chara[0] = BitmapFactory.decodeResource(r,R.drawable.pants_01);
                chara[1] = BitmapFactory.decodeResource(r,R.drawable.pants_02);
                chara[2] = BitmapFactory.decodeResource(r,R.drawable.pants_03);
                chara[3] = BitmapFactory.decodeResource(r,R.drawable.pants_04);
                chara[4] = BitmapFactory.decodeResource(r,R.drawable.pants_05);
                pants_hit = rnd.nextInt(5);
                pants_alpha = 255;
                Scene = 0;
                count = 60;
                level = 0;
                score = 0;
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                //解像度情報変更通知
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
                _thread = new Thread(this);             //別スレッドでメインループを作る
                _thread.start();
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
                _thread = null;
        }

    	//視点変更
    	@Override
    	public void onWindowFocusChanged(boolean hasFocus) {
    		super.onWindowFocusChanged(hasFocus);
    		width = this.getWidth();
    		height = this.getHeight();

    		int l_width = height * 9 / 10;

    		back_rect = new Rect(0,0,width,height);

    		logo_rect = new Rect(width / 2 - l_width,0,width / 2 + l_width ,height);
    		int c_width = height / 3;
    		for(int i = 0; i < 5; i++) {
    			chara_rect[i] = new Rect(width * (i + 1) / 6 - c_width / 2, 0, width * (i + 1) / 6  + c_width / 2, height);
    		}

    	}

        @Override
        public void run() {
                while (_thread!=null) { //メインループ
                	manager();
                    onDraw(getHolder());
                }
        }

        void manager() {
        	int down = 8;
        	switch(Scene) {
        	//スタート待機
        	case 1:
        		count--;
        		if(count <= 0) {
        			Scene = 2;
        			pants_hit = rnd.nextInt(5);
        			pants_alpha = 255;
        		}
        		break;
        	//スカートめくり
        	case 2:
        		switch(level) {
        		case 0:
        			down = 8;
        			break;
        		}

        		pants_alpha -= down;
        		if(pants_alpha <= 0) {
        			pants_alpha = 0;
        			count = 60;
        			Scene = 3;
        		}
        		break;
        	//パンツ選択
        	case 3:
        		count--;
        		if(count <= 0) {
        			Scene = 6;
        		}
        		break;
        	//当たり
        	case 4:
        		count--;
        		if(count <= 0) {
        			Scene = 5;
        		}
        		break;
        	//スカート直し
        	case 5:
        		switch(level) {
        		case 0:
        			down = 8;
        			break;
        		}
        		pants_alpha += down;
        		if(pants_alpha >= 255) {
        			pants_alpha = 255;
        			pants_hit = rnd.nextInt(5);
        			Scene = 2;
        		}
        		break;
        	//ゲームオーバー
        	case 6:

        		break;

        	}
        }



    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    		int touch_x = (int) event.getX(), touch_y = (int) event.getY();
    		switch (event.getAction()) {
    			case MotionEvent.ACTION_DOWN:
    				switch(Scene) {
    				//ロゴ
    				case 0:
    					score = 0;
    					count = 60;
    					Scene = 1;
    					break;
    				case 3:
    					for(int i = 0; i < 5; i++) {
    						if(Hit(touch_x, touch_y, chara_rect[i])) {
    							if(i == pants_hit ) {
    								Scene = 4;
    								count = 60;
    								score++;
    							}
    							else {
    								Scene = 6;
    							}
    							break;
    						}
    					}
    					break;
    				}
    		}
    		return true;
    	}

    	boolean Hit(int x, int y, Rect rect) {
    		if(y > rect.top && y < rect.bottom &&
    			x > rect.left && x < rect.right) {
    			return true;
    		}
    		return false;
    	}




        private void onDraw(SurfaceHolder holder) {
                Canvas c = holder.lockCanvas();
                Paint p = new Paint();
                c.drawColor(Color.BLUE);
                p.setAlpha(255);
                c.drawBitmap(back, null, back_rect, p);
                draw_manager(c,p);

                //ここにゲームの描画処理を書く
                holder.unlockCanvasAndPost(c);
        }

        void draw_manager(Canvas c, Paint p) {
        	switch(Scene) {
        		//ロゴ表示
        		case 0:
        			p.setAlpha(255);
        			draw_logo(c,p);
        			break;
        		//スタート待機
        		case 1:
        		//スカートめくり
        		case 2:
        		//パンツ選択
        		case 3:
        		//当たり
        		case 4:
        		//スカート直し
        		case 5:
           		//ゲームオーバー
           		case 6:
        			draw_chara(c,p);
        			break;
        	}

        }


        void draw_chara(Canvas c, Paint p) {
            for(int i = 0; i < 5; i++) {
            	p.setAlpha(255);
            	c.drawBitmap(chara[i], null, chara_rect[i], p);
            	if(pants_hit == i) {
            		c.drawBitmap(pants, null, chara_rect[i], p);
            	}
            	p.setAlpha(pants_alpha);
            	c.drawBitmap(cloth, null, chara_rect[i], p);
            	//p.setAlpha(128);
            	//c.drawRect(chara_rect[i], p);
            }
        }

        void draw_logo(Canvas c, Paint p) {
            c.drawBitmap(logo, null, logo_rect, p);
        }


}

Re: Android:イライラ棒をレイアウトにはめ込む

Posted: 2013年7月08日(月) 01:31
by ISLe
(略して)将軍 さんが書きました:コンストラクタにこっちを加えると通るのですが、スレッドはしらなくなってしまうんですよね……結果、何も表示されず……
それだけでは強制終了にならないですよね。
(略して)将軍 さんが書きました:Viewは、以下の通りになります、なおイライラ棒の再序盤だけベースにしている練習用の為、中身は大幅に異なります。
onWindowFocusChangedメソッドってActivityでオーバーライドするものでは。
SurfaceViewを継承したクラスで@Override付けてコンパイル通らない気がするのですが。

適当にいじってる感がビンビンしますが、getWidth()やgetHeight()が0を返して0除算で強制終了している可能性が高いですかね。
デバッガに例外の内容が出力されると思うのですが。

幅や高さが欲しかったらsurfaceChangedを使えば良いと思います。
あるいは、SurfaceHolder#lockCanvasからのCanvas#getWidth/Canvas#getHeight。

Re: Android:イライラ棒をレイアウトにはめ込む

Posted: 2013年7月08日(月) 10:24
by (略して)将軍
以前からの知識継ぎ足して使っているので、ご指摘等いただけるのはありがたいです、どうもありがとうございます。
ただ、アクティビティのsetContentViewのコメントアウトしてある方はキチンと通るので、縦幅、横幅が取れてないという事は無いと思うんですね

コード:

        public PantsView(Context context, AttributeSet attrs) {
        	super(context, attrs);
        	getHolder().addCallback(this);
        	Init(context);
        }
コンストラクタにこっちを付け加えると、プログラムは動くのですが今度は画像が表示されなくなると言う状態に陥っております
lockCanvas関連もちゃんとしてますし、レイアウトもきちんと配置されているはずなのですが、どこがおかしいのでしょうか?

Re: Android:イライラ棒をレイアウトにはめ込む

Posted: 2013年7月08日(月) 16:52
by ISLe
思うだけでなく、デバッガできちんと確認すべきではないでしょうか。
最終的なアプリの強制終了に至るまでにメソッドが例外で中断している可能性もあります。

描画されないのなら、ブレークポイントを使って描画している箇所で止めて、パラメータが正しいか検証してください。
Bitmapへの参照が正しいか、Rectの中身が正しいか、確認してください。