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

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

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

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

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

1435閲覧

NullPointerExceptionが発生する

yukkuri

総合スコア624

Java

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

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2018/08/17 22:48

編集2018/08/17 23:36

現在、ゲームを作っているのですが、NullPointerExceptionがクラスの配列で発生してしまいます。ソースは

lang

1import java.awt.event.*; 2 3import src.yukkuri.lib.*; 4import src.yukkuri.lib.Game.*; 5 6enum Battle 7{ 8 SETUP, // 敵出現のメッセージ 9 MAIN, // コマンド選択中 10 P_ACTION, // プレイヤーの行動 11 M_ACTION, // モンスターの行動 12 RESET, // MAINへのリターン 13 RESULT; // アイテム入手、経験値、お金入手 14} 15 16public class debug2 extends BaseGame 17{ 18 static boolean debug = true; 19 20 static MapImageChip m_mic; 21/* newSprite m_player; 22 newSprite player_up; // angle:1 23 newSprite player_right; // angle:2 24 newSprite player_left; // angle:3 25 newSprite player_down; // angle:4*/ 26 newSprite[] m_player = new newSprite[ 5 ]; // 上右下左現在 27 int angle = 4; 28 boolean upMenu = false; 29 boolean upMove = true; 30 31 GameLib gl; 32 Sprite boss_one; 33 int boss_one_hpmax = 1000; 34 int boss_one_hpmin = 1000; 35 36 Sprite boss_two; 37 int boss_two_hpmax = 10000; 38 int boss_two_hpmin = 10000; 39 String message = ""; 40 41 static int l = 0; 42 43 player p1; 44 45 public static void main( String[] args ) 46 { 47 new debug2(); 48 } 49 50 public debug2() 51 { 52 super( "てすとげーむ", 1920, 1088, false ); 53 } 54 55 @Override public void Create() 56 { 57 gl = new GameLib(); 58 59 setBackground( 0x000000 ); 60 try{ 61 // マップ用 62/* player_up = new newSprite( ".\image\char_p_hero01.amg", 0, 9, 48, 64 ); 63 player_right = new newSprite( ".\image\char_p_hero01.amg", 0, 73, 48, 64 ); 64 player_down = new newSprite( ".\image\char_p_hero01.amg", 0, 137, 48, 64 ); 65 player_left = new newSprite( ".\image\char_p_hero01.amg", 0, 201, 48, 64 ); 66 m_player = new newSprite( ".\image\char_p_hero01.amg", 0, 137, 48, 64 );*/ 67 for( int l = 3; l > -1; l-- ){ 68 System.out.println( l ); 69 m_player[ l ] = new newSprite( ".\image\char_p_hero01.amg", 0, 9 + l * 64, 48, 64 ); 70 } 71 m_player[ 0 ] = new newSprite( ".\image\char_p_hero01.amg", 0, 9 + 0 * 64, 48, 64 ); 72 System.out.println( "抜けたよ" ); 73 m_player[ 4 ] = m_player[ 2 ]; // 初期状態を下向きに設定 74 m_mic = new MapImageChip( ".\image\chip02d_dungeon.amg", 64, 64 ); 75 76 // 戦闘用 77 boss_one = new Sprite( ".\image\human232_l.amg", 0, 0, 695, 486 ); 78 boss_two = new Sprite( ".\image\monster171_l.amg", 0, 0, 683, 504 ); 79 p1 = new player( ".\bgm.se\nc98796.wav", 0 ); 80 }catch( java.io.IOException ie ){ ie.printStackTrace(); } 81 82 m_mic.m_map = new int[]{ 83 // 5 10 15 20 25 30 84 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 85 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 86 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 87 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 88 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 5 89 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 90 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 91 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 92 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 93 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 13 94 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 95 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 96 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 97 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 98 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 15 99 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 100 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 101 }; 102 } 103 104 @Override public void Key_Press( int code ) 105 { 106 if( debug ){ System.out.println( "キー" + code + "が押されたよ!" ); } 107 if( code == KeyEvent.VK_D ){ 108 if( debug ){ 109 System.out.println( "デバッグをオフにしました" ); 110 debug = false; 111 }else{ 112 System.out.println( "デバッグをオンにしました" ); 113 debug = true; 114 } 115 } 116 if( code == KeyEvent.VK_X ){ 117 if( upMenu ){ 118 upMenu = false; upMove = true; 119 }else{ 120 upMenu = true; upMove = false; 121 } 122 }if( code == KeyEvent.VK_ENTER )boss_one_hpmin -= 10; 123 if( upMove ){ 124 m_player[ 4 ].move( code ); 125 if( code == KeyEvent.VK_UP ) angle = 1; 126 if( code == KeyEvent.VK_RIGHT ) angle = 2; 127 if( code == KeyEvent.VK_LEFT ) angle = 3; 128 if( code == KeyEvent.VK_DOWN ) angle = 4; 129 } 130 if( debug ) System.out.println( "X:" + m_player[ 4 ].m_x + " Y:" + m_player[ 4 ].m_y ); 131 repaint(); 132 } 133 134 @Override public void Paint() 135 { 136/* setColor( 0xffff255 ); 137 if( boss_one_hpmin < 1 ){ 138 if( l == 0 ){ 139 System.out.println( "音楽再生" ); 140 p1.playMusic(); 141 l++; 142 } 143 message = "この程度で負けると思うなよ!敵が復活してしまった!"; 144 draw( boss_two, 625, 65 ); 145 fillRect( 10, 20, 19 * gl.per( boss_two_hpmax, boss_two_hpmin ), 25 ); 146 }else{ 147 message = "ボスが現れた!"; 148 draw( boss_one, 625, 65 ); 149 fillRect( 10, 20, 19 * gl.per( boss_one_hpmax, boss_one_hpmin ), 25 ); 150 } 151 setColor( 0xffffff ); 152 draw( 0, 600, 1920, 600 ); 153 drawRect( 10, 20, 1900, 25 ); 154 setFont( 60 ); 155 draw( message, 50, 700 ); 156 String[] command = { "攻撃", "防御", "移動", "魔法", "アイテム", "逃げる" }; 157 for( int l = 0; l < 6; l++ ){ 158 draw( command[ l ], 1600, 700 + 60 * l ); 159 }*/ 160 m_mic.putMapCip( this, 0, 0, 30, 17 ); 161 162 if( angle == 1 ) draw( m_player[ 0 ], m_player[ 4 ].m_x, m_player[ 4 ].m_y ); 163 if( angle == 2 ) draw( m_player[ 1 ], m_player[ 4 ].m_x, m_player[ 4 ].m_y ); 164 if( angle == 3 ) draw( m_player[ 2 ], m_player[ 4 ].m_x, m_player[ 4 ].m_y ); 165 if( angle == 4 ) draw( m_player[ 3 ], m_player[ 4 ].m_x, m_player[ 4 ].m_y ); 166 if( upMenu ){ 167 setColor( 0x33000000, true ); 168 fillRect( 0, 0, 600, 1080 ); 169 } 170 } 171} 172 173class newSprite extends Sprite 174{ 175 public newSprite( String fname, int x, int y, int w, int h ) throws java.io.IOException 176 { 177 super( fname, x, y, w, h ); 178 } 179 180 public void move( int code ) 181 { 182 if( code == KeyEvent.VK_RIGHT ){ 183 m_x += 48; 184 }if( code == KeyEvent.VK_LEFT ){ 185 m_x -= 48; 186 }if( code == KeyEvent.VK_UP ){ 187 m_y -= 32; 188 }if( code == KeyEvent.VK_DOWN ){ 189 m_y += 32; 190 } 191 } 192}

この中の、エラー個所は

lang

1for( int l = 3; l > -1; l-- ){ 2 System.out.println( l ); 3 m_player[ l ] = new newSprite( ".\image\char_p_hero01.amg", 0, 9 + l * 64, 48, 64 ); 4 }

です。よろしくお願いします。

追記
スタックトレース
Exception in thread "main" java.lang.NullPointerException at debug2.Create(debug2.java:69) at src.yukkuri.lib.Game.BaseGame.<init>(BaseGame.java:29) at debug2.<init>(debug2.java:52) at debug2.main(debug2.java:47)

javaのバージョンは7です。

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

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

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

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

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

umyu

2018/08/17 23:18

NullPointerExceptionが発生時のスタックトレースをcodeタグで囲ってそのまま貼ってくださいな。
guest

回答1

0

ベストアンサー

スタックトレースの追記ありがとうございました。

スタックトレースのdebug2.Create(debug2.java:69)が質問文のコードを見る限り以下の行です、

m_player[ l ] = new newSprite( ".\image\char_p_hero01.amg", 0, 9 + l * 64, 48, 64 );

Spriteクラスの定義が質問文に無いので確実な事はいえませんが、
上記行でNullPointerExceptionが発生しえるのは変数:m_playerです、
以下のようにfinal宣言に変更して再代入を抑止しても上記問題が発生するか確認して頂けませんか?

diff

1-newSprite[] m_player = new newSprite[ 5 ]; 2+private final newSprite[] m_player = new newSprite[5];

無理でした。

Java

1at debug2.Create(debug2.java:69) 2src.yukkuri.lib.Game.BaseGame.<init>(BaseGame.java:29) // ← BaseGameのコンストラクタ<init> 3at debug2.<init>(debug2.java:52)

スタックトレースを見るとBaseGameクラスのコンストラクタからBaseGameCreateを呼び出していませんか。


BaseGameクラスが気になりますが。
継承したクラスでのcreateの呼び出しをprintlnしてみましたこのような出力になります。

■対策としては
案1,コンストラクタでオーバーライド対象のメソッドのcreate()の呼び出しをやめる。
コンストラクタの可視性の関係上、イベントリスナーの登録、スレッドの起動も避けたほうがよいです。
(私もサンプルコードではよく書きますが)

以下からは改造の手間がかかります。
案2, BaseGameが何を目的のクラスなのかで変わりますが。
BaseGameを継承するのをやめて、コンポジット(委譲)にする。
debug2クラスはBaseGameクラスのフィールドを持ち、baseGame.create();などを必要な都度呼び出す。
private BaseGame baseGame = new BaseGame();

案3, BaseGameはクラスではなくinterfaceで抽象メソッドの定義とdefalutメソッドにする。

個人的なオススメは案2でしょうか。
BaseGameというクラス名はいろいろな処理がありそうなクラス名に見えるので、
内部の処理をクラス分割することをお勧めします。


追記したBaseGameを見ました、率直な感想は継承する意味があまりないような。
クラスを導入する事で解消される問題もあまりなさそうに見えますし。
どちらかというと、PropertiesクラスもしくはJSON形式のファイルを使って
今、プログラムに埋め込んでいるMAP情報や画像のパスなどを外部化した方が管理しやすいかもです。

投稿2018/08/17 23:50

編集2018/08/18 01:28
umyu

総合スコア5846

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

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

yukkuri

2018/08/17 23:54

無理でした。 後、Sprite.javaのソースはこれです。 package src.yukkuri.lib.Game; import java.awt.*; import java.awt.image.*; import java.io.*; import javax.imageio.*; public class Sprite { public BufferedImage m_bi; public int m_x, m_y; public Sprite( BufferedImage bi ) { m_bi = bi; } public Sprite( BufferedImage bi, int x, int y, int w, int h ) { m_bi = bi.getSubimage( x, y, w, h ); } public Sprite( File file, int x, int y, int w, int h ) throws IOException { BufferedImage bi = ImageIO.read( file ); m_bi = bi.getSubimage( x, y, w, h ); } public Sprite( String fname, int x, int y, int w, int h ) throws IOException { BufferedImage bi = ImageIO.read( new File( fname ) ); m_bi = bi.getSubimage( x, y, w, h ); } public void draw( Graphics g ) { g.drawImage( m_bi, m_x, m_y, null ); } public void draw( Graphics g, int x, int y ) { g.drawImage( m_bi, x, y, null ); } } (直貼りですいません、マークダウン方式がよくわからなくて・・・)
yukkuri

2018/08/18 00:03

そうですね。 BaseGameクラスでFrameを作成して、 そこでCreateを呼び出して、Overrideでこっちが呼び出されて・・・ というイメージです。ただ、前も上の処理でできていたので、あまり関係ないかも・・・
umyu

2018/08/18 00:08

@yukkuriさんへ 前の処理は配列じゃないのではないでしょうか? player_upとか別の変数で宣言してますよね。 えっとですね、コンストラクタでインスタンスメソッドの呼び出しは避けたほうがよいというのがありまして。 http://irof.hateblo.jp/entry/2016/01/09/231631
yukkuri

2018/08/18 00:16

いまリンクのサイトを拝見しまして、なんとなく理解できました。 umyuさんの言うとおり、前は配列ではなく、変数が5つでした。 それをまとめようとしたら、今のエラーというわけです。
umyu

2018/08/18 00:18

Subのコンストラクタにprint文を追加するとわかりやすいかもです。
yukkuri

2018/08/18 00:23

そういうことですか! そしたら、どうしたらいいんでしょうか? ご教授お願いします。
yukkuri

2018/08/18 00:32

一応BaseGameのソースを貼りますね。 package src.yukkuri.lib.Game; import java.awt.*; import javax.swing.*; /** * JFrameのラッパークラスです。Gameの基本を作成します。 * * @author yukkuriP */ public class BaseGame extends JFrame { public BaseGraphic m_bgra; private BaseGame( String title, boolean resize ) { m_bgra = new BaseGraphic( this ); setDefaultCloseOperation( EXIT_ON_CLOSE ); setTitle( title ); setResizable( resize ); } public BaseGame( String title, int w, int h, boolean resize ) { this( title, resize ); getContentPane().setPreferredSize( new Dimension( w, h ) ); pack(); getContentPane().add( m_bgra ); Create(); setVisible( true ); } public BaseGame( String title, int x, int y, int w, int h, boolean resize ) { this( title, resize ); setBounds( x, y, w, h ); getContentPane().setPreferredSize( new Dimension( w, h ) ); pack(); getContentPane().add( m_bgra ); Create(); setVisible( true ); } public void clearRect( int x, int y, int width, int height ) { m_bgra.clearRect( x, y, width, height ); } public void draw( Sprite s ) { m_bgra.draw( s ); } public void draw( String str, int x, int y ) { m_bgra.draw( str, x, y ); } public void draw( Sprite s, int x, int y ) { m_bgra.draw( s, x, y ); } public void draw( int x1, int y1, int x2, int y2 ) { m_bgra.draw( x1, y1, x2, y2 ); } public void drawRect( int x, int y, int width, int height ) { m_bgra.drawRect( x, y, width, height ); } public void fillRect( int x, int y, int width, int height ) { m_bgra.fillRect( x, y, width, height ); } public void setBackground( int rgb ) { m_bgra.setBackground( rgb ); } public void setColor( int rgb ) { m_bgra.setColor( rgb ); } public void setColor( int argb, boolean hasalpha ) { m_bgra.setColor( argb, hasalpha ); } public void setFont( int size ) { m_bgra.setFont( size ); } public void setFontGC( Font f ) { m_bgra.setFontGC( f ); } public void Create(){} public void Key_Press( int code ){} public void Key_Release( int code ){} public void Paint(){} }
yukkuri

2018/08/18 00:56

思ったのですが、BaseGameは継承元の予定で最初から作っていたので、内部処理は全くありません。汎用的なクラスを目指していたのですが、どうしたらいいでしょうか。
umyu

2018/08/18 00:58

汎用的なクラスとはどういうニュアンスのクラスでしょうか。何かの目的のためにBaseGameと質問文のプログラムを作られたのですよね?
m.ts10806

2018/08/18 01:11

横から失礼します。 コメント欄ではマークダウンが使えないので質問に追記されては? 文字制限にひっかかるようでしたら関係なさそうな部分を削るなど工夫が必要ですが。
yukkuri

2018/08/18 01:26

汎用的なクラスというのは、継承して、その人が実装したいシステムなどを追加できる(というイメージの)クラスのことですね。
umyu

2018/08/18 01:39 編集

@mts10806さんへ 指摘ありがとうございます、そうですね。この回答欄に記載していただいても、他の回答者の方の目が届かないので、質問文を編集して頂けませんか?>@yukkuriさんへ @yukkuriさんへ そういう感じだとUnityを参考にクラス設計をした方がよいのですが。 一般論として開発者一人だと技術力と時間の関係上作りきれないかと。 https://docs.unity3d.com/ja/current/Manual/ScriptingImportantClasses.html 個人的には画面周り(JFrame/JPanel)は実装するシステムによってかなり変わるので、ゲームで使用するリソースを管理しやすい形に纏める方がいいかもです。 で、質問文の本題であるNullPointerExceptionの件から少し横道にそれて来たので、話題を振っておいてなんですが、対策方法は既に回答に記載していますので、別の質問(ゲームの設計のあり方)みたいなのを立てて頂けるといいかもです。
yukkuri

2018/08/18 01:57

わかりました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問