-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathBulletEmiter.cs
293 lines (253 loc) · 7.36 KB
/
BulletEmiter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
using UnityEngine;
namespace Sample07
{
public class EmiterData
{
/// <summary>
/// 发射CD
/// </summary>
public float emitCD = 1;
/// <summary>
/// 允许角度偏移计算
/// </summary>
public bool enableAngleRange;
/// <summary>
/// 允许位置偏移计算
/// </summary>
public bool enablePositionRange;
/// <summary>
/// 允许反向折回
/// </summary>
public bool enableReverse;
/// <summary>
/// 每次发射的组数。一组又包括若干个子弹
/// </summary>
public int groupCount = 1;
/// <summary>
/// 组之间的间隔时间
/// </summary>
public float groupTimeDelta;
/// <summary>
/// 发射角度范围起始点
/// </summary>
public float angleBegin = 0;
/// <summary>
/// 发射角度范围终点
/// </summary>
public float angleEnd = 360;
public Vector2 positionBegin;
public Vector2 positionEnd;
public Vector2 bulletVelocity = new Vector2(0, 1.0f);
#region 以下是单次发射的参数
/// <summary>
/// 单次发射的子弹数量
/// </summary>
public int bulletCount = 1;
/// <summary>
/// 每个子弹的时间间隔
/// </summary>
public float bulletTimeDelta;
/// <summary>
/// 每个子弹的角度间隔
/// </summary>
public float bulletAngleDelta;
/// <summary>
/// 每个子弹的位置偏移
/// </summary>
public Vector2 bulletPositionDelta;
#endregion
}
/// <summary>
/// 子弹发射器
/// </summary>
public class BulletEmiter
{
public Entity owner;
public EmiterData data;
public uint selfMask;
public uint collisionMask;
/// <summary>
/// 是否正在发射中
/// </summary>
bool isEmiting;
/// <summary>
/// 下次可发射子弹的时间. 受发射CD影响
/// </summary>
float nextEmitTime;
/// <summary>
/// 当前发射组索引
/// </summary>
int groupIndex = 0;
/// <summary>
/// 当前组内的子弹索引
/// </summary>
int bulletIndex = 0;
/// <summary>
/// 折回的正负
/// </summary>
float reverseSign = 1;
/// <summary>
/// 发射器当前偏移位置
/// </summary>
Vector2 position;
/// <summary>
/// 发射器当前偏移角度
/// </summary>
float angle;
public void Reset()
{
isEmiting = false;
nextEmitTime = 0;
}
public void Update(float deltaTime)
{
if (isEmiting)
{
OnEmitUpdate();
}
}
public void Fire()
{
if (isEmiting)
{
return;
}
if (owner.game.gameTime > nextEmitTime)
{
OnEmitStart();
}
}
void OnEmitStart()
{
isEmiting = true;
nextEmitTime = owner.game.gameTime;
groupIndex = 0;
bulletIndex = 0;
position = data.positionBegin;
angle = data.angleBegin;
reverseSign = 1;
}
void OnEmitFinish()
{
isEmiting = false;
nextEmitTime += data.emitCD;
}
void OnEmitUpdate()
{
float gameTime = owner.game.gameTime;
for (; bulletIndex < data.bulletCount && nextEmitTime < gameTime; ++bulletIndex)
{
EmitOneBullet();
nextEmitTime += data.bulletTimeDelta;
AdvanceAngle();
AdvancePosition();
}
// 当前组还没有发射完. 单次发射时间用完了
if (bulletIndex < data.bulletCount)
{
return;
}
bulletIndex = 0;
position = data.positionBegin;
angle = data.angleBegin;
reverseSign = 1;
++groupIndex;
// 组还没有完
if (groupIndex < data.groupCount)
{
nextEmitTime += data.groupTimeDelta;
}
// 全部组都发射完毕了
else
{
OnEmitFinish();
}
}
void EmitOneBullet()
{
Vector2 pos = owner.rigidbody.position + position;
float rot = owner.rigidbody.rotation + angle;
Matrix2D mat = new Matrix2D();
mat.setRotate(rot);
Vector2 velocity = mat.transformVector(data.bulletVelocity);
Bullet bullet = new Bullet
{
owner = owner,
initData = new EntityInitData
{
position = pos,
rotation = rot,
scale = new Vector2(0.1f, 0.5f),
velocity = owner.rigidbody.velocity + velocity,
selfMask = selfMask,
collisionMask = collisionMask,
mass = 0.001f,
inertial = 0.001f,
color = owner.initData.color,
},
};
owner.game.AddEntity(bullet);
}
void AdvanceAngle()
{
float next = angle + data.bulletAngleDelta * reverseSign;
if (!data.enableAngleRange)
{
angle = next;
return;
}
if (reverseSign > 0 && next > data.angleEnd)
{
if (data.enableReverse)
{
reverseSign = -reverseSign;
angle = data.angleEnd;
}
else
{
angle = data.angleBegin;
}
}
else if (reverseSign < 0 && next < data.angleBegin)
{
reverseSign = -reverseSign;
angle = data.angleBegin;
}
else
{
angle = next;
}
}
void AdvancePosition()
{
Vector2 next = position + data.bulletPositionDelta * reverseSign;
if (!data.enablePositionRange)
{
position = next;
return;
}
float sqrDistance = (data.positionEnd - data.positionBegin).sqrMagnitude;
if (reverseSign > 0 && (next - data.positionBegin).sqrMagnitude > sqrDistance)
{
if (data.enableReverse)
{
reverseSign = -reverseSign;
position = data.positionEnd;
}
else
{
position = data.positionBegin;
}
}
else if (reverseSign < 0 && (next - data.positionEnd).sqrMagnitude > sqrDistance)
{
reverseSign = -reverseSign;
position = data.positionBegin;
}
else
{
position = next;
}
}
}
}