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

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

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

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

Java

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

Android

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

Q&A

解決済

1回答

1406閲覧

android studio ボタンを押してキャラクターを左右に移動させたい

entd270

総合スコア19

XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

Java

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

Android

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

0グッド

1クリップ

投稿2019/05/09 07:45

前提・実現したいこと

ボタンを押すことでキャラクターを動かしたいです。
以前まではViewを用いて、キャラクタの描画をしていたのですが、キャラクターの高速描画のためにSurfaceViewを利用することにしました。SurfaceViewについて勉強しているのですが、どうしてもクリックでSurfaceViewの更新をするやり方がわかりません。自分でも、色々調べてみたのですが、解決できなかったので、質問させてください。

xml

1<RelativeLayout 2 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 xmlns:app="http://schemas.android.com/apk/res-auto" 5 xmlns:tools="http://schemas.android.com/tools" 6 android:layout_width="match_parent" 7 android:layout_height="match_parent" 8 tools:context=".MainActivity"> 9 10 <ImageButton //左ボタン 11 android:id="@+id/imageButtonLeft" 12 android:layout_width="wrap_content" 13 android:layout_height="wrap_content" 14 android:layout_alignParentLeft="true" 15 android:layout_alignParentBottom="true" 16 android:layout_marginLeft="12dp" 17 app:srcCompat="@drawable/left" /> 18 19 <ImageButton //右ボタン 20 android:id="@+id/imageButtonRight" 21 android:layout_width="wrap_content" 22 android:layout_height="wrap_content" 23 app:srcCompat="@drawable/right" 24 android:layout_alignParentBottom="true" 25 android:layout_centerVertical="true" 26 android:layout_marginLeft="15dp" 27 android:layout_toRightOf="@+id/imageButtonLeft"/> 28 29 <ImageButton //ジャンプボタン 30 android:id="@+id/imageButtonTop" 31 android:layout_width="wrap_content" 32 android:layout_height="wrap_content" 33 app:srcCompat="@drawable/top" 34 android:layout_alignParentRight="true" 35 android:layout_alignParentBottom="true" 36 android:layout_marginRight="15dp"/> 37 38</RelativeLayout> 39

java

1//MainActivity 2package com.example.test; 3 4import android.support.v7.app.AppCompatActivity; 5import android.os.Bundle; 6 7import android.view.View; 8import android.view.ViewGroup; 9import android.widget.ImageButton; 10import android.widget.LinearLayout; 11import android.view.View.OnClickListener; 12 13public class MainActivity extends AppCompatActivity { 14 15 private GameView gameView; 16 private Droid droid; 17 18 @Override 19 protected void onCreate(Bundle savedInstanceState) { 20 super.onCreate(savedInstanceState); 21 22 gameView = new GameView(this); 23 setContentView(gameView);//画面にgameViewを配置 24 View view = this.getLayoutInflater().inflate(R.layout.activity_main, null); 25 26 addContentView(view, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, 27 ViewGroup.LayoutParams.FILL_PARENT));//activity_mainのviewを重ねて配置 28 29 ImageButton imageButton = (ImageButton) findViewById(R.id.imageButtonRight); 30 31 imageButton.setOnClickListener(new OnClickListener() { 32 @Override 33 public void onClick(View v) { 34 //droid.move(); 35 } 36 }); 37 LongClickRepeatAdapter.bless(imageButton);//自動でクリック動作を繰り返す 38 } 39 } 40 41

xml

1//ゲーム画面の設定 2 3package com.example.test; 4 5import android.content.Context; 6import android.graphics.Bitmap; 7import android.graphics.BitmapFactory; 8import android.graphics.Canvas; 9import android.graphics.Color; 10import android.view.SurfaceHolder; 11import android.view.SurfaceView; 12 13 14import java.util.concurrent.atomic.AtomicBoolean; 15 16public class GameView extends SurfaceView implements SurfaceHolder.Callback { 17 private static final long DRAW_INTERVAL = 1000 / 100;//描画と描画の間隔 18 19 private class DrawThread extends Thread {//描画用のサブスレッド 20 21 private final AtomicBoolean isFinished = new AtomicBoolean(false); 22 23 public void finish() { 24 isFinished.set(true); 25 } 26 27 @Override 28 public void run() { 29 SurfaceHolder holder = getHolder(); //SurfaceHolderオブジェクトを取得 30 31 while (!isFinished.get()) { //DrawThreadは、isFinishedがtrueになるまで、描画処理を行う 32 33 if (holder.isCreating()) { 34 continue; 35 } 36 37 Canvas canvas = holder.lockCanvas(); //描画用のCanvasオブジェクトを取得する 38 39 if (canvas == null) { 40 continue; 41 } 42 43 drawGame(canvas); 44 45 /*Canvasオブジェクトに描画した後、unlockCanvasAndPostを 46 実行することで実際に画面に反映する*/ 47 holder.unlockCanvasAndPost(canvas); 48 49 synchronized (this) { 50 try { 51 wait(DRAW_INTERVAL); 52 } catch (InterruptedException e) { 53 } 54 } 55 } 56 } 57 } 58 59 private DrawThread drawThread; 60 61 public void startDrawThread() {//DrawThreadを開始する 62 stopDrawThread(); 63 64 drawThread = new DrawThread(); 65 drawThread.start(); 66 67 } 68 69 public boolean stopDrawThread() {//DrawThreadを停止する 70 if (drawThread == null) { 71 return false; 72 } 73 drawThread.finish(); 74 drawThread = null; 75 76 return true; 77 } 78 79 80 @Override 81 public void surfaceCreated(SurfaceHolder holder) { 82 } 83 84 /*SurfaceViewの描画タイミングに合わせて描画用のスレッドを開始する*/ 85 //startDrawThreadメソッドを呼び出す 86 @Override 87 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 88 startDrawThread(); 89 } 90 91 //stopDrawThreadメソッドを呼び出す 92 @Override 93 public void surfaceDestroyed(SurfaceHolder holder) { 94 stopDrawThread(); 95 } 96 97 private Bitmap droidBitmap; 98 private Droid droid; 99 100 public GameView(Context context){ 101 super(context); 102 103 droidBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.droid100);// キャラクター画像を設定 104 droid = new Droid(droidBitmap,0,600/*,droidCallback*/);//キャラクターの初期位置 105 106 getHolder().addCallback(this);//SurfaceHolderを初期化する 107 } 108 109 private void drawGame(Canvas canvas){ 110 canvas.drawColor(Color.WHITE);//白く塗りつぶして初期化 111 //droid.move(); 112 ground.draw(canvas); 113 droid.draw(canvas); 114 } 115} 116

java

1//キャラクターの設定 2 3package com.example.test; 4 5import android.graphics.Bitmap; 6import android.graphics.Canvas; 7import android.graphics.Paint; 8import android.graphics.Rect; 9 10public class Droid { 11 12 private final Paint paint = new Paint(); 13 14 public interface Callback {//インターフェース 15 int getDistanceFromGround(Droid droid); 16 } 17 18 final Rect rect; 19 final Rect hitRect; 20 21 private Bitmap bitmap; 22 23 public Rect getRect(){ 24 return this.rect; 25 } 26 27 public Droid(Bitmap bitmap,int left,int top){ 28 this.bitmap = bitmap; 29 int right = left + bitmap.getWidth(); 30 int bottom= top + bitmap.getHeight(); 31 this.rect = new Rect(left,top,right,bottom); 32 this.hitRect = new Rect(left,top,right,bottom); 33 this.hitRect.left += HIT_MARGIN_LEFT; 34 this.hitRect.right -= HIT_MARGIN_RIGHT; 35 } 36 37 public void draw(Canvas canvas){ 38 canvas.drawBitmap(bitmap,rect.left,rect.top,paint); 39 } 40 41 public void move(){ 42 rect.offset(10,0); 43 } 44} 45

試したこと

私のイメージでは、MainActivityで下記のようにすることで、クリック時にキャラクターを移動させたいのです。

@Override public void onClick(View v) {   droid.move(); }

しかし上記では、画面は表示されるのですが、クリックすると、強制終了してしまいます。
3日ほどここから進めずいます。アドバイスをいただけないでしょうか。

一部不必要かと思ったjavaファイルはあげてませんが、必要なら追記するのでおっしゃってください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

droid が初期化されていないので、ヌルポで落ちると思います。
Logcat と言うのがあるので確認してみてください。

あと、コンパイル時に droid が初期化されずに使われてる的なワーニングが出ていても無視してるのではないでしょうか?

投稿2019/05/09 07:57

kamikaze.cappa

総合スコア558

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

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

entd270

2019/05/09 08:29

ご回答ありがとうございます。 Logcatを確認してみた所、おっしゃる通りでした。下記のように表示されました。 java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.test.Droid.move()' on a null object reference at com.example.test.MainActivity$1.onClick(MainActivity.java:33) MainActivityでGameViewのインスタンスを生成した時にdroidの初期化は行われないのでしょうか。知識不足で申し訳ありません。
kamikaze.cappa

2019/05/09 08:52

ソースを見る限り、個別の初期化が必要です。
entd270

2019/05/09 09:09

ご回答ありがとうございます。 個別に初期化というのは、具体的にどのように行えば良いのでしょうか。 MainActivityでも、GameViewと同じように、Droidクラスのコンストラクタを呼び出せば良いのでしょうか。
entd270

2019/05/09 09:44

ご回答ありがとうございます。 早速、MainActivityで下記のように初期化しました。 droidBitmap = gameView.getDroidBitmap(); droid = new Droid(droidBitmap,0,600); ボタンを押しても、ヌルポで強制終了することはなくなったのですが、 キャラクターは移動しませんでした。 何が問題なのでしょうか。なんども申し訳ありません。
entd270

2019/05/10 04:05

ご回答ありがとうございます。 MainActivityの中から、GameViewのrunメソッドの中で取得しているCanvasに対して、drawするようにしようとしたのですが、うまく行きませんでした。 クリックに応じてcanvasにdrawするには、具体的にどのように行なえば良いのでしょうか。
kamikaze.cappa

2019/05/10 04:25

ざっとソースをみた感じだと startDrawThread() の呼び出しを surfaceChanged では無く surfaceCreated のタイミングに変更しても変わらないでしょうか?
entd270

2019/05/10 04:49

startDrawThread()の呼び出しを surfaceCreatedに移動してもm、キャラクターの移動は描画されませんでした...。
kamikaze.cappa

2019/05/10 05:58

わかりました。 MainActivity で Droid を参照していましたが、その値をムーブ(変更)しても移動しません。 実際の Driod の表示をつかさどる変数は、GameView で宣言されています。 なので、GameView 内の droid 変数に対して move するメソッドをつくるか Move のインターフェイスを変更する必要があります。 最初に初期化していない droid にアクセスしていたので、初期化が必要だと説明しましたが 実は、アクセスする変数が違っていたのだとおもいます。 アクセスすべきは、GameView の中で宣言された droid 変数です。
entd270

2019/05/10 09:10

おっしゃる通り、GameViewで宣言したdroidに対してのmoveメソッドを作成して、MainActityのonclickメソッドの中で呼び出したところ、ちゃんと、キャラクターが移動しました!!ご丁寧に教えてくださり、本当にありがとうございました。本当に助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問