回答編集履歴

6

編集修正

2023/10/04 07:41

投稿

jimbe
jimbe

スコア12721

test CHANGED
@@ -1,14 +1,23 @@
1
- JFrame に直接ペイントせず、 JPanel を土台に paintComponent を Override して直接(間に offscreen の image を挟まず)描画して下さい。
2
- Swingはデフォルトでダブルバッファリングを行います。
3
-
4
1
  >これまでに描画していた、画像をがrepaintメソッドを呼び出しても、
5
2
  >描画されてしまっています。
6
3
 
7
4
  これまでに描画していたモノを消していないなら残っているのは当然ではないでしょうか。
5
+ 一番簡単には、 image をクリアする処理を入れることでしょう。
8
6
 
7
+ GameController.GameLoopクラス
8
+ ```java
9
+ public void draw() {
10
+ Graphics g = image.getGraphics();
11
+ g.setColor(new Color(0x80c080)); //追加
12
+ g.fillRect(0, 0, mainJFrame.getWidth(), mainJFrame.getHeight()); //追加
13
+ g.setColor(Color.blue);
14
+ ```
9
15
  ---
10
- JFrame 直接使うのではなく、 JPanel Timer使って gameTick() メソッドを呼び出 Hiro Enemy動かします。
16
+ JFrame 直接ペイントせず、 JPanel を土台に paintComponentOverrideて直接(間に offscreen image を挟まず)描画します。
17
+ 描画タイミングには Swing の Timer クラスを使用します。ウインドウのアクティブ状態に合わせて再開/停止を制御します。
11
- Character はそれぞれが draw() メソッドで自身描画します。
18
+ データの描画と更新の衝突を防ぐため、 syncronized を入れています。
19
+ キャラクタの描画はそれぞれのクラス自身が行います。Hero も赤四角として横に移動させるようにしました。
20
+
12
21
  ```java
13
22
  import java.awt.*;
14
23
  import java.awt.event.WindowAdapter;
@@ -26,8 +35,6 @@
26
35
  TestArpgWalk() {
27
36
  super("Title");
28
37
  setDefaultCloseOperation(EXIT_ON_CLOSE);
29
- setSize(600, 600);
30
- setLocationRelativeTo(null);
31
38
 
32
39
  GamePanel gamePanel = new GamePanel();
33
40
  setContentPane(gamePanel);
@@ -49,6 +56,9 @@
49
56
  windowDeactivated(e);
50
57
  }
51
58
  });
59
+
60
+ pack();
61
+ setLocationRelativeTo(null);
52
62
  }
53
63
  }
54
64
 
@@ -58,13 +68,19 @@
58
68
 
59
69
  public GamePanel() {
60
70
  super(null);
71
+ setSize(600, 600);
72
+ setPreferredSize(getSize());
73
+ setMinimumSize(getSize());
74
+
75
+ setBackground(new Color(0x80c080));
61
76
 
62
77
  charaList.add(new Hero());
63
78
  charaList.add(new Enemy());
64
79
  }
65
80
 
66
81
  void resume() {
82
+ if(gameLoop != null) throw new IllegalStateException("'gameLoop' NOT null");
67
- gameLoop = new Timer(20, e -> { gameTick(); repaint(); } );
83
+ gameLoop = new Timer(20, e -> { tick(); repaint(); } );
68
84
  gameLoop.start();
69
85
  }
70
86
 
@@ -76,12 +92,12 @@
76
92
  }
77
93
 
78
94
  @Override
79
- public void paintComponent(Graphics g) {
95
+ synchronized public void paintComponent(Graphics g) {
80
96
  super.paintComponent(g);
81
97
  for(Character c : charaList) c.draw(g);
82
98
  }
83
99
 
84
- private void gameTick() {
100
+ synchronized private void tick() {
85
101
  logic();
86
102
  }
87
103
 

5

修正

2023/10/04 06:51

投稿

jimbe
jimbe

スコア12721

test CHANGED
@@ -1,4 +1,5 @@
1
- Swing では paint ではなく paintComponent をOverride して下さい。
1
+ JFrame に直接ペイントせず、 JPanel を土台に paintComponent を Override して直接(間に offscreen の image を挟まず)描画して下さい。
2
+ Swingはデフォルトでダブルバッファリングを行います。
2
3
 
3
4
  >これまでに描画していた、画像をがrepaintメソッドを呼び出しても、
4
5
  >描画されてしまっています。

4

コード追加

2023/10/04 04:42

投稿

jimbe
jimbe

スコア12721

test CHANGED
@@ -5,5 +5,129 @@
5
5
 
6
6
  これまでに描画していたモノを消していないなら残っているのは当然ではないでしょうか。
7
7
 
8
+ ---
9
+ JFrame を直接使うのではなく、 JPanel で Timer を使って gameTick() メソッドを呼び出し、 Hiro と Enemy を動かします。
10
+ Character はそれぞれが draw() メソッドで自身を描画します。
11
+ ```java
12
+ import java.awt.*;
13
+ import java.awt.event.WindowAdapter;
14
+ import java.awt.event.WindowEvent;
15
+ import java.util.ArrayList;
16
+ import java.util.List;
17
+
18
+ import javax.swing.*;
19
+
20
+ public class TestArpgWalk extends JFrame {
21
+ public static void main(String[] args) {
22
+ SwingUtilities.invokeLater(() -> new TestArpgWalk().setVisible(true));
23
+ }
24
+
25
+ TestArpgWalk() {
26
+ super("Title");
27
+ setDefaultCloseOperation(EXIT_ON_CLOSE);
28
+ setSize(600, 600);
29
+ setLocationRelativeTo(null);
30
+
31
+ GamePanel gamePanel = new GamePanel();
8
- ついでに、各クラスのカプセル化が全く出来ていません。
32
+ setContentPane(gamePanel);
33
+
34
+ addWindowListener(new WindowAdapter() {
35
+ @Override
36
+ public void windowActivated(WindowEvent e) {
37
+ //System.out.println("windowActivated");
38
+ gamePanel.resume();
39
+ }
40
+ @Override
9
- 各クラスの役割をはっきりさせ、クラス間のインターフェースを最小にするようにしたほうが良いと思います。
41
+ public void windowDeactivated(WindowEvent e) {
42
+ //System.out.println("windowDeactivated");
43
+ gamePanel.pause();
44
+ }
45
+ @Override
46
+ public void windowClosing(WindowEvent e) {
47
+ //System.out.println("windowClosing");
48
+ windowDeactivated(e);
49
+ }
50
+ });
51
+ }
52
+ }
53
+
54
+ class GamePanel extends JPanel {
55
+ private List<Character> charaList = new ArrayList<>();
56
+ private Timer gameLoop;
57
+
58
+ public GamePanel() {
59
+ super(null);
60
+
61
+ charaList.add(new Hero());
62
+ charaList.add(new Enemy());
63
+ }
64
+
65
+ void resume() {
66
+ gameLoop = new Timer(20, e -> { gameTick(); repaint(); } );
67
+ gameLoop.start();
68
+ }
69
+
70
+ void pause() {
71
+ if(gameLoop != null) {
72
+ gameLoop.stop();
73
+ gameLoop = null;
74
+ }
75
+ }
76
+
77
+ @Override
78
+ public void paintComponent(Graphics g) {
79
+ super.paintComponent(g);
80
+ for(Character c : charaList) c.draw(g);
81
+ }
82
+
83
+ private void gameTick() {
84
+ logic();
85
+ }
86
+
87
+ private void logic() {
88
+ for(Character c : charaList) c.move();
89
+ }
90
+ }
91
+
92
+ abstract class Character {
93
+ protected Point point = new Point();
94
+
95
+ void move() {}
96
+ abstract void draw(Graphics g);
97
+ }
98
+
99
+ class Hero extends Character {
100
+ Hero() {
101
+ point.setLocation(20, 20);
102
+ }
103
+
104
+ @Override
105
+ void move() {
106
+ point.x++;
107
+ }
108
+
109
+ @Override
110
+ void draw(Graphics g) {
111
+ g.setColor(Color.RED);
112
+ g.fillRect(point.x, point.y, 30, 30);
113
+ }
114
+ }
115
+
116
+ class Enemy extends Character {
117
+ Enemy() {
118
+ point.setLocation(50, 50);
119
+ }
120
+
121
+ @Override
122
+ void move() {
123
+ point.x++;
124
+ point.y++;
125
+ }
126
+
127
+ @Override
128
+ void draw(Graphics g) {
129
+ g.setColor(Color.BLUE);
130
+ g.fillOval(point.x, point.y, 30, 30);
131
+ }
132
+ }
133
+ ```

3

間違いじゃなかった

2023/10/04 04:29

投稿

jimbe
jimbe

スコア12721

test CHANGED
@@ -1,4 +1,4 @@
1
- Swing では paint ではなく paintComponents をOverride して下さい。
1
+ Swing では paint ではなく paintComponent をOverride して下さい。
2
2
 
3
3
  >これまでに描画していた、画像をがrepaintメソッドを呼び出しても、
4
4
  >描画されてしまっています。

2

メソッド名間違い

2023/10/04 03:02

投稿

jimbe
jimbe

スコア12721

test CHANGED
@@ -1,4 +1,4 @@
1
- Swing では paint ではなく paintComponent をOverride して下さい。
1
+ Swing では paint ではなく paintComponents をOverride して下さい。
2
2
 
3
3
  >これまでに描画していた、画像をがrepaintメソッドを呼び出しても、
4
4
  >描画されてしまっています。

1

追記

2023/10/04 02:07

投稿

jimbe
jimbe

スコア12721

test CHANGED
@@ -4,3 +4,6 @@
4
4
  >描画されてしまっています。
5
5
 
6
6
  これまでに描画していたモノを消していないなら残っているのは当然ではないでしょうか。
7
+
8
+ ついでに、各クラスのカプセル化が全く出来ていません。
9
+ 各クラスの役割をはっきりさせ、クラス間のインターフェースを最小にするようにしたほうが良いと思います。