Javaを使って四角形をキーボード入力で動かしてみた

#はじめに
この記事は、[SLP KBIT AdventCalendar2021](https://adventar.org/calendars/6706) 17日目の記事です。
Javaを使って画面に映した図形をキーボードからの入力で動かす処理を作ってみました。

Javaで2Dゲーム作ってみたいなと思い、とりあえずキーボードでキャラクターを動かせるようにしてみようという経緯で作りました。

#目次
[・プログラムの作成](#プログラムの作成)
[・コード](#コード)
[・まとめ](#まとめ)

#プログラムの作成

##環境
Java 16
Eclipse 4.19.0

##機能
画面に表示した四角形をキーボードの[W][A][S][D]で動かします。


#コード
```Java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;

public class GameMain extends JFrame implements KeyListener{
	int x= 200,y= 100;
	int speed=5;
	boolean flag_W=false,flag_A=false,flag_S=false,flag_D=false;
	
    // Main
	public static void main(String args[]){
		GameMain g = new GameMain();
		while(true) {
			g.repaint();
		}
	}

    // Constructor
	GameMain(){
		super("Move");
		addKeyListener(this);
		setBackground(Color.GRAY);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(400, 340);
		setLocationRelativeTo(null);
		setResizable(false);
		setVisible(true);
	}

	//paint
	public void paint(Graphics g){
		move();
		g.setColor(Color.GRAY);
		g.fillRect(0, 0, 400, 340);
		g.setColor(Color.blue);
		g.fillRect(x,y,20,20);
		try{
			Thread.sleep(10);
		} catch(InterruptedException e) {
			
		}
	}

	// KeyEvent Listener
	public void keyPressed(KeyEvent e){
		switch(e.getKeyCode()){
		case KeyEvent.VK_W: flag_W=true; break;
		case KeyEvent.VK_D: flag_D=true; break;
		case KeyEvent.VK_S: flag_S=true; break;
		case KeyEvent.VK_A: flag_A=true; break;
	}
	}
	public void keyReleased(KeyEvent e) {
		switch(e.getKeyCode()) {
			case KeyEvent.VK_W: flag_W=false; break;
			case KeyEvent.VK_D: flag_D=false; break;
			case KeyEvent.VK_S: flag_S=false; break;
			case KeyEvent.VK_A: flag_A=false; break;
		}
	}
	public void keyTyped(KeyEvent e) {
		
	}
	//flagを受け取ってそれに合わせて図形を動かす
	public void move() {
		if(y>=30) {
			if(flag_W) {
				y-=speed;
			}
		}
		if(x+20<400) {
			if(flag_D) {
				x+=speed;
			}
		}
		if(x>=0) {
			if(flag_A) {
				x-=speed;
			}
		}
		if(y+20<340) {
			if(flag_S) {
				y+=speed;
			}
		}
	}
}
```
###実行結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366974/fe3615f0-520c-4623-4ab7-9872467a3e2a.png" width=50%>
↓[A]と[S]で左下に移動
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366974/c4bac33a-23c9-e944-6975-c68a4fce1262.png" width=50%>



##コードの解説
main関数で作ったインスタンスを無限にrepaintさせてるだけです。

repaintの際に前に描画した図形が残り続けたので、毎回背景と同じ色で塗りつぶしすることで対処しました。

keyPressed関数の中は下のようにしても一応動きますが、カクカク動くのでflagで管理した方がお勧めです。

```Java
// KeyEvent Listener
	public void keyPressed(KeyEvent e){
		switch(e.getKeyCode()){
		case KeyEvent.VK_W: y-=speed; break;
		case KeyEvent.VK_D: x+=speed; break;
		case KeyEvent.VK_S: x-=speed; break;
		case KeyEvent.VK_A: y+=speed; break;
	}
   }
```

#まとめ
imageを使えば図形だけじゃなく画像も動かせそうですね。
背景や今回動かした図形を画像にしたらゲームっぽくなりそうな気がします。

##今後について
1画面を移動するプログラムはできたので、次は図形の動きに合わせて画面全体を動かす処理を作りたいですね。

##最後に
今年もあと半月弱ですね。
今年は毎日睡眠不足だったような気がします…。
僕の来年の目標はちゃんと寝ることです。
皆さんも健康に気をつけて、良いお年を。

###参考文献
[【Java】キー入力処理](https://nompor.com/2017/12/10/post-1924/)
[Javaでプログラムを一時停止、Thread.sleepの使い方と仕組みを解説](https://www.bold.ne.jp/engineer-club/java-sleep)
[Java　AWT キー操作に関するイベント](https://yan-note.blogspot.com/2009/05/awg_23.html)