• ベストアンサー
  • すぐに回答を!

Java ゲームプログラミング 例外

  • 質問No.7764829
  • 閲覧数512
  • ありがとう数2
  • 回答数4

お礼率 57% (46/80)

JavaでSwing GUIプログラミングをしている者です。

初めて自分で1からプログラムを組んで、念願のゲームを作るということになりました。
自分が作っているゲームは、サバイバルゲームで自分の体力1000相手100でどれだけ倒せるか、というゲームです。
まだ、攻撃してダメージを与えるや、相手の数は一体だったりします。初の挑戦なのでご了承ください。

プログラム↓(長いかも)
//ゲームサバイバル

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class startgame { //スタート画面クラス
public static JButton b1start;
public static JPanel p1,p2; //p2はスタートボタンを押した後にでるJPanel
public static JLabel l1;

startgame start = new startgame();

startgame(){

p1 = new JPanel();
p1.setLayout(new BorderLayout());
p1.setBackground(Color.green);

p2 = new JPanel();
p2.setLayout(new BorderLayout());
p2.setBackground(Color.green);

b1start = new JButton("GAME START");
b1start.setForeground(Color.red);
Font font = new Font(Font.SERIF,Font.BOLD,50);
p1.add(b1start);

l1 = new JLabel("SURVIVAL GAME");
l1.setFont(font);
p1.add(l1,BorderLayout.NORTH);

}
}

class Teki{ //敵クラス
public static JLabel l0icon,l0p;
public static ImageIcon Ticon;
static int yourP;

Teki teki = new Teki();

Teki(){

ImageIcon Ticon = new ImageIcon("./.jpeg"); //相手の画像

l0icon = new JLabel(Ticon);
startgame.p2.add(l0icon,BorderLayout.CENTER);

l0p = new JLabel("100"); //相手体力
int yourP = Integer.parseInt(l0p.getText()); //JLabelをint型に型変化
startgame.p2.add(l0p,BorderLayout.EAST);

}
}

class Jibun{ //自分クラス
public static JLabel l0p2;
public static JButton kogeki;

Jibun jibun = new Jibun();

Jibun(){

l0p2 = new JLabel("1000");
startgame.p2.add(l0p2,BorderLayout.WEST); //自分の体力

kogeki = new JButton("攻撃");
startgame.p2.add(kogeki,BorderLayout.WEST); //攻撃ボタン
}
}

class maingame extends JFrame implements ActionListener{

public static void main(String[] args) { //はじめ

maingame frame = new maingame();

frame.setBounds(200,200,700,400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}

maingame(){
super("サバイバルゲーム");

add(startgame.p1);
startgame.b1start.addActionListener(this);
Jibun.kogeki.addActionListener(this);
}

public void actionPerformed(ActionEvent e){
Object obj = e.getSource();

if(startgame.b1start == obj) {

startgame.p1.add(startgame.p2); //スタートボタンの処理
}

else if(Jibun.kogeki == obj){

System.out.println("攻撃した"); //攻撃処理
}
}

これをコンパイルすると、このような例外が出ます。↓

Exception in thread "main" java.lang.NullPointerException
at java.awt.Container.addImpl(Unknow Source)
at java.awt.Container.add(Unknow Source)
at javax.swing.JFrame.addImpl(Unknow Source)
at java.awtContainer.add(Unknow Source)
at maingame.<init>(maingame.java:88)
at maingame.main(maingame.java:77)

となります。
これは、どうすれば解決できますか?
他にも、「ここはこうしたほうがいい」などがありましたら、どんどんご指摘ください。

質問者が選んだベストアンサー

  • 回答No.2
  • ベストアンサー

ベストアンサー率 55% (1857/3366)

java.lang.NullPointerException は、nullではないものを要求しているところにnullを使った時に出る例外。
その発生箇所がその下に並んでる 「at メソッド(ソースファイル:行番号)」で示されてる。
at java.awt.Container.addImpl(Unknow Source)←例外が発生したメソッド
at java.awt.Container.add(Unknow Source)← java.awt.Container.addImplを呼びだしたメソッド
at javax.swing.JFrame.addImpl(Unknow Source)← java.awt.Container.addを呼びだしたメソッド
...
at maingame.main(maingame.java:77)←上記を呼びだしたメソッド。maingame.javaの77行目

この場合では
・java.*, javax.*は既存のモジュールのものなので、ここにはバグは無いと仮定しておく。
・ <init> は内部処理のものなので、ここにもバグは無いと仮定しておく。どのメソッドかだけは確認しておく。
・残った自作部分を最初に疑う。残っているのは
at maingame.main(maingame.java:77)
だけ。どこが77行目かわからないけど、java.*のaddメソッドで発生しているから
add(startgame.p1);
が該当。
使われているのは startgame.p1だから、これがnullである可能性が高い。
実際にデバッガで調べたり、直前にif( startgame.p1 == null ){ ~ }などとしたりすれば、確認できる。

nullになっている、ということは
・明示的にnullを代入している
・nullを返すメソッドの戻り値を代入している
・初期値にままでなにも代入していない
の可能性がある。

startgame.p1を追っていくと
・startgameコンストラクタで代入されている
・startgameコンストラクタは、mainの開始→maingameコンストラクタ実行→addメソッド実行までの間で、まったく使われていない

ということで、「初期値のままなにも代入されていない」のが原因。
対策は、「正しく初期化する」


コンストラクタはインスタンス作成時に呼ばれるメソッドであって、クラス作成時に呼ばれるメソッドではありません。
staticなメンバーを初期化するなら、宣言時に初期値を入れるか、staticメンバー初期化用のstaticなメソッドを用意して最初に呼び出すようにするか、です。




> 他にも、「ここはこうしたほうがいい」などがありましたら、どんどんご指摘ください。

・エラーメッセージはちゃんと読め
上記のように、エラーメッセージをちゃんと読むだけで、多くの問題は解決できます。
・設計を1からやりなおせ
startgameクラスってこんな作りでいいの?static使わずに、インスタンスを一つだけ作るのが妥当だと思うんだけど。
・Javaを基礎からやりなおせ
前から言ってるけど、まずは基礎を身に付けてください。
基本的な間違いばかりです。
特に、ゲームなんて総合的な機能が必要なものは、見様見真似でできるものではありません。

学ぶ気が無いなら、プログラミングなんかやめてしまえ。
お礼コメント
javaboy

お礼率 57% (46/80)

その通りですね・・・・・・・

一から出直します。
回答ありがとうございます
投稿日時:2012/12/09 21:21

その他の回答 (全3件)

  • 回答No.4

ベストアンサー率 23% (3656/15482)

も一つ追加:

変数名にしろクラス名にしろメソッド名にしろ, すべからく「機能を反映する」名前を付けてください. このプログラムみたいに「p1」とか「l0p2」とかいった名前が出てくるようなものは, 黙ってゴミ箱に投げ込まれてもしょうがないと認識してください.
お礼コメント
javaboy

お礼率 57% (46/80)

わかりましたこれからは、その通りにしてみようと思います。

回答ありがとうございます。
投稿日時:2012/12/09 21:23
  • 回答No.3

ベストアンサー率 23% (3656/15482)

念のため:

「<init>」はコンストラクタ (に対応する内部的なメソッド) ですよね>#2.
  • 回答No.1

ベストアンサー率 23% (3656/15482)

「コンパイルする」だけでは, そんなメッセージは出ないはずです.

メッセージの意味はわかりますか? 「エラーが出るたびに他人に頼る」というのでなければ, メッセージの読み方を理解すべきでしょう.
関連するQ&A
ページ先頭へ