回答編集履歴

3

Birdクラス内の Bird. を self. に変更

2019/12/01 13:32

投稿

shiracamus
shiracamus

スコア5406

test CHANGED
@@ -202,31 +202,31 @@
202
202
 
203
203
  def _collision_detection(self):
204
204
 
205
- if self.x - Bird.RADIAN < 0:
205
+ if self.x - self.RADIAN < 0:
206
206
 
207
207
  self.vx *= -1
208
208
 
209
- self.x = Bird.RADIAN
209
+ self.x = self.RADIAN
210
-
210
+
211
- if self.x + Bird.RADIAN > Field.WIDTH:
211
+ if self.x + self.RADIAN > Field.WIDTH:
212
212
 
213
213
  self.vx *= -1
214
214
 
215
- self.x = Field.WIDTH - Bird.RADIAN
215
+ self.x = Field.WIDTH - self.RADIAN
216
-
217
-
218
-
216
+
217
+
218
+
219
- if self.y - Bird.RADIAN < 0:
219
+ if self.y - self.RADIAN < 0:
220
220
 
221
221
  self.vy *= -1
222
222
 
223
- self.y = Bird.RADIAN
223
+ self.y = self.RADIAN
224
-
224
+
225
- if self.y + Bird.RADIAN > Field.HEIGHT:
225
+ if self.y + self.RADIAN > Field.HEIGHT:
226
226
 
227
227
  self.vy *= -1
228
228
 
229
- self.y = Field.HEIGHT - Bird.RADIAN
229
+ self.y = Field.HEIGHT - self.RADIAN
230
230
 
231
231
 
232
232
 
@@ -298,7 +298,7 @@
298
298
 
299
299
  self.update()
300
300
 
301
- drawer.create_oval(self.x - Bird.RADIAN, self.y - Bird.RADIAN, self.x+Bird.RADIAN, self.y+Bird.RADIAN)
301
+ drawer.create_oval(self.x - self.RADIAN, self.y - self.RADIAN, self.x+self.RADIAN, self.y+self.RADIAN)
302
302
 
303
303
  drawer.create_line(self.x, self.y, self.x + self.vx * 3, self.y + self.vy * 3)
304
304
 

2

問題修正

2019/12/01 13:32

投稿

shiracamus
shiracamus

スコア5406

test CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  ソースの理解を兼ねてリファクタリングしてみました。
16
16
 
17
- 上に指摘た行はコメントアウトしあり
17
+ 問題そうな部分も修正してした
18
18
 
19
19
 
20
20
 
@@ -242,9 +242,13 @@
242
242
 
243
243
  def update(self):
244
244
 
245
- #self.vx += self.r1 * self.v1.x + self.r2 * self.v2.x + self.r3 * self.v3.x
245
+ dx = self.r1 * self.v1.x + self.r2 * self.v2.x + self.r3 * self.v3.x
246
-
246
+
247
- #self.vy += self.r1 * self.v1.y + self.r2 * self.v2.y + self.r3 * self.v3.y
247
+ dy = self.r1 * self.v1.y + self.r2 * self.v2.y + self.r3 * self.v3.y
248
+
249
+ self.vx += dx if self.vx >= 0 else -dx
250
+
251
+ self.vy += dy if self.vy >= 0 else -dy
248
252
 
249
253
 
250
254
 

1

リファクタリング実施

2019/12/01 13:16

投稿

shiracamus
shiracamus

スコア5406

test CHANGED
@@ -1,4 +1,4 @@
1
- > ```python
1
+ ```python
2
2
 
3
3
  self.vx += self.r1 * self.v1.x + self.r2 * self.v2.x + self.r3 * self.v3.x
4
4
 
@@ -9,3 +9,333 @@
9
9
 
10
10
 
11
11
  self.vx, self.vy がどんどん変化して、どんどん早くなっていくと思うのですが、意図した動作ですか?
12
+
13
+
14
+
15
+ ソースの理解を兼ねてリファクタリングしてみました。
16
+
17
+ 上に指摘した行はコメントアウトしてあります。
18
+
19
+
20
+
21
+ ```python
22
+
23
+ import random
24
+
25
+ from statistics import mean
26
+
27
+ from tkinter import *
28
+
29
+
30
+
31
+
32
+
33
+ class Field:
34
+
35
+ WIDTH = 300
36
+
37
+ HEIGHT = 200
38
+
39
+
40
+
41
+
42
+
43
+ class Coordinate():
44
+
45
+
46
+
47
+ def __init__(self):
48
+
49
+ self.reset()
50
+
51
+
52
+
53
+ def reset(self):
54
+
55
+ self.x = 0
56
+
57
+ self.y = 0
58
+
59
+
60
+
61
+
62
+
63
+ class Bird():
64
+
65
+ NUM = 3
66
+
67
+ RADIAN = 10
68
+
69
+ SPEED = 5
70
+
71
+ VIEW = 50
72
+
73
+
74
+
75
+ @staticmethod
76
+
77
+ def setup():
78
+
79
+ Bird.birds = [Bird() for _ in range(Bird.NUM)]
80
+
81
+
82
+
83
+ def __init__(self):
84
+
85
+ self.x = random.randint(0, Field.WIDTH)
86
+
87
+ self.y = random.randint(0, Field.HEIGHT)
88
+
89
+ self.vx = random.randint(-self.SPEED, self.SPEED)
90
+
91
+ self.vy = random.randint(-self.SPEED, self.SPEED)
92
+
93
+ self.view = self.VIEW
94
+
95
+ self.inverse_x = Field.WIDTH - self.x
96
+
97
+ self.inverse_y = Field.HEIGHT - self.y
98
+
99
+ self.r1 = 2.0 # cohesion coefficient
100
+
101
+ self.r2 = 0.5 # separation coefficient
102
+
103
+ self.r3 = 1.0 # alignment coefficient
104
+
105
+
106
+
107
+ self.v1 = Coordinate()
108
+
109
+ self.v2 = Coordinate()
110
+
111
+ self.v3 = Coordinate()
112
+
113
+
114
+
115
+ def neighbors(self):
116
+
117
+ return [agent for agent in self.birds if agent != self]
118
+
119
+
120
+
121
+ # 結合
122
+
123
+ def cohesion(self):
124
+
125
+ neighbors = self.neighbors()
126
+
127
+ if not neighbors:
128
+
129
+ return
130
+
131
+ center_pull_coeff = 10
132
+
133
+ self.v1.x = mean([agent.x for agent in neighbors])
134
+
135
+ self.v1.y = mean([agent.y for agent in neighbors])
136
+
137
+ self.v1.x = (self.v1.x - self.x) / center_pull_coeff
138
+
139
+ self.v1.y = (self.v1.y - self.y) / center_pull_coeff
140
+
141
+
142
+
143
+ # 離脱
144
+
145
+ def separation(self):
146
+
147
+ personal_space = 50
148
+
149
+ for agent in self.neighbors():
150
+
151
+ dist = self.calc_distance(agent)
152
+
153
+ if dist and dist <= personal_space:
154
+
155
+ self.v2.x -= (agent.x - self.x) / dist
156
+
157
+ self.v2.y -= (agent.y - self.y) / dist
158
+
159
+
160
+
161
+ def _separation(self):
162
+
163
+ neighbors = self.neighbors()
164
+
165
+ if not neighbors:
166
+
167
+ return
168
+
169
+ self.v2.x = mean([agent.x for agent in neighbords]) - self.x
170
+
171
+ self.v2.y = mean([agent.y for agent in neighbords]) - self.y
172
+
173
+
174
+
175
+ # 距離の計算
176
+
177
+ def calc_distance(self, target):
178
+
179
+ return ((target.x - self.x) ** 2 + (target.y - self.y) ** 2) ** 0.5
180
+
181
+
182
+
183
+ # 整列
184
+
185
+ def alignment(self):
186
+
187
+ neighbors = self.neighbors()
188
+
189
+ if not neighbors:
190
+
191
+ return
192
+
193
+ self.v3.x = mean([agent.x for agent in neighbors])
194
+
195
+ self.v3.y = mean([agent.y for agent in neighbors])
196
+
197
+ self.v3.x = (self.v3.x - self.vx) / 2
198
+
199
+ self.v3.y = (self.v3.y - self.vy) / 2
200
+
201
+
202
+
203
+ def _collision_detection(self):
204
+
205
+ if self.x - Bird.RADIAN < 0:
206
+
207
+ self.vx *= -1
208
+
209
+ self.x = Bird.RADIAN
210
+
211
+ if self.x + Bird.RADIAN > Field.WIDTH:
212
+
213
+ self.vx *= -1
214
+
215
+ self.x = Field.WIDTH - Bird.RADIAN
216
+
217
+
218
+
219
+ if self.y - Bird.RADIAN < 0:
220
+
221
+ self.vy *= -1
222
+
223
+ self.y = Bird.RADIAN
224
+
225
+ if self.y + Bird.RADIAN > Field.HEIGHT:
226
+
227
+ self.vy *= -1
228
+
229
+ self.y = Field.HEIGHT - Bird.RADIAN
230
+
231
+
232
+
233
+ def step(self):
234
+
235
+ self.cohesion()
236
+
237
+ self.separation()
238
+
239
+ self.alignment()
240
+
241
+
242
+
243
+ def update(self):
244
+
245
+ #self.vx += self.r1 * self.v1.x + self.r2 * self.v2.x + self.r3 * self.v3.x
246
+
247
+ #self.vy += self.r1 * self.v1.y + self.r2 * self.v2.y + self.r3 * self.v3.y
248
+
249
+
250
+
251
+ distance = (self.vx ** 2 + self.vy ** 2) ** 0.5
252
+
253
+ if distance > self.SPEED:
254
+
255
+ self.vx = (self.vx / distance) * self.SPEED
256
+
257
+ self.vy = (self.vy / distance) * self.SPEED
258
+
259
+
260
+
261
+ self.x += int(self.vx)
262
+
263
+ self.y += int(self.vy)
264
+
265
+
266
+
267
+ self._collision_detection()
268
+
269
+ print(self.vx, self.vy)
270
+
271
+
272
+
273
+ self.inverse_x = Field.WIDTH - self.x
274
+
275
+ self.inverse_y = Field.HEIGHT - self.y
276
+
277
+
278
+
279
+ def clear_movement(self):
280
+
281
+ self.v1.reset()
282
+
283
+ self.v2.reset()
284
+
285
+ self.v3.reset()
286
+
287
+
288
+
289
+ def draw(self, drawer):
290
+
291
+ self.clear_movement()
292
+
293
+ self.step()
294
+
295
+ self.update()
296
+
297
+ drawer.create_oval(self.x - Bird.RADIAN, self.y - Bird.RADIAN, self.x+Bird.RADIAN, self.y+Bird.RADIAN)
298
+
299
+ drawer.create_line(self.x, self.y, self.x + self.vx * 3, self.y + self.vy * 3)
300
+
301
+
302
+
303
+ def main():
304
+
305
+ Bird.setup()
306
+
307
+
308
+
309
+ root = Tk()
310
+
311
+
312
+
313
+ canvas = Canvas(root, width=Field.WIDTH, height=Field.HEIGHT)
314
+
315
+ canvas.pack()
316
+
317
+
318
+
319
+ def animate():
320
+
321
+ canvas.delete("all")
322
+
323
+ for bird in Bird.birds:
324
+
325
+ bird.draw(canvas)
326
+
327
+ root.after(20, animate)
328
+
329
+
330
+
331
+ animate()
332
+
333
+ root.mainloop()
334
+
335
+
336
+
337
+ if __name__ == '__main__':
338
+
339
+ main()
340
+
341
+ ```