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

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

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

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

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

837閲覧

Surfaceviewでゲームアプリを描画したいです!

dousuruyo

総合スコア74

Java

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

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2018/03/22 14:28

編集2018/03/24 10:53

前提・実現したいこと

個人でゲームアプリ開発をしたいと思っています
ゲーム開発の基礎を学ぶために、STGの基礎を作りたいと思いましたが、
ゲーム描画の基礎っていわれるsurfaceviewが描画できないです。。
何が原因か、思い当たる節がある場合はお願いします><

発生している問題・エラーメッセージ

前略 03-22 22:57:41.948 2571-2600/com.example.dousuruyo.shoot_game E/AndroidRuntime: FATAL EXCEPTION: Thread-4 Process: com.example.dousuruyo.shoot_game, PID: 2571 java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawColor(int)' on a null object reference at com.example.dousuruyo.shoot_game.MainLoop.run(MainLoop.java:101) at java.lang.Thread.run(Thread.java:761)

Javaソースコード

java

1package com.example.dousuruyo.shoot_game; 2 3import android.app.Activity; 4import android.graphics.PixelFormat; 5import android.graphics.Point; 6import android.os.Bundle; 7import android.view.Display; 8import android.view.Window; 9import android.view.WindowManager; 10 11import java.lang.reflect.Method; 12 13public class MainActivity extends Activity { 14 public float disp_w,disp_h; 15 public Point point; 16 @Override 17 /** 18 * フルスクリーン仕様にして画面の大きさを変数に収めてる格好 19 */ 20 protected void onCreate(Bundle savedInstanceState) { 21 super.onCreate(savedInstanceState); 22 requestWindowFeature(Window.FEATURE_NO_TITLE); 23 getWindow().setFormat(PixelFormat.TRANSLUCENT); 24 Window window = getWindow(); 25 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 26 WindowManager manager = window.getWindowManager(); 27 Display disp = manager.getDefaultDisplay(); 28 point = new Point(); 29 overrideGetSize(disp, point); 30 setContentView(new MainLoop(this)); 31 } 32 33 /** 34 * APIレベル13を基準としてディスプレイサイズの取り方が変わるので、それの対応 35 * @param display 36 * @param outSize 37 */ 38 void overrideGetSize(Display display, Point outSize) { 39 try { 40 // test for new method to trigger exception 41 Class pointClass = Class.forName("android.graphics.Point"); 42 Method newGetSize = Display.class.getMethod("getSize", new Class[]{ pointClass }); 43 44 // no exception, so new method is available, just use it 45 newGetSize.invoke(display, outSize); 46 } catch(NoSuchMethodException ex) { 47 // new method is not available, use the old ones 48 outSize.x = display.getWidth(); 49 outSize.y = display.getHeight(); 50 } catch (Exception e) { 51 e.printStackTrace(); 52 } 53 } 54 55 @Override 56 protected void onDestroy() { 57 super.onDestroy(); 58 Thread.interrupted(); 59 } 60} 61

java

1package com.example.dousuruyo.shoot_game; 2 3import android.content.Context; 4import android.content.res.Resources; 5import android.graphics.Bitmap; 6import android.graphics.BitmapFactory; 7import android.graphics.Canvas; 8import android.graphics.Color; 9import android.graphics.Paint; 10import android.graphics.drawable.Drawable; 11import android.util.AttributeSet; 12import android.view.MotionEvent; 13import android.view.SurfaceHolder; 14import android.view.SurfaceView; 15 16/** 17 * Created by dousuruyo on 2018/03/03. 18 */ 19 20public class MainLoop extends SurfaceView implements 21 SurfaceHolder.Callback,Runnable{ 22 private SurfaceHolder holder; //定型 23 private Thread thread; //定型 24 25 private MainActivity main; 26 private float disp_w,disp_h; 27 private Drawable jiki_img,tama_img; 28 private Object jiki; 29 30 /** 31 * 自前でview呼ぶ際 32 * @param context 33 */ 34 public MainLoop(Context context) { 35 super(context); 36 init(context); 37 } 38 39 /** 40 * xml方式でview呼ぶ際 41 * @param context 42 * @param attrs 43 */ 44 public MainLoop(Context context, AttributeSet attrs){ 45 super(context, attrs); 46 init(context); 47 } 48 49 /** 50 * 初期化ルーチン 51 */ 52 private void init(Context context) { 53 holder = getHolder(); //定型 54 holder.addCallback(this); //定型 55 holder.setFixedSize(getWidth(), getHeight()); //定型 56 main = (MainActivity)context; 57 disp_h = main.disp_h; 58 disp_w = main.disp_w; 59 60 Resources resources = context.getResources(); //画像登録準備 61 Bitmap img= BitmapFactory.decodeResource 62 (resources, R.drawable.suwako); //ビットマップで取得 63 // 画像分割 64 Bitmap jikibit = Bitmap.createBitmap(img,0,0,img.getWidth()/2,img.getHeight()); 65 Bitmap tamabit = Bitmap.createBitmap(img,img.getWidth()/2,0,img.getWidth()/2,img.getHeight()); 66 67 jiki = new Jiki(disp_w,disp_h); 68 jiki.Oint(resources,jikibit, 240, 800, 10, 10, jikibit.getWidth(), jikibit.getHeight()); 69 } 70 71 72 @Override 73 public void surfaceCreated(SurfaceHolder surfaceHolder) { 74 thread = new Thread(this); 75 thread.start(); 76 // 定型 77 } 78 79 @Override 80 public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { 81 // 定型 82 } 83 84 @Override 85 public void surfaceDestroyed(SurfaceHolder surfaceHolder) { 86 thread = null; 87 // 定型 88 } 89 90 /** 91 * メインループ 92 */ 93 @Override 94 public void run() { 95 Canvas c; 96 Paint p = new Paint(); 97 p.setAntiAlias(true); 98 99 while (thread != null){ 100 c = getHolder().lockCanvas(); //定型 101 c.drawColor(Color.YELLOW); 102 jiki.ODraw(c); 103 104 getHolder().unlockCanvasAndPost(c); //定型 105 106 try { 107 Thread.sleep(50); //定型 108 }catch (Exception e){} 109 } 110 } 111 112 public boolean onTouchEvent(MotionEvent event){ 113 int action = event.getAction(); 114 int x = (int)event.getX(); 115 int y = (int)event.getY(); 116 switch (action){ 117 case MotionEvent.ACTION_DOWN: 118 break; 119 case MotionEvent.ACTION_UP: 120 break; 121 } 122 return true; 123 } 124} 125

java

1package com.example.dousuruyo.shoot_game; /** 2 * Created by dousuruyo on 2018/03/11. 3 */ 4 5import android.graphics.Rect; 6 7/** 8 * 汎用的に使用するメソッド群クラス 9 */ 10public class CommonMethod { 11 static public final float ZERO = 0f; 12 13 /** 14 * 受け取ったxy座標と調べたい短形範囲が重なっているかいないか 15 * @param x 16 * @param y 17 * @param gazou 18 * @return 19 */ 20 public boolean RectTap(int x,int y,Rect gazou){ 21 return gazou.left < x && gazou.top < y && gazou.right > x && gazou.bottom > y; 22 } 23 24 public int setSizeX(float disp_w,float zahyou){return (int) (zahyou * (disp_w));} 25 public int setSizeY(float disp_h,float zahyou){return (int) (zahyou * (disp_h));} 26} 27

java

1package com.example.dousuruyo.shoot_game; 2 3import android.content.res.Resources; 4import android.graphics.Bitmap; 5import android.graphics.Canvas; 6import android.graphics.drawable.BitmapDrawable; 7import android.graphics.drawable.Drawable; 8 9/** 10 * Created by dousuruyo on 2018/03/11. 11 */ 12 13public abstract class Object { 14 private CommonMethod cm = new CommonMethod(); 15 private float disp_w,disp_h; 16 private Drawable img; //オブジェクトの画像 17 private float cx,cy; //オブジェクトの中心座標 18 private float vx,vy; //向かおうとしてる座標 19 private float spx,spy; //オブジェクトの移動スピード 20 private int imgw,imgh; //オブジェクトの大きさ 21 22 public Object(){} 23 public Object(float dw,float dh){ 24 disp_h = dh; 25 disp_w = dw; 26 } 27 28 public void Oint(Resources r,Bitmap imgb, float x, float y, float sx, float sy, int w, int h){ 29 img = new BitmapDrawable(r,imgb); 30 cx = cm.setSizeX(disp_w, x); 31 cy = cm.setSizeY(disp_h, y); 32 spx = sx; 33 spy = sy; 34 imgw = w; 35 imgh = h; 36 } 37 38 public void ODraw(Canvas c){ 39 img.setBounds((int)(cx-imgw/2),(int)(cy-imgh/2),(int)(cx+imgw/2),(int)(cy+imgh/2)); 40 img.draw(c); 41 } 42} 43

java

1package com.example.dousuruyo.shoot_game; 2 3/** 4 * Created by dousuruyo on 2018/03/11. 5 */ 6 7public class Jiki extends Object { 8 9 public Jiki(){} 10 public Jiki(float dw, float dh) { 11 super(dw, dh); 12 } 13} 14

xml

1<?xml version="1.0" encoding="utf-8"?> 2<android.support.constraint.ConstraintLayout 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="com.example.dousuruyo.shoot_game.MainActivity"> 9 10</android.support.constraint.ConstraintLayout> 11

xml

1<?xml version="1.0" encoding="utf-8"?> 2<manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 package="com.example.dousuruyo.shoot_game"> 4 5 <application 6 android:allowBackup="true" 7 android:icon="@mipmap/ic_launcher" 8 android:label="@string/app_name" 9 android:roundIcon="@mipmap/ic_launcher_round" 10 android:supportsRtl="true" 11 android:theme="@style/AppTheme"> 12 <activity android:name=".MainActivity" 13 android:screenOrientation="portrait"> 14 <intent-filter> 15 <action android:name="android.intent.action.MAIN"/> 16 17 <category android:name="android.intent.category.LAUNCHER"/> 18 </intent-filter> 19 </activity> 20 </application> 21 22</manifest>

参考にしたサイト(無断転載問題ある場合は、消します)

http://androidn.hannnari.com/link200-shooting-2.html

補足情報(動作環境)

Nexus4 API25 Android7.1.1(エミュ)

イベントログにはこんな感じで出続けています

19:51 エミュレーター: android/android-emugl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp:glReadPixels:2330 error 0x502

19:51 エミュレーター: android/android-emugl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp:glTexSubImage2D:2606 error 0x500

19:51 エミュレーター: android/android-emugl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp:glReadPixels:2330 error 0x502

19:51 エミュレーター: android/android-emugl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp:glTexSubImage2D:2606 error 0x500

19:51 エミュレーター: android/android-emugl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp:glReadPixels:2330 error 0x502

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

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

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

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

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

guest

回答1

0

ベストアンサー

NullPointerExceptionというのはJavaで最も遭遇する代表的な例外で、値がnullの変数を参照しようとしたことによって発生します。このケースでは、

c.drawColor(Color.YELLOW);

という処理をしようとしたときに、cの値がnullであったために発生したと思われます。

SurfaceHolder#lockCanvas()は、SurfaceViewの描画排他制御のためのメソッドですが、状況によってはnullが返ることがあります。ですから、この処理を

java

1 c = getHolder().lockCanvas(); //定型 2 if (c != null) { 3 c.drawColor(Color.YELLOW); 4 jiki.ODraw(c); 5 6 getHolder().unlockCanvasAndPost(c); //定型 7 }

のようにすれば改善されるのではないかと思います。

投稿2018/03/23 01:27

keicha_hrs

総合スコア6768

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

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

dousuruyo

2018/03/23 06:44

回答ありがとうございます! そこでぬるぽを回避するようにした場合、処理が続いたとしても(今は実行できない状態ですが。。)描画はされない、のでしょうか?。。
keicha_hrs

2018/03/23 08:20

while(){}で回し続けているわけですから、いずれ描画できるタイミングが来れば描画されるんじゃないでしょうか?この場面でnullが返るのは、主に起動直後でまだSurfaceViewの準備が完了していないときでしょう。端末の処理能力など環境にも左右されるので(むしろ遅いと間に合っちゃうのかも)、情報元のサイトではチェックしていませんが、ここでのnullチェックは必須だと思います。
dousuruyo

2018/03/24 10:45

指摘されたnullチェックをいれて動かしてみましたが、同じところでぬるぽのエラーを出し続けました;; んーというか、logcatには出続けていないのですが、事象としては修正前と同じ感じで・・・ 原因がさっぱり不明状態です、、
dousuruyo

2018/03/24 10:48

デバッグ実行したところ、ifの中には入っているのに描画されない感じでした。。 これは、ほかになにか原因があるでしょうか・・・?
keicha_hrs

2018/03/24 11:00

提示されたコードをそのまま移植して(画像は適当)AVDで動かしてみましたが、こちらでは飛ぶことなく動作していますね(この描画が意図通りなのかわからないけど)。何か環境に違いがあるんでしょうか?
keicha_hrs

2018/03/24 11:21

もし前記のStackOverflowの対処を試してみるなら、AVD Managerを開いてこのプログラムを動作させているAVDの行の右端にある鉛筆アイコンをクリックし、出てきた設定画面のEmulated Performanceの行にある設定を"Automatic"から"Software - GLES 2.0"に変えてみてください。
dousuruyo

2018/03/24 15:25

AVDからエミュの設定を上記通りに変えたところ、無事に描画されました!!>< 環境の問題っぽかったです。。 ほんとうに、ありがとうございました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問