質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

2回答

4385閲覧

android テトリス ブロックの操作

cray

総合スコア29

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2016/06/10 04:46

テトリスのアプリを作成しています。

現在はパソコンのキーボードでブロックを操作しているのですが、キーボード操作ではなくボタン操作に変更したいと考えています。
ボタンを取り付け、onClickメソッドを記述して試してみたのですが、ボタンを押しても反応がありません。

以下ソースコードです

public class MainActivity extends AppCompatActivity { private class FieldView extends SurfaceView implements View.OnClickListener{ Random mRand = new Random(System.currentTimeMillis()); int[][][] blocks = { //省略 }; int[][] block = blocks[mRand.nextInt(blocks.length)]; int block1[][] = blocks[mRand.nextInt(blocks.length)]; int posx = 4, posy; int mapWidth = 10; int mapHeight = 20; int count = 0; int[][] map = new int[mapHeight][]; int[][] next = new int[mapHeight][]; public FieldView(Context context) { super(context); setBackgroundColor(0xFFFFFFFF); setFocusable(true); setFocusableInTouchMode(true); requestFocus(); } public void initGame() { //省略 盤面を作ったりの処理 } void gameover() { for (int i = 0; i < 10 ; i++) { if (map[0][i] != 0) { Log.d("i=","" +i); count = 1; } } } private void paintMatrix(Canvas canvas, int[][] matrix, int offsetx, int offsety, int color) { //省略 ブロックに形をつける } boolean check(int[][] block, int offsetx, int offsety) { //省略 ブロックが存在していいかどうか判別 } void mergeMatrix(int[][] block, int offsetx, int offsety) { //ブロックをマップ上に表示 } void mergeMatrix1(int[][] block, int offsetx, int offsety) { //次落ちてくるブロックを指定位置に表示 } void clearRows() { //一列そろったら消す処理 } @Override protected void onDraw(Canvas canvas) { //盤面などに色を付ける } int[][] rotate(final int[][] block) { //ブロックの回転処理 } @Override //ボタンを押したときの処理 public void onClick(View v) { switch (v.getId()) { case R.id.ch: Log.d("ch","push"); int[][] newBlock = rotate(block); if (check(newBlock, posx, posy)) { block = newBlock; } break; case R.id.right: if (check(block, posx + 1, posy)) { posx = posx + 1; } break; case R.id.left: if (check(block, posx - 1, posy)) { posx = posx - 1; } break; case R.id.end: int y = posy; while (check(block, posx, y)) { y++; } if (y > 0) posy = y - 1; break; case R.id.sita: if (check(block, posx, posy + 1)) { posy = posy + 1; } break; } mHandler.sendEmptyMessage(INVALIDATE); } public void startAnime() { mHandler.sendEmptyMessage(INVALIDATE); mHandler.sendEmptyMessage(DROPBLOCK); } public void stopAnime() { mHandler.removeMessages(INVALIDATE); mHandler.removeMessages(DROPBLOCK); } private static final int INVALIDATE = 1; private static final int DROPBLOCK = 2; //時間経過でブロックを落とす private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { if (count == 0) { switch (msg.what) { case INVALIDATE: invalidate(); break; case DROPBLOCK: if (check(block, posx, posy + 1)) { posy++; } else { mergeMatrix(block, posx, posy); clearRows(); posx = 4; posy = 0; block = block1; block1 = blocks[mRand.nextInt(blocks.length)]; mergeMatrix1(block1, 0, 0); } invalidate(); Message massage = new Message(); massage.what = DROPBLOCK; sendMessageDelayed(massage, 500); break; } } } }; } FieldView mFieldView; @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.start); Button btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mFieldView == null) { setContentView(R.layout.activity_main); mFieldView = new FieldView(getApplication()); LinearLayout lay = (LinearLayout) findViewById(R.id.lay); lay.addView(mFieldView); setFieldView(); mFieldView.initGame(); mFieldView.startAnime(); Looper.myQueue().addIdleHandler(new Idler()); } } }); } // Allow the activity to go idle before its animation starts class Idler implements MessageQueue.IdleHandler { public Idler() { super(); } public final boolean queueIdle() { return false; } } }

となっています。ボタンのidはそれぞれch、left等割り振っています。

ボタンを押しても動作しないのですがなぜでしょうか。

キーボード入力の時は普通に動作しました。

@Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_ENTER: int[][] newBlock = rotate(block); if (check(newBlock, posx, posy)) { block = newBlock; } break; case KeyEvent.KEYCODE_D: if (check(block, posx + 1, posy)) { posx = posx + 1; } break; case KeyEvent.KEYCODE_A: if (check(block, posx - 1, posy)) { posx = posx - 1; } break; case KeyEvent.KEYCODE_W: int y = posy; while (check(block, posx, y)) { y++; } if (y > 0) posy = y - 1; break; case KeyEvent.KEYCODE_S: if (check(block, posx, posy + 1)) { posy = posy + 1; } break; } mHandler.sendEmptyMessage(INVALIDATE); return true; }

onClickの部分を上記に変更するとキーボードで操作が可能でした。

なぜ動かないか教えていただけませんか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

クリックリスナーを実装しているだけでViewにセットしていないからだと思われます。
コンストラクタでsetOnClickListnerを行うと良いでしょう。

投稿2016/06/10 10:52

yona

総合スコア18155

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cray

2016/06/13 01:23

回答ありがとうございます!setContentViewで別のレイアウトを指定するとその指定されたレイアウトに含まれるボタンは機能しなくなる、というのが原因だったみたいです。 そこを調整したら治りました!ご回答ありがとうございました!
guest

0

ベストアンサー

元のソースコードはこちらでしょうか。
JavaScriptテトリスを移植してみた

独自に画面遷移後にゲーム画面を表示しようとしていると推測しますが、
setContentViewでレイアウトを変更する場合、以下の注意点があります。
1つのactivityに対し、複数のレイアウトを設定したい

ボタンを押したOnClickListenerの中で単純にsetContentViewで他方のXMLファイルのリソースを指定しても、最初の一発だけは切り替わりますが、新たに表示したレイアウトのボタンは機能せず、それ以上動かなくなります。inflateメソッドを使って取得したViewを用いてsetContentViewで表示を切り替え、さらにそのViewのメソッドとしてのfindViewByIdで切り替えたレイアウト側のボタンオブジェクトを用いることで、始めて切り替わった側のボタンのsetTextやsetOnClickListenerが機能するようになります。

上記を踏まえ、下記のように修正するとクリックイベントが取得できるようになります。

これを public void onClick(View v) { if (mFieldView == null) { setContentView(R.layout.activity_main); mFieldView = new FieldView(getApplication());
このように public void onClick(View v) { if (mFieldView == null) { LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = layoutInflater.inflate(R.layout.activity_main, null, false); setContentView(view); mFieldView = new FieldView(getApplication()); Button btn = (Button) view.findViewById(R.id.ch); btn.setOnClickListener(mFieldView); ...以下ボタン数分設定

投稿2016/06/10 07:44

dsuzuki

総合スコア1682

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cray

2016/06/13 02:05

ご回答ありがとうございます!おっしゃる通り、setCOntentViewで画面を切り替えていました。記載のコードに変更しましたら解決しました!ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問