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

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

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

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

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

Q&A

解決済

1回答

1501閲覧

timerクラスでkeylistenerが反応しない

zenoxxx44

総合スコア7

Java

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

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

0グッド

0クリップ

投稿2019/07/31 13:37

編集2019/07/31 14:37

前提・実現したいこと

シューティングゲームを作成しています。
矢印キーの左右で、自機を左右に移動させ、矢印キーの上で、ミサイルを発射させたいです。
マウスの処理は、そのままにしておきたいです。

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

矢印キーで自機を操作したいのですが、keylistenerを使っても反応してくれません。
敵に関する文と、Bossに関する文、ミサイルの当たり判定の文を、文字制限にかかったので、省略しています。
どなたかご教授していただけると助かります。

エラーメッセージ なし

該当のソースコード

ソースコード import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.Random; public class Ex_15_1801010495 extends JFrame{ final int windowWidth=800;//windowの幅 final int windowHeight=500;//windowの高さ Container c; Start panelStart; MyJPanel mainPanel; Clear clear; GameOver gameover; public boolean key_up; public boolean key_right; public boolean key_left; public static void main(String[] args){ new Ex_15_1801010495(); } public Ex_15_1801010495(){ Dimension dimOfScreen=Toolkit.getDefaultToolkit().getScreenSize(); setBounds(dimOfScreen.width/2-windowWidth/2,dimOfScreen.height/2-windowHeight/2,windowWidth,windowHeight); setResizable(false);//ウィンドウサイズ変更の可否 setTitle("Software Development II"); //タイトル setDefaultCloseOperation(EXIT_ON_CLOSE);//バツボタンの処理 panelStart=new Start();//panelオブジェクト作成 panelStart.setLayout(null); c=getContentPane(); c.add(panelStart); setVisible(true); } public class MyJPanel extends JPanel implements ActionListener,MouseListener,MouseMotionListener,KeyListener{ //全体の設定 Dimension dimOfPanel;//dimensionクラス Timer timer;//timerクラス ImageIcon iconMe,iconEnemy,iconHeart,iconBoss;//icon Image imgMe,imgEnemy,imgmyHeart,imgBoss;//img Font fmb = new Font("Serif" , Font.BOLD , 20); Random rnd=new Random();//乱数発生 //自分のライフ int myLife=3;//自機ライフ数 int myHeartWidth,myHeartHeight;//ライフの幅と高さ int[] myHeartX=new int[myLife];//ライフのX座標配列 int[] myHeartY=new int[myLife];//ライフのY座標配列 boolean[] isHeartActive=new boolean[myLife];//ライフの有無 //自機 int myHeight,myWidth;//自機の幅と高さ int myX,myY,tempMyX;//自機のX座標,Y座標 int gap=100;//絶対値比較の際に使用、 int myMissileX,myMissileY,myMissileX2,myMissileY2;//ミサイルのX座標,Y座標、ミサイル2のX座標,Y座標 int myMissileWidth=3,myMissileHeight=5;//ミサイルの横幅と縦幅 boolean isMyMissileActive;//ミサイルの発射状態 //敵機 int numOfEnemy=12;//敵の数 int numOfAlive=numOfEnemy;//敵の残数 int enemyWidth,enemyHeight;//敵の幅と高さ int enemyMissileWidth=3,enemyMissileHeight=5; int[] enemyX=new int[numOfEnemy];//敵のX座標配列 int[] enemyY=new int[numOfEnemy];//敵のY座標配列 int[] enemyMove=new int[numOfEnemy];//敵の動く方向 int[] enemyMissileX=new int[numOfEnemy];//敵ミサイルのX座標配列 int[] enemyMissileY=new int[numOfEnemy];//敵ミサイルのY座標配列 int[] enemyMissileSpeed= new int[numOfEnemy];//敵ミサイルのスピード配列 int[] enemyLife=new int[numOfEnemy];//敵のライフ配列 boolean[] isEnemyAlive=new boolean[numOfEnemy];//敵の生存状態 boolean[] isEnemyMissileActive=new boolean[numOfEnemy];//敵のミサイル発射状態 //boss int bossLife=10;//bossライフ int bossHeight,bossWidth;//bossの幅と高さ int bossX,bossY,bossMoveX,bossMoveY;//bossのx,y座標、動く方向x,y int bossMissileX,bossMissileY,bossMissileX2,bossMissileY2,bossMissileX3,bossMissileY3,bossMissileX4,bossMissileY4,bossMissileX5,bossMissileY5;//bossミサイルのx,y座標 int bossMissileWidth=8,bossMissileHeight=5,bossMissileSpeed;//bossミサイルの横幅、bossミサイルの縦幅、bossミサイルのスピード boolean isBossAlive=true;//bossの生存状態 boolean isBossActive=false;//bossの出現状態 boolean isBossMissileActive;//bossミサイル発射状態 public MyJPanel(){ //全体の設定 setBackground(Color.black);//背景色 addMouseListener(this); addMouseMotionListener(this); addKeyListener(this); timer=new Timer(50,this);//timer設定 timer.start();//timerスタート //自機img imgMe=getImg("jiki.jpg"); myWidth=imgMe.getWidth(this); myHeight=imgMe.getHeight(this); //敵機img imgEnemy=getImg("teki.jpg"); enemyWidth=imgEnemy.getWidth(this); enemyHeight=imgEnemy.getHeight(this); //ライフimg imgmyHeart=getImg("heart.jpg"); myHeartWidth=imgmyHeart.getWidth(this); myHeartHeight=imgmyHeart.getHeight(this); //bossimg imgBoss=getImg("boss.jpg"); bossWidth=imgBoss.getWidth(this); bossHeight=imgBoss.getHeight(this); initMyHeart();//ライフの初期化 initMyPlane();//自機の初期化 initEnemyPlane();//敵の初期化 initBossPlane();//bossの初期化 } //パネル上の描画 public void paintComponent(Graphics g){ dimOfPanel=getSize(); super.paintComponent(g); //各要素の描画 drawMyHeart(g); drawMyPlane(g); drawMyMissile(g); drawEnemyPlane(g); drawEnemyMissile(g); if(numOfAlive==0){ drawBossPlane(g);//boss描画 drawBossMissile(g);//bossミサイル g.setFont(fmb);//font指定 g.setColor(Color.red);//文字色指定 g.drawString("BossLife "+String.valueOf(bossLife),650,20);//ボスライフ表示 isBossActive=true;//bossの出現状態 } } public void actionPerformed(ActionEvent e){ action(); repaint(); //自機ライフが0 if(myLife==0){ timer.stop(); setVisible(false); gameover = new GameOver(); gameover.setLayout(null); c.removeAll(); c.add(gameover); setVisible(true); } //bossライフが0なら if(bossLife==0){ isBossAlive=false;//生存状態false timer.stop(); setVisible(false); clear = new Clear(); clear.setLayout(null); c.removeAll(); c.add(clear); setVisible(true); } } public void action(){ if(key_up){ if(!isMyMissileActive){ myMissileX=tempMyX+myWidth/2; myMissileY=myY; isMyMissileActive=true; } } if(key_right){ tempMyX+=5; } if(key_left){ tempMyX-=5; } } //マウスボタンをクリック public void mouseClicked(MouseEvent e){ } //マウスボタンを押す public void mousePressed(MouseEvent e){ if(!isMyMissileActive){ myMissileX=tempMyX+myWidth/2; myMissileY=myY; isMyMissileActive=true; } } //マウスボタン離す public void mouseReleased(MouseEvent e){ } //マウスが領域外に出る public void mouseExited(MouseEvent e){ } //マウスが領域内に入る public void mouseEntered(MouseEvent e){ } //マウスを動かす public void mouseMoved(MouseEvent e){ myX=e.getX(); } //ドラッグする public void mouseDragged(MouseEvent e){ myX=e.getX(); } //キーボードをタイプする public void keyTyped(KeyEvent e){ } //キーが押された時 @Override public void keyPressed(KeyEvent e) { switch(e.getKeyCode( )){ case KeyEvent.VK_UP: key_up=true; break; case KeyEvent.VK_RIGHT: key_right=true; break; case KeyEvent.VK_LEFT: key_left=true; break; } } //キーが離れた時 @Override public void keyReleased(KeyEvent e){ switch(e.getKeyCode( )){ case KeyEvent.VK_UP : key_up=false; break; case KeyEvent.VK_RIGHT: key_right=false; break; case KeyEvent.VK_LEFT : key_left=false; break; } } //画像ファイルをImageクラスへ変換 public Image getImg(String filename){ ImageIcon icon=new ImageIcon(filename); Image img=icon.getImage(); return img; } //自機の初期化 public void initMyPlane(){ myX=windowWidth/2; myY=windowHeight-100; tempMyX=windowWidth/2; isMyMissileActive=false; } //自機の描画 public void drawMyPlane(Graphics g){ if(Math.abs(tempMyX-myX)<gap){ if(myX<0){ myX=0; }else if(myX+myWidth>dimOfPanel.width){ myX=dimOfPanel.width-myWidth; } tempMyX=myX; g.drawImage(imgMe,tempMyX,myY,this); }else{ g.drawImage(imgMe,tempMyX,myY,this); } g.drawImage(imgMe,tempMyX,myY,this); } //自機ミサイルの描画 public void drawMyMissile(Graphics g){ myMissileX2=myMissileX;//ミサイル2のx座標 myMissileY2=myMissileY+5;//ミサイル2のy座標 //ミサイルの発射状態がtrue未発射なら if(isMyMissileActive){ myMissileY-=20;//ミサイル1の速さ設定 g.setColor(Color.white);//ミサイルの色指定 g.fillRect(myMissileX,myMissileY,myMissileWidth,myMissileHeight);//ミサイル1描画 //ミサイル1のY座標が400を下回ったら if(myMissileY<400){ myMissileY-=20;//ミサイル2の速さ設定 g.fillRect(myMissileX2,myMissileY2,myMissileWidth,myMissileHeight);//ミサイル2描画 } } } public class Start extends JPanel implements ActionListener{ JButton start=new JButton("スタート"); public Start(){ start.setBounds(300,150,200,100); start.addActionListener(this); add(start); } public void actionPerformed(ActionEvent e){ if(e.getSource()==start){ setVisible(false); mainPanel = new MyJPanel(); mainPanel.setFocusable(true); mainPanel.requestFocus(); c.removeAll(); c.add(mainPanel); setVisible(true); } } } }

試したこと

**ここに問題に対して試したことを記載してください。
画面を遷移させるときに、mainPanel.setFocusable(true);
mainPanel.requestFocus();を使いましたが、入力しても反応してくれません。

自作関数を使用して、自機のx座標を変更したり、Listener内で、自機のx座標を変更したりしましたが、反応がありませんでした。
**

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

ngsvx

2019/07/31 15:00

mainPanel.requestFocus();をc.add(mainPanel);の後にするとどうでしょうか。 また、mainPanel.requestFocus();をmainPanel.requestFocusInWindow();にしてみてください。
guest

回答1

0

ベストアンサー

requestFocus では無く requestFocusInWindow を使うようにとされています.

public void requestFocus()

このComponentが入力フォーカスを取得することを要求します。このメソッドの詳細については、Component.requestFocus()を参照してください。

このメソッドの動作はプラットフォームに依存しているため、このメソッドを使用することは推奨されません。代わりにrequestFocusInWindow()を使用することをお勧めします。フォーカスの詳細については、「The Java Tutorial」の「How to Use the Focus Subsystem」を参照してください。

チュートリアルの How to Use the Focus Subsystem には以下の文があります. (google 翻訳しました)

ウィンドウが最初にアクティブになったときに特定のコンポーネントが確実にフォーカスを取得するようにしたい場合は、コンポーネントが認識された後、フレームが表示される前に、そのコンポーネントrequestFocusInWindowメソッドを呼び出すことができます。 次のサンプルコードは、この操作がどのように行われることができるのか示します。

//...Where initialization occurs... JFrame frame = new JFrame("Test"); JPanel panel = new JPanel(new BorderLayout()); //...Create a variety of components here... //Create the component that will have the initial focus. JButton button = new JButton("I am first"); panel.add(button); frame.getContentPane().add(panel); //Add it to the panel frame.pack(); //Realize the components. //This button will have the initial focus. button.requestFocusInWindow(); frame.setVisible(true); //Display the window

蛇足ですが.
自機, 敵機, ボス, それぞれのミサイル等の各種変数が直接パネルクラス内にあるために, キー入力等の部分が埋もれてしまっています.
それぞれに適切なクラスを作成してパネルから呼び出すようにすれば, パネル内がスッキリしてくると思います.

投稿2019/07/31 17:49

jimbe

総合スコア12545

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問