

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 镜头控制
6 /// </summary>
7 public class CameraControl : MonoBehaviour {
8
9 /// <summary>
10 /// 玩家
11 /// </summary>
12 private GameObject player = null;
13 /// <summary>
14 /// 玩家到相机的偏移
15 /// </summary>
16 public Vector3 offset;
17 /// <summary>
18 /// 玩家到相机的y轴偏移
19 /// </summary>
20 public Vector3 interest;
21 /// <summary>
22 /// 玩家的前一个位置
23 /// </summary>
24 public Vector3 player_position_prev;
25
26 void Start () {
27
28 //获取玩家
29 this.player = GameObject.FindGameObjectWithTag("NekoPlayer");
30 //计算玩家到相机的偏移
31 this.offset = this.transform.position - this.player.transform.position;
32 //计算玩家到相机的y轴偏移
33 this.interest = new Vector3(0.0f, this.transform.position.y - this.player.transform.position.y, 0.0f);
34 //玩家的前一个位置未玩家的初始位置
35 this.player_position_prev = this.player.transform.position;
36 }
37
38 void Update () {
39 //让相机跟随玩家
40 this.transform.position = new Vector3(player.transform.position.x + this.offset.x, player.transform.position.y + this.offset.y, player.transform.position.z + this.offset.z);
41 }
42 }

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 特效
6 /// </summary>
7 public class Effect:MonoBehaviour {
8
9 void Update() {
10 //特效不在播放状态,删除特效物体
11 if(!this.GetComponentInChildren<ParticleSystem>().isPlaying) {
12 Destroy(this.gameObject);
13 }
14 }
15 }

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 特效控制
6 /// </summary>
7 public class EffectControl:MonoBehaviour {
8
9 /// <summary>
10 /// 通过木窗特效
11 /// </summary>
12 public GameObject eff_break = null;
13 /// <summary>
14 /// Miss木窗特效
15 /// </summary>
16 public GameObject eff_miss = null;
17 /// <summary>
18 /// 摄像机
19 /// </summary>
20 public GameObject game_camera = null;
21
22 void Start() {
23 //获取相机引用
24 this.game_camera = GameObject.FindGameObjectWithTag("MainCamera");
25 }
26
27 void Update() {
28
29 }
30
31 /// <summary>
32 /// 创建通过木窗特效
33 /// </summary>
34 public void createBreakEffect(SyoujiPaperControl paper,NekoControl neko) {
35 GameObject go = Instantiate(this.eff_break) as GameObject;
36 go.AddComponent<Effect>();
37 Vector3 position = paper.transform.position;
38 position.x = neko.transform.position.x;
39 position.y = neko.transform.position.y;
40 position.y += 0.3f;
41 go.transform.position = position;
42 go.transform.parent = this.game_camera.transform;
43 }
44
45 /// <summary>
46 /// 创建Miss特效
47 /// </summary>
48 public void createMissEffect(NekoControl neko) {
49 GameObject go = Instantiate(this.eff_miss) as GameObject;
50 go.AddComponent<Effect>();
51 Vector3 position = neko.transform.position;
52 position.y += 0.3f;
53 position.z -= 0.2f;
54 go.transform.position = position;
55 }
56 }

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 控制单间房间(窗户的关闭等)
6 /// </summary>
7 public class FloorControl:MonoBehaviour {
8
9 /// <summary>
10 /// 状态
11 /// </summary>
12 public enum STEP {
13 /// <summary>
14 /// 默认
15 /// </summary>
16 NONE = -1,
17 /// <summary>
18 /// 关闭
19 /// </summary>
20 CLOSE = 0,
21 /// <summary>
22 /// 打开
23 /// </summary>
24 OPEN,
25 /// <summary>
26 /// 打开中
27 /// </summary>
28 TO_OPEN,
29 /// <summary>
30 /// 关闭
31 /// </summary>
32 CLOSE_SHOJI,
33 /// <summary>
34 /// 关闭中
35 /// </summary>
36 TO_CLOSE_SHOJI,
37 /// <summary>
38 /// 最大值
39 /// </summary>
40 NUM,
41 };
42
43 /// <summary>
44 /// 当前状态
45 /// </summary>
46 public STEP step = STEP.NONE;
47 /// <summary>
48 /// 下一个状态
49 /// </summary>
50 public STEP next_step = STEP.NONE;
51 /// <summary>
52 /// 状态计时
53 /// </summary>
54 public float step_timer = 0.0f;
55 /// <summary>
56 /// 上一个状态计时器
57 /// </summary>
58 public float step_timer_prev = 0.0f;
59
60
61 /// <summary>
62 /// 木窗预设
63 /// </summary>
64 public GameObject shojiPrefab = null;
65 /// <summary>
66 /// 门预设
67 /// </summary>
68 public GameObject fusumaPrefab = null;
69
70 /// <summary>
71 /// 门,木窗的z坐标
72 /// </summary>
73 public static float SHUTTER_POSITION_Z = 15.0f;
74 /// <summary>
75 /// 开启状态下 门,木窗的x坐标
76 /// </summary>
77 public static float SHUTTER_POSITION_OPEN_X = 4.1f;
78 /// <summary>
79 /// 关闭状态下 门,木窗的x坐标
80 /// </summary>
81 public static float SHUTTER_POSITION_CLOSE_X = 1.35f;
82
83 /// <summary>
84 /// 门数量
85 /// </summary>
86 public static int FUSUMA_NUM = 2;
87 /// <summary>
88 /// 木窗数量
89 /// </summary>
90 public static int SHOJI_NUM = 1;
91
92 /// <summary>
93 /// 门
94 /// </summary>
95 private GameObject[] fusuma_objects;
96 /// <summary>
97 /// 木窗
98 /// </summary>
99 private ShojiControl shoji_object = null;
100
101
102 /// <summary>
103 /// 关门模式类型
104 /// </summary>
105 public enum CLOSING_PATTERN_TYPE {
106 /// <summary>
107 /// 默认
108 /// </summary>
109 NONE = -1,
110 /// <summary>
111 /// 普通
112 /// </summary>
113 NORMAL = 0,
114 /// <summary>
115 /// 从右边的出现,向左停了
116 /// </summary>
117 OVERSHOOT,
118 /// <summary>
119 /// 第一次出现第二次出现
120 /// </summary>
121 SECONDTIME,
122 /// <summary>
123 /// 从左边拉窗和麸皮同时
124 /// </summary>
125 ARCODION,
126 /// <summary>
127 /// 从左边藏嘛,有点晚了,从右隔扇
128 /// </summary>
129 DELAY,
130 /// <summary>
131 /// 从上面落下拉窗
132 /// </summary>
133 FALLDOWN,
134 /// <summary>
135 /// 麸皮2张(张)后,右边来就拉着拉窗拉
136 /// </summary>
137 FLIP,
138 /// <summary>
139 /// 慢慢地
140 /// </summary>
141 SLOW,
142 /// <summary>
143 /// 从左边藏嘛,超市晚从右隔扇
144 /// </summary>
145 SUPER_DELAY,
146 /// <summary>
147 /// 上限
148 /// </summary>
149 NUM,
150 };
151
152 /// <summary>
153 /// 关门模式类型
154 /// </summary>
155 public CLOSING_PATTERN_TYPE closing_pattern_type = CLOSING_PATTERN_TYPE.NORMAL;
156 /// <summary>
157 ///
158 /// </summary>
159 public bool is_flip_closing = false; // 登場パターンを左右反転する?.
160
161 /// <summary>
162 /// 关门模式
163 /// </summary>
164 public struct ClosingPattern {
165
166 public float total_time; // トータルの時間.
167 public int fusuma_num; // ふすまの数.
168
169 // 毎フレーム更新.
170
171 public float[] fusuma_x; // 各ふすまのX座標(毎フレーム更新).
172 public float shoji_x; // 障子のX座標(毎フレーム更新).
173 public float shoji_y;
174 public float shoji_z_offset; // 障子のZ座標のオフセット(毎フレーム更新).
175
176 public float[] fusuma_rot_x; // 各ふすまのX座標(毎フレーム更新).
177 public float shoji_rot_x; // 障子のX座標(毎フレーム更新).
178
179 public bool is_play_close_sound; // 障子が閉まっているときの SE を鳴らす.
180 public bool is_play_close_end_sound; // 障子が閉まりきったときの SE を鳴らす.
181
182 public float se_volume;
183 public float se_pitch; // SE のピッチ.
184
185 public float previous_distance; // 前のフレームでの、RoomControl.getDistanceNekoToShutter()
186 public float local_timer;
187
188 public ClosingPatternParam param; // 汎用パラメーター
189 };
190
191 /// <summary>
192 /// 关门模式参数
193 /// </summary>
194 public struct ClosingPatternParam {
195
196 public float as_float;
197 public bool as_bool;
198 }
199
200 /// <summary>
201 /// 关门模式参数
202 /// </summary>
203 public ClosingPattern closing_pattern;
204
205 /// <summary>
206 /// 关闭声音
207 /// </summary>
208 public AudioClip CLOSE_SOUND = null;
209 /// <summary>
210 /// 关闭结束声音
211 /// </summary>
212 public AudioClip CLOSE_END_SOUND = null;
213
214 // ---------------------------------------------------------------- //
215
216 void Start() {
217 //创建门
218 this.fusuma_objects = new GameObject[FUSUMA_NUM];
219 for(int i = 0;i < FUSUMA_NUM;i++) {
220 this.fusuma_objects[i] = Instantiate(this.fusumaPrefab) as GameObject;
221 this.fusuma_objects[i].transform.parent = this.gameObject.transform;
222 this.fusuma_objects[i].transform.localPosition = new Vector3(SHUTTER_POSITION_OPEN_X,0.0f,SHUTTER_POSITION_Z);
223 }
224
225 this.closing_pattern_type = CLOSING_PATTERN_TYPE.NORMAL;
226 }
227
228 void Update() {
229 this.step_timer_prev = this.step_timer;
230 this.step_timer += Time.deltaTime;
231
232 //打开中状态持续时间
233 const float to_open_time = 0.5f;
234
235 if(this.next_step == STEP.NONE) {
236 switch(this.step) {
237 case STEP.TO_OPEN: {
238 if(this.step_timer > to_open_time) {
239 this.next_step = STEP.OPEN;
240 }
241 }
242 break;
243 case STEP.TO_CLOSE_SHOJI: {
244 if(this.step_timer > this.closing_pattern.total_time + Time.deltaTime) {
245 this.next_step = STEP.CLOSE_SHOJI;
246 }
247 }
248 break;
249 }
250 }
251
252 //处理下一个状态
253 if(this.next_step != STEP.NONE) {
254
255 switch(this.next_step) {
256
257 case STEP.CLOSE: {
258 this.reset_shutters();
259
260 this.fusuma_objects[0].SetActive(true);
261 this.fusuma_objects[1].SetActive(true);
262
263 this.fusuma_objects[0].GetComponent<ShutterControl>().setX(-SHUTTER_POSITION_CLOSE_X);
264 this.fusuma_objects[1].GetComponent<ShutterControl>().setX(SHUTTER_POSITION_CLOSE_X);
265 }
266 break;
267
268 case STEP.OPEN: {
269 this.reset_shutters();
270
271 this.fusuma_objects[0].SetActive(true);
272 this.fusuma_objects[1].SetActive(true);
273
274 this.fusuma_objects[0].GetComponent<ShutterControl>().setX(-SHUTTER_POSITION_OPEN_X);
275 this.fusuma_objects[1].GetComponent<ShutterControl>().setX(SHUTTER_POSITION_OPEN_X);
276 }
277 break;
278
279 case STEP.TO_CLOSE_SHOJI: {
280 this.closing_pattern_init();
281 }
282 break;
283
284 case STEP.CLOSE_SHOJI: {
285 }
286 break;
287 }
288
289 this.step = this.next_step;
290 this.next_step = STEP.NONE;
291
292 this.step_timer_prev = -Time.deltaTime;
293 this.step_timer = 0.0f;
294 }
295
296 //处理当前状态
297 switch(this.step) {
298 //打开门
299 case STEP.TO_OPEN: {
300 float rate;
301 float x;
302
303 rate = Mathf.Clamp01(this.step_timer / to_open_time);
304 rate = Mathf.Sin(Mathf.Lerp(0.0f,Mathf.PI / 2.0f,rate));
305
306 x = Mathf.Lerp(SHUTTER_POSITION_CLOSE_X,SHUTTER_POSITION_OPEN_X,rate);
307
308 this.fusuma_objects[0].GetComponent<ShutterControl>().setX(x);
309
310 x = Mathf.Lerp(-SHUTTER_POSITION_CLOSE_X,-SHUTTER_POSITION_OPEN_X,rate);
311
312 this.fusuma_objects[1].GetComponent<ShutterControl>().setX(x);
313 }
314 break;
315
316 case STEP.TO_CLOSE_SHOJI: {
317 this.closing_pattern_execute();
318 }
319 break;
320
321 }
322
323 // ---------------------------------------------------------------- //
324 }
325
326 /// <summary>
327 /// 重置门
328 /// </summary>
329 private void reset_shutters() {
330 for(int i = 0;i < this.fusuma_objects.Length;i++) {
331 this.fusuma_objects[i].SetActive(false);
332 }
333 }
334
335 /// <summary>
336 /// 关门模式初始化
337 /// </summary>
338 private void closing_pattern_init() {
339 switch(this.closing_pattern_type) {
340
341 case CLOSING_PATTERN_TYPE.NORMAL: {
342 this.closing_pattern.fusuma_num = 1;
343 this.closing_pattern.total_time = 0.5f;
344 }
345 break;
346
347 case CLOSING_PATTERN_TYPE.OVERSHOOT: {
348 this.closing_pattern.fusuma_num = 2;
349 this.closing_pattern.total_time = 1.0f;
350 }
351 break;
352
353 case CLOSING_PATTERN_TYPE.SECONDTIME: {
354 this.closing_pattern.fusuma_num = 2;
355 this.closing_pattern.total_time = 1.0f;
356 }
357 break;
358
359 case CLOSING_PATTERN_TYPE.ARCODION: {
360 this.closing_pattern.fusuma_num = 1;
361 this.closing_pattern.total_time = 0.5f;
362 }
363 break;
364
365 case CLOSING_PATTERN_TYPE.DELAY: {
366 this.closing_pattern.fusuma_num = 1;
367 this.closing_pattern.total_time = 0.8f;
368 }
369 break;
370
371 case CLOSING_PATTERN_TYPE.FALLDOWN: {
372 this.closing_pattern.fusuma_num = 2;
373 this.closing_pattern.total_time = 1.0f;
374 }
375 break;
376
377 case CLOSING_PATTERN_TYPE.FLIP: {
378 this.closing_pattern.fusuma_num = 2;
379 this.closing_pattern.total_time = 1.0f;
380 }
381 break;
382
383 case CLOSING_PATTERN_TYPE.SLOW: {
384 this.closing_pattern.fusuma_num = 2;
385 //this.closing_pattern.total_time = 2.0f;
386 this.closing_pattern.total_time = this.closing_pattern.param.as_float;
387 }
388 break;
389
390 case CLOSING_PATTERN_TYPE.SUPER_DELAY: {
391 this.closing_pattern.fusuma_num = 1;
392 this.closing_pattern.total_time = 2.5f;
393
394 }
395 break;
396 }
397
398 this.closing_pattern.fusuma_x = new float[this.closing_pattern.fusuma_num];
399 this.closing_pattern.fusuma_rot_x = new float[this.closing_pattern.fusuma_num];
400
401 //
402
403 this.reset_shutters();
404
405 for(int i = 0;i < this.closing_pattern.fusuma_num;i++) {
406
407 this.fusuma_objects[i].SetActive(true);
408
409 this.closing_pattern.fusuma_x[i] = -SHUTTER_POSITION_OPEN_X;
410
411 this.closing_pattern.fusuma_rot_x[i] = 0.0f;
412 }
413
414 this.closing_pattern.shoji_x = SHUTTER_POSITION_OPEN_X;
415
416 this.closing_pattern.shoji_rot_x = 0.0f;
417
418 // 左側にあるふすまを左右反転する.
419 //
420
421 Vector3 scale = new Vector3(-1.0f,1.0f,1.0f);
422
423 if(this.is_flip_closing) {
424
425 scale.x *= -1.0f;
426 }
427
428 this.fusuma_objects[0].transform.localScale = scale;
429
430 scale.x *= -1.0f;
431
432 for(int i = 1;i < this.closing_pattern.fusuma_num;i++) {
433
434 this.fusuma_objects[i].transform.localScale = scale;
435 }
436
437 }
438
439 // ステップタイマーが time をまたいだ?.
440 private bool is_step_timer_reach(float time) {
441 bool ret = false;
442
443 if(this.step_timer_prev < time && time <= this.step_timer) {
444
445 ret = true;
446 }
447
448 return (ret);
449 }
450
451 // 登場パターンの実行.
452 private void closing_pattern_execute() {
453 float rate;
454
455 // 「毎フレーム更新する値」を初期化しておく.
456
457 for(int i = 0;i < this.closing_pattern.fusuma_num;i++) {
458
459 this.closing_pattern.fusuma_x[i] = SHUTTER_POSITION_OPEN_X;
460 this.closing_pattern.fusuma_rot_x[i] = 0.0f;
461 }
462
463 this.closing_pattern.shoji_x = SHUTTER_POSITION_OPEN_X;
464 this.closing_pattern.shoji_y = 0.0f;
465 this.closing_pattern.shoji_z_offset = 0.0f;
466 this.closing_pattern.shoji_rot_x = 0.0f;
467
468 this.closing_pattern.is_play_close_sound = false;
469 this.closing_pattern.is_play_close_end_sound = false;
470
471 this.closing_pattern.se_volume = 1.0f;
472 this.closing_pattern.se_pitch = 1.0f;
473
474 // 現在の位置、回転等を更新する.
475
476 switch(this.closing_pattern_type) {
477
478 case CLOSING_PATTERN_TYPE.NORMAL: {
479 rate = Mathf.Clamp01(this.step_timer / this.closing_pattern.total_time);
480 rate = Mathf.Sin(Mathf.Lerp(0.0f,Mathf.PI / 2.0f,rate));
481
482 this.closing_pattern.shoji_x = Mathf.Lerp(SHUTTER_POSITION_OPEN_X,SHUTTER_POSITION_CLOSE_X,rate);
483
484 this.closing_pattern.fusuma_x[0] = Mathf.Lerp(-SHUTTER_POSITION_OPEN_X,-SHUTTER_POSITION_CLOSE_X,rate);
485
486 if(this.is_step_timer_reach(0.0f)) {
487
488 this.closing_pattern.is_play_close_sound = true;
489 }
490 if(this.is_step_timer_reach(this.closing_pattern.total_time)) {
491
492 this.closing_pattern.is_play_close_end_sound = true;
493 }
494 }
495 break;
496
497 case CLOSING_PATTERN_TYPE.OVERSHOOT: {
498 rate = Mathf.Clamp01(this.step_timer / this.closing_pattern.total_time);
499 rate = Mathf.Sin(Mathf.Lerp(0.0f,Mathf.PI / 2.0f,rate));
500
501 this.closing_pattern.shoji_x = Mathf.Lerp(SHUTTER_POSITION_OPEN_X,-SHUTTER_POSITION_CLOSE_X,rate);
502
503 if(rate < 0.5f) {
504
505 rate = Mathf.InverseLerp(0.0f,0.5f,rate);
506
507 this.closing_pattern.fusuma_x[0] = Mathf.Lerp(-SHUTTER_POSITION_OPEN_X,-SHUTTER_POSITION_CLOSE_X,rate);
508
509 } else {
510
511 rate = Mathf.InverseLerp(0.5f,1.0f,rate);
512
513 this.closing_pattern.fusuma_x[0] = Mathf.Lerp(-SHUTTER_POSITION_CLOSE_X,-SHUTTER_POSITION_OPEN_X,rate);
514
515 this.closing_pattern.fusuma_x[1] = Mathf.Lerp(SHUTTER_POSITION_OPEN_X,SHUTTER_POSITION_CLOSE_X,rate);
516 }
517
518 if(this.is_step_timer_reach(0.0f)) {
519
520 this.closing_pattern.is_play_close_sound = true;
521 }
522 if(this.is_step_timer_reach(this.closing_pattern.total_time * Mathf.Asin(0.5f) / (Mathf.PI / 2.0f))) {
523
524 this.closing_pattern.is_play_close_end_sound = true;
525 }
526 }
527 break;
528
529 case CLOSING_PATTERN_TYPE.SECONDTIME: {
530 rate = Mathf.Clamp01(this.step_timer / this.closing_pattern.total_time);
531 rate = Mathf.Sin(Mathf.Lerp(0.0f,Mathf.PI / 2.0f,rate));
532
533 this.closing_pattern.fusuma_x[1] = Mathf.Lerp(SHUTTER_POSITION_OPEN_X,-SHUTTER_POSITION_CLOSE_X,rate);
534
535 if(rate < 0.5f) {
536
537 rate = Mathf.InverseLerp(0.0f,0.5f,rate);
538
539 this.closing_pattern.fusuma_x[0] = Mathf.Lerp(-SHUTTER_POSITION_OPEN_X,-SHUTTER_POSITION_CLOSE_X,rate);
540
541 } else {
542
543 rate = Mathf.InverseLerp(0.5f,1.0f,rate);
544
545 this.closing_pattern.fusuma_x[0] = Mathf.Lerp(-SHUTTER_POSITION_CLOSE_X,-SHUTTER_POSITION_OPEN_X,rate);
546
547 this.closing_pattern.shoji_x = Mathf.Lerp(SHUTTER_POSITION_OPEN_X,SHUTTER_POSITION_CLOSE_X,rate);
548 }
549
550 if(this.is_step_timer_reach(0.0f)) {
551
552 this.closing_pattern.is_play_close_sound = true;
553 }
554 if(this.is_step_timer_reach(this.closing_pattern.total_time * Mathf.Asin(0.5f) / (Mathf.PI / 2.0f))) {
555
556 this.closing_pattern.is_play_close_end_sound = true;
557 }
558 }
559 break;
560
561 case CLOSING_PATTERN_TYPE.ARCODION: {
562 rate = Mathf.Clamp01(this.step_timer / this.closing_pattern.total_time);
563 rate = Mathf.Sin(Mathf.Lerp(0.0f,Mathf.PI / 2.0f,rate));
564
565 this.closing_pattern.shoji_x = Mathf.Lerp(-SHUTTER_POSITION_OPEN_X,SHUTTER_POSITION_CLOSE_X,rate);
566 this.closing_pattern.shoji_z_offset = 0.01f;
567
568 this.closing_pattern.fusuma_x[0] = Mathf.Lerp(-SHUTTER_POSITION_OPEN_X,-SHUTTER_POSITION_CLOSE_X,rate);
569
570 if(this.is_step_timer_reach(0.0f)) {
571
572 this.closing_pattern.is_play_close_sound = true;
573 }
574 if(this.is_step_timer_reach(this.closing_pattern.total_time)) {
575
576 this.closing_pattern.is_play_close_end_sound = true;
577 }
578 }
579 break;
580
581 case CLOSING_PATTERN_TYPE.DELAY: {
582 rate = Mathf.Clamp01(this.step_timer / this.closing_pattern.total_time);
583
584 const float time0 = 0.3f;
585 const float time1 = 0.7f;
586
587 if(rate < time0) {
588
589 // 右側にふすまがさっとしまる.
590
591 rate = Mathf.InverseLerp(0.0f,time0,rate);
592 rate = Mathf.Sin(Mathf.Lerp(0.0f,Mathf.PI / 2.0f,rate));
593
594 this.closing_pattern.fusuma_x[0] = Mathf.Lerp(-SHUTTER_POSITION_OPEN_X,-SHUTTER_POSITION_CLOSE_X,rate);
595 this.closing_pattern.shoji_x = SHUTTER_POSITION_OPEN_X;
596
597 } else if(rate < time1) {
598
599 // しばらくためる.
600
601 this.closing_pattern.fusuma_x[0] = -SHUTTER_POSITION_CLOSE_X;
602 this.closing_pattern.shoji_x = SHUTTER_POSITION_OPEN_X;
603
604 } else {
605
606 // 左側に障子がさっとしまる.
607
608 rate = Mathf.InverseLerp(time1,1.0f,rate);
609 rate = Mathf.Sin(Mathf.Lerp(0.0f,Mathf.PI / 2.0f,rate));
610
611 this.closing_pattern.fusuma_x[0] = -SHUTTER_POSITION_CLOSE_X;
612
613 if(this.closing_pattern.param.as_bool) {
614
615 // 障子が左から(ふすまの裏から)出てくる.
616
617 this.closing_pattern.shoji_x = Mathf.Lerp(-SHUTTER_POSITION_CLOSE_X,SHUTTER_POSITION_CLOSE_X,rate);
618
619 // ふすまのモデルからはみ出ないよう、少し後ろにずらす.
620 this.closing_pattern.shoji_z_offset = 0.01f;
621
622 } else {
623
624 this.closing_pattern.shoji_x = Mathf.Lerp(SHUTTER_POSITION_OPEN_X,SHUTTER_POSITION_CLOSE_X,rate);
625 }
626 }
627
628 if(this.is_step_timer_reach(0.0f)) {
629
630 this.closing_pattern.is_play_close_sound = true;
631 this.closing_pattern.se_pitch = 2.0f;
632 }
633 if(this.is_step_timer_reach(this.closing_pattern.total_time * time1)) {
634
635 this.closing_pattern.is_play_close_sound = true;
636 this.closing_pattern.se_pitch = 2.0f;
637 }
638 if(this.is_step_timer_reach(this.closing_pattern.total_time)) {
639
640 this.closing_pattern.is_play_close_end_sound = true;
641 this.closing_pattern.se_pitch = 1.5f;
642 }
643 }
644 break;
645
646 case CLOSING_PATTERN_TYPE.FALLDOWN: {
647 const float height0 = 6.0f;
648 const float height1 = height0 / 16.0f;
649
650 rate = Mathf.Clamp01(this.step_timer / this.closing_pattern.total_time);
651
652 if(rate < 0.1f) {
653
654 // 両側からふすまが閉まる(だいぶすき間をあけて).
655
656 rate = Mathf.InverseLerp(0.0f,0.1f,rate);
657
658 this.closing_pattern.fusuma_x[0] = Mathf.Lerp(-SHUTTER_POSITION_OPEN_X,-SHUTTER_POSITION_CLOSE_X * 2.0f,rate);
659 this.closing_pattern.fusuma_x[1] = Mathf.Lerp(SHUTTER_POSITION_OPEN_X,SHUTTER_POSITION_CLOSE_X * 2.0f,rate);
660
661 this.closing_pattern.shoji_y = height0;
662
663 } else {
664
665 // 上から障子が落ちてくる.
666
667 rate = Mathf.InverseLerp(0.1f,1.0f,rate);
668
669 this.closing_pattern.fusuma_x[0] = -SHUTTER_POSITION_CLOSE_X * 2.0f;
670 this.closing_pattern.fusuma_x[1] = SHUTTER_POSITION_CLOSE_X * 2.0f;
671
672 this.closing_pattern.shoji_x = 0.0f;
673
674 //
675
676 const float fall_time0 = 0.5f;
677 const float fall_time1 = 0.75f;
678
679 if(rate < fall_time0) {
680
681 rate = Mathf.InverseLerp(0.0f,fall_time0,rate);
682
683 rate = rate * rate;
684
685 this.closing_pattern.shoji_y = Mathf.Lerp(height0,0.0f,rate);
686
687 } else if(rate < fall_time1) {
688
689 // バウンドする.
690
691 this.closing_pattern.shoji_x = 0.0f;
692
693 rate = Mathf.InverseLerp(fall_time0,fall_time1,rate);
694
695 rate = Mathf.Lerp(-1.0f,1.0f,rate);
696
697 rate = 1.0f - rate * rate;
698
699 this.closing_pattern.shoji_y = Mathf.Lerp(0.0f,height1,rate);
700
701 } else {
702
703 Vector3 position = this.shoji_object.transform.position;
704
705 position.y = 0.0f;
706
707 this.shoji_object.transform.position = position;
708 }
709 }
710
711 if(this.is_step_timer_reach(0.0f)) {
712
713 this.closing_pattern.is_play_close_sound = true;
714 this.closing_pattern.se_pitch = 3.0f;
715 }
716 if(this.is_step_timer_reach(this.closing_pattern.total_time * 0.1f)) {
717
718 this.closing_pattern.is_play_close_sound = true;
719 }
720 if(this.is_step_timer_reach(this.closing_pattern.total_time * (0.1f + 0.9f * 0.5f))) {
721
722 this.closing_pattern.is_play_close_end_sound = true;
723 }
724 if(this.is_step_timer_reach(this.closing_pattern.total_time * (0.1f + 0.9f * 0.75f))) {
725
726 this.closing_pattern.is_play_close_end_sound = true;
727 this.closing_pattern.se_volume = 0.1f;
728 }
729 }
730 break;
731
732 case CLOSING_PATTERN_TYPE.FLIP: {
733 rate = Mathf.Clamp01(this.step_timer / this.closing_pattern.total_time);
734 rate = Mathf.Sin(Mathf.Lerp(0.0f,Mathf.PI / 2.0f,rate));
735
736 const float time0 = 0.3f;
737 const float time1 = 0.7f;
738
739 if(rate < time0) {
740
741 // さっとしまる(両方ともふすま).
742
743 rate = Mathf.InverseLerp(0.0f,time0,rate);
744
745 this.closing_pattern.fusuma_x[0] = Mathf.Lerp(-SHUTTER_POSITION_OPEN_X,-SHUTTER_POSITION_CLOSE_X,rate);
746 this.closing_pattern.fusuma_x[1] = Mathf.Lerp(SHUTTER_POSITION_OPEN_X,SHUTTER_POSITION_CLOSE_X,rate);
747 this.closing_pattern.shoji_x = SHUTTER_POSITION_OPEN_X;
748
749 } else if(rate < time1) {
750
751 // しばらくためる.
752
753 this.closing_pattern.fusuma_x[0] = -SHUTTER_POSITION_CLOSE_X;
754 this.closing_pattern.fusuma_x[1] = SHUTTER_POSITION_CLOSE_X;
755 this.closing_pattern.shoji_x = SHUTTER_POSITION_OPEN_X;
756
757 } else {
758
759 // 右側がくるんとまわって障子になる.
760
761 this.closing_pattern.fusuma_x[0] = -SHUTTER_POSITION_CLOSE_X;
762 this.closing_pattern.fusuma_x[1] = SHUTTER_POSITION_CLOSE_X;
763 this.closing_pattern.shoji_x = SHUTTER_POSITION_OPEN_X;
764
765 //
766
767 rate = Mathf.InverseLerp(time1,1.0f,rate);
768
769 if(rate < 0.5f) {
770
771 // 0~90度 ふすまを表示.
772
773 rate = Mathf.InverseLerp(0.0f,0.5f,rate);
774
775 this.closing_pattern.fusuma_x[1] = SHUTTER_POSITION_CLOSE_X;
776 this.closing_pattern.shoji_x = SHUTTER_POSITION_OPEN_X;
777
778 //
779
780 this.closing_pattern.fusuma_rot_x[1] = Mathf.Lerp(0.0f,90.0f,rate);
781 this.closing_pattern.shoji_rot_x = 0.0f;
782
783
784 } else {
785
786 // 90~180度 障子を表示.
787
788 rate = Mathf.InverseLerp(0.5f,1.0f,rate);
789
790 this.closing_pattern.fusuma_x[1] = SHUTTER_POSITION_OPEN_X;
791 this.closing_pattern.shoji_x = SHUTTER_POSITION_CLOSE_X;
792
793 //
794
795 this.closing_pattern.fusuma_rot_x[1] = 0.0f;
796 this.closing_pattern.shoji_rot_x = Mathf.Lerp(-90.0f,0.0f,rate);
797
798 }
799 }
800
801 if(this.is_step_timer_reach(0.0f)) {
802
803 this.closing_pattern.is_play_close_sound = true;
804 this.closing_pattern.se_pitch = 2.0f;
805 }
806 if(this.is_step_timer_reach(this.closing_pattern.total_time * time0)) {
807
808 this.closing_pattern.is_play_close_end_sound = true;
809 this.closing_pattern.se_pitch = 1.5f;
810 }
811 if(this.is_step_timer_reach(this.closing_pattern.total_time)) {
812
813 this.closing_pattern.is_play_close_end_sound = true;
814 this.closing_pattern.se_pitch = 1.5f;
815 }
816 }
817 break;
818
819 case CLOSING_PATTERN_TYPE.SLOW: {
820 rate = Mathf.Clamp01(this.step_timer / this.closing_pattern.total_time);
821 rate = Mathf.Sin(Mathf.Lerp(0.0f,Mathf.PI / 2.0f,rate));
822
823 this.closing_pattern.shoji_x = Mathf.Lerp(SHUTTER_POSITION_OPEN_X,SHUTTER_POSITION_CLOSE_X,rate);
824
825 this.closing_pattern.fusuma_x[0] = Mathf.Lerp(-SHUTTER_POSITION_OPEN_X,-SHUTTER_POSITION_CLOSE_X,rate);
826
827 if(this.is_step_timer_reach(0.0f)) {
828
829 this.closing_pattern.is_play_close_sound = true;
830 this.closing_pattern.se_pitch = 0.5f;
831 }
832 if(this.is_step_timer_reach(this.closing_pattern.total_time)) {
833
834 this.closing_pattern.is_play_close_end_sound = true;
835 this.closing_pattern.se_pitch = 0.5f;
836 this.closing_pattern.se_volume = 0.5f;
837 }
838 }
839 break;
840
841 case CLOSING_PATTERN_TYPE.SUPER_DELAY: {
842 rate = Mathf.Clamp01(this.step_timer / this.closing_pattern.total_time);
843
844 const float time0 = 0.1f;
845 float time1 = this.closing_pattern.param.as_float;
846 float time2 = time1 + 0.1f;
847
848 if(rate < time0) {
849
850 // ふすまがさっとしまる.
851
852 rate = Mathf.InverseLerp(0.0f,time0,rate);
853 rate = Mathf.Sin(Mathf.Lerp(0.0f,Mathf.PI / 2.0f,rate));
854
855 this.closing_pattern.fusuma_x[0] = Mathf.Lerp(-SHUTTER_POSITION_OPEN_X,-SHUTTER_POSITION_CLOSE_X,rate);
856 this.closing_pattern.shoji_x = SHUTTER_POSITION_OPEN_X;
857
858 } else if(rate < time1) {
859
860 // しばらくためる.
861
862 this.closing_pattern.fusuma_x[0] = -SHUTTER_POSITION_CLOSE_X;
863 this.closing_pattern.shoji_x = SHUTTER_POSITION_OPEN_X;
864
865 } else if(rate < time2) {
866
867 // 左側に障子がさっとしまる.
868
869 rate = Mathf.InverseLerp(time1,time2,rate);
870 rate = Mathf.Sin(Mathf.Lerp(0.0f,Mathf.PI / 2.0f,rate));
871
872 this.closing_pattern.fusuma_x[0] = -SHUTTER_POSITION_CLOSE_X;
873 this.closing_pattern.shoji_x = Mathf.Lerp(SHUTTER_POSITION_OPEN_X,SHUTTER_POSITION_CLOSE_X,rate);
874
875 } else {
876
877 this.closing_pattern.fusuma_x[0] = -SHUTTER_POSITION_CLOSE_X;
878 this.closing_pattern.shoji_x = SHUTTER_POSITION_CLOSE_X;
879 }
880 //
881
882 if(this.is_step_timer_reach(0.0f)) {
883
884 this.closing_pattern.is_play_close_sound = true;
885 this.closing_pattern.se_pitch = 2.0f;
886 }
887 if(this.is_step_timer_reach(this.closing_pattern.total_time * time1)) {
888
889 this.closing_pattern.is_play_close_sound = true;
890 this.closing_pattern.se_pitch = 2.0f;
891 }
892 if(this.is_step_timer_reach(this.closing_pattern.total_time * time2)) {
893
894 this.closing_pattern.is_play_close_end_sound = true;
895 this.closing_pattern.se_pitch = 1.5f;
896 }
897 }
898 break;
899 }
900
901 // 位置、回転等を GameObject に反映させる.
902
903 for(int i = 0;i < this.closing_pattern.fusuma_num;i++) {
904
905 if(!this.is_flip_closing) {
906
907 this.fusuma_objects[i].GetComponent<ShutterControl>().setX(this.closing_pattern.fusuma_x[i]);
908 this.fusuma_objects[i].transform.rotation = Quaternion.AngleAxis(this.closing_pattern.fusuma_rot_x[i],Vector3.up);
909
910 } else {
911
912 this.fusuma_objects[i].GetComponent<ShutterControl>().setX(-this.closing_pattern.fusuma_x[i]);
913 this.fusuma_objects[i].transform.rotation = Quaternion.AngleAxis(-this.closing_pattern.fusuma_rot_x[i],Vector3.up);
914 }
915 }
916
917 if(this.shoji_object != null) {
918
919 Vector3 position = this.shoji_object.transform.localPosition;
920
921 if(!this.is_flip_closing) {
922
923 position.x = this.closing_pattern.shoji_x;
924 position.y = this.closing_pattern.shoji_y;
925
926 this.shoji_object.transform.rotation = Quaternion.AngleAxis(this.closing_pattern.shoji_rot_x,Vector3.up);
927
928 } else {
929
930 position.x = -this.closing_pattern.shoji_x;
931 position.y = this.closing_pattern.shoji_y;
932
933 this.shoji_object.transform.rotation = Quaternion.AngleAxis(-this.closing_pattern.shoji_rot_x,Vector3.up);
934 }
935
936 position.z = SHUTTER_POSITION_Z + this.closing_pattern.shoji_z_offset;
937
938 this.shoji_object.transform.localPosition = position;
939 }
940
941 // サウンド.
942
943 if(this.closing_pattern.is_play_close_sound) {
944
945 this.GetComponent<AudioSource>().PlayOneShot(this.CLOSE_SOUND,this.closing_pattern.se_volume);
946 this.GetComponent<AudioSource>().pitch = this.closing_pattern.se_pitch;
947 }
948 if(this.closing_pattern.is_play_close_end_sound) {
949
950 this.GetComponent<AudioSource>().PlayOneShot(this.CLOSE_END_SOUND,this.closing_pattern.se_volume);
951 this.GetComponent<AudioSource>().pitch = this.closing_pattern.se_pitch;
952 }
953 }
954
955 /// <summary>
956 /// 添加窗户控制器
957 /// </summary>
958 public void attachShouji(ShojiControl shoji) {
959 this.shoji_object = shoji;
960 if(this.shoji_object != null) {
961 this.shoji_object.transform.parent = this.gameObject.transform;
962 this.shoji_object.transform.localPosition = new Vector3(SHUTTER_POSITION_OPEN_X,0.0f,SHUTTER_POSITION_Z);
963 }
964 }
965
966 // 障子の登場パターンをセットする.
967 public void setClosingPatternType(CLOSING_PATTERN_TYPE type,bool is_flip) {
968 ClosingPatternParam param;
969
970 param.as_float = 0.0f;
971 param.as_bool = true;
972
973 this.setClosingPatternType(type,is_flip,param);
974 }
975 // 障子の登場パターンをセットする.
976 public void setClosingPatternType(CLOSING_PATTERN_TYPE type,bool is_flip,ClosingPatternParam param) {
977 this.closing_pattern_type = type;
978
979 this.is_flip_closing = is_flip;
980
981 this.closing_pattern.param = param;
982 }
983
984 public void setClose() {
985 this.next_step = STEP.CLOSE;
986 }
987 public void setOpen() {
988 this.next_step = STEP.OPEN;
989 }
990
991 public void beginOpen() {
992 this.next_step = STEP.TO_OPEN;
993 }
994 public void beginCloseShoji() {
995 this.next_step = STEP.TO_CLOSE_SHOJI;
996 }
997 }

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 管理场景中使用的共通参数
6 /// </summary>
7 public class GlobalParam:MonoBehaviour {
8
9 /// <summary>
10 /// 难度
11 /// </summary>
12 private int m_difficultyMode = 0;
13
14 /// <summary>
15 /// 单例
16 /// </summary>
17 private static GlobalParam m_instance = null;
18
19 /// <summary>
20 /// 获取单例
21 /// </summary>
22 public static GlobalParam GetInstance() {
23 if(m_instance == null) {
24 GameObject g = new GameObject("GlobalParam");
25 m_instance = g.AddComponent<GlobalParam>();
26 DontDestroyOnLoad(g);
27 }
28 return m_instance;
29 }
30
31 /// <summary>
32 /// 获取难度
33 /// </summary>
34 public int difficulty() {
35 return m_difficultyMode;
36 }
37
38 /// <summary>
39 /// 设置难度
40 /// </summary>
41 public void SetMode(int difficulty) {
42 m_difficultyMode = difficulty;
43 }
44 }

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 根据难易程度来改变窗户的关闭方式等
6 /// </summary>
7 public class LevelControl : MonoBehaviour {
8
9 public enum LEVEL {
10
11 NONE = -1,
12
13 EASY = 0,
14 NORMAL = 1,
15 HARD = 2,
16
17 NUM,
18 };
19
20 public LEVEL level = LEVEL.EASY;
21
22 public SceneControl scene_control = null;
23
24 private bool random_bool_prev;
25
26 // ---------------------------------------------------------------- //
27
28 // Use this for initialization
29 void Start () {
30
31 switch(GlobalParam.GetInstance().difficulty()) {
32
33 case 0:
34 {
35 this.level = LEVEL.EASY;
36 }
37 break;
38
39 case 1:
40 {
41 this.level = LEVEL.NORMAL;
42 }
43 break;
44
45 case 2:
46 {
47 this.level = LEVEL.HARD;
48 }
49 break;
50
51 default:
52 {
53 this.level = LEVEL.EASY;
54 }
55 break;
56 }
57
58 this.scene_control = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<SceneControl>();
59
60 this.random_bool_prev = Random.Range(0, 2) == 0 ? true : false;
61 }
62
63 // Update is called once per frame
64 void Update () {
65
66 }
67
68 // 障子が閉まり始める距離.
69 public float getCloseDistance()
70 {
71 // ちいさな値にすると障子が閉まり始めるタイミングが遅くなって、難しくなります.
72
73 float close_distance = 14.0f;
74
75 int paper_num = this.scene_control.getPaperNum();
76
77 switch(this.level) {
78
79 case LEVEL.EASY:
80 {
81 close_distance = 14.0f;
82 }
83 break;
84
85 case LEVEL.NORMAL:
86 {
87 close_distance = 14.0f;
88 }
89 break;
90
91 case LEVEL.HARD:
92 {
93 if(paper_num >= 8) {
94
95 close_distance = 12.0f;
96
97 } else if(paper_num >= 5) {
98
99 close_distance = 12.0f;
100
101 } else {
102
103 close_distance = FloorControl.SHUTTER_POSITION_Z;
104 }
105 }
106 break;
107
108 default:
109 {
110 close_distance = 14.0f;
111 }
112 break;
113 }
114
115
116 return(close_distance);
117 }
118
119 // 障子の閉まり方パターンを取得する.
120 public void getClosingPattern(out FloorControl.CLOSING_PATTERN_TYPE out_type, out bool out_is_flip, out FloorControl.ClosingPatternParam out_param)
121 {
122 int paper_num = this.scene_control.getPaperNum();
123 bool random_bool = Random.Range(0, 2) == 0 ? true : false;
124
125 out_param.as_float = 0.0f;
126 out_param.as_bool = false;
127
128 switch(this.level) {
129
130 case LEVEL.EASY:
131 {
132 // easy は normal のみ.
133
134 out_type = FloorControl.CLOSING_PATTERN_TYPE.NORMAL;
135
136 out_is_flip = false;
137 }
138 break;
139
140 case LEVEL.NORMAL:
141 {
142 StaticArray<FloorControl.CLOSING_PATTERN_TYPE> out_type_cadidates = new StaticArray<FloorControl.CLOSING_PATTERN_TYPE>((int)FloorControl.CLOSING_PATTERN_TYPE.NUM);
143
144 if(9 >= paper_num && paper_num >= 8) {
145
146 // 1、2枚目は NORMAL.
147
148 out_type_cadidates.push_back(FloorControl.CLOSING_PATTERN_TYPE.NORMAL);
149
150 out_is_flip = false;
151
152 } else if(paper_num == 7) {
153
154 // 残り7枚のときは OVERSHOOT.
155
156 out_type_cadidates.push_back(FloorControl.CLOSING_PATTERN_TYPE.OVERSHOOT);
157
158 out_is_flip = false;
159
160 } else if(paper_num == 6) {
161
162 // 残り6枚のときは SECONDTIME.
163
164 out_type_cadidates.push_back(FloorControl.CLOSING_PATTERN_TYPE.SECONDTIME);
165
166 out_is_flip = false;
167
168 } else if(paper_num == 5) {
169
170 // 残り5枚のときは ARCODION.
171
172 out_type_cadidates.push_back(FloorControl.CLOSING_PATTERN_TYPE.ARCODION);
173
174 out_is_flip = false;
175
176 } else if(4 >= paper_num && paper_num >= 3) {
177
178 // 残り4~3枚のときは DELAY(is_flip はランダム).
179
180 out_type_cadidates.push_back(FloorControl.CLOSING_PATTERN_TYPE.DELAY);
181
182 out_is_flip = random_bool;
183
184 if(paper_num == 4) {
185
186 // 残り4枚のときは右から.
187
188 out_param.as_bool = false;
189
190 } else {
191
192 // 残り3枚のときは右から(ふすまの裏から).
193 out_param.as_bool = true;
194 }
195
196 } else if(paper_num == 2) {
197
198 // 残り2枚の時は必ず FALLDOWN.
199
200 out_type_cadidates.push_back(FloorControl.CLOSING_PATTERN_TYPE.FALLDOWN);
201
202 out_is_flip = false;
203
204 } else {
205
206 // 残り1枚の時は必ず FLIP(is_flip はランダム).
207
208 out_type_cadidates.push_back(FloorControl.CLOSING_PATTERN_TYPE.FLIP);
209
210 out_is_flip = random_bool;
211 }
212
213 out_type = out_type_cadidates[Random.Range(0, out_type_cadidates.size())];
214 }
215 break;
216
217 case LEVEL.HARD:
218 {
219 if(paper_num >= 8) {
220
221 // 残り9~8枚のときは NORMAL.
222
223 out_type = FloorControl.CLOSING_PATTERN_TYPE.NORMAL;
224
225 if(paper_num == 9) {
226
227 out_is_flip = random_bool;
228
229 } else {
230
231 out_is_flip = !this.random_bool_prev;
232 }
233
234 } else if(paper_num >= 5) {
235
236 // 残り7~5枚のときは SLOW.
237 // 閉まり終わるのがだんだん遅くなる.
238
239 out_type = FloorControl.CLOSING_PATTERN_TYPE.SLOW;
240
241 if(paper_num == 7) {
242
243 out_is_flip = random_bool;
244 out_param.as_float = 1.5f;
245
246 } else if(paper_num == 6) {
247
248 out_is_flip = !this.random_bool_prev;
249 out_param.as_float = 1.7f;
250
251 // 次回のために上書きしておく.
252 // (7, 6, 5 で必ず交互になるように).
253 random_bool = !this.random_bool_prev;
254
255 } else {
256
257 out_is_flip = !this.random_bool_prev;
258 out_param.as_float = 2.0f;
259 }
260
261 } else {
262
263 // 残り4~1枚のときは SUPER_DELAY.
264
265 out_type = FloorControl.CLOSING_PATTERN_TYPE.SUPER_DELAY;
266
267 out_is_flip = random_bool;
268
269 if(paper_num >= 4) {
270
271 out_param.as_float = 0.6f;
272
273 } else if(paper_num >= 3) {
274
275 out_param.as_float = 0.7f;
276
277 } else {
278
279 out_param.as_float = 0.9f;
280 }
281 }
282 }
283 break;
284
285 default:
286 {
287 out_type = FloorControl.CLOSING_PATTERN_TYPE.NORMAL;
288
289 out_is_flip = false;
290 }
291 break;
292 }
293
294 this.random_bool_prev = random_bool;
295 }
296
297 // 『何回空振り(やぶった後の穴を通過)したら鉄板になるか』を取得する.
298 public int getChangeSteelCount()
299 {
300 // -1 のときは鉄板にならない.
301 int count = -1;
302
303 int paper_num = this.scene_control.getPaperNum();
304
305 switch(this.level) {
306
307 case LEVEL.EASY:
308 {
309 // easy は鉄板化なし.
310 count = -1;
311 }
312 break;
313
314 case LEVEL.NORMAL:
315 {
316 // hardは鉄板化なし.
317 count = -1;
318 }
319 break;
320
321 case LEVEL.HARD:
322 {
323 // (仮)です.
324 // のこり枚数が少なくなるほど鉄板化しやすくなるようにしてください.
325
326 if(paper_num >= 8) {
327
328 count = -1;
329
330 } else if(paper_num >= 6) {
331
332 count = 5;
333
334 } else if(paper_num >= 3) {
335
336 count = 2;
337
338 } else {
339
340 count = 1;
341 }
342
343 }
344 break;
345
346 default:
347 {
348 count = -1;
349 }
350 break;
351 }
352
353 return(count);
354 }
355 }

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 猫的碰撞结果
6 /// </summary>
7 public class NekoColiResult {
8
9 public NekoControl neko = null;
10
11 public static float THROUGH_GAP_LIMIT = 0.4f; //!< 格子の中心からこれ以上ずれていたら、組み木に当たる.
12 public static float UNLOCK_DISTANCE = 3.0f; //!< 誘導を解除する距離.
13
14 // ---------------------------------------------------------------- //
15
16 // 障子の組み木に当たったときの情報いろいろ.
17 //
18 public struct ShojiHitInfo {
19
20 public bool is_enable;
21
22 public ShojiControl shoji_control;
23
24 public ShojiControl.HoleIndex hole_index;
25 };
26
27 public ShojiHitInfo shoji_hit_info;
28 public ShojiHitInfo shoji_hit_info_first;
29
30 // 障子の穴に当たったときの情報いろいろ.
31 //
32 public struct HoleHitInfo {
33
34 public SyoujiPaperControl paper_control;
35 };
36
37 public StaticArray<HoleHitInfo> hole_hit_infos;
38
39 // ふすま、障子の組み木にあたったときの情報いろいろ.
40 //
41 public struct ObstacleHitInfo {
42
43 public bool is_enable;
44
45 public GameObject go;
46 public bool is_steel;
47 };
48
49 public ObstacleHitInfo obstacle_hit_info;
50
51 // 誘導をかける、障子の格子
52 //
53 public struct LockTarget {
54
55 public bool enable;
56
57 public ShojiControl.HoleIndex hole_index;
58
59 public Vector3 position;
60 };
61
62 public LockTarget lock_target;
63
64 public bool is_steel = false;
65
66 // ---------------------------------------------------------------- //
67
68 public void create()
69 {
70 this.hole_hit_infos = new StaticArray<HoleHitInfo>(4);
71
72 this.shoji_hit_info.is_enable = false;
73 this.shoji_hit_info_first.is_enable = false;
74
75 this.obstacle_hit_info.is_enable = false;
76
77 this.lock_target.enable = false;
78 }
79
80 // 前のフレームのコリジョン結果をチェックする.
81
82 public void resolveCollision()
83 {
84 // 「格子の穴」をすり抜けて一定距離進んだら、誘導を解除する.
85 if(this.lock_target.enable) {
86
87 if(this.neko.transform.position.z > this.lock_target.position.z + UNLOCK_DISTANCE) {
88
89 this.lock_target.enable = false;
90 }
91 }
92
93 if(!this.lock_target.enable) {
94
95 this.resolve_collision_sub();
96 }
97 }
98
99 private void resolve_collision_sub()
100 {
101 bool is_collied_obstacle = false;
102
103 this.is_steel = false;
104
105 // ふすま/鉄板に当たったかを最初に調べる.
106 //
107 // ふすま/鉄板に当たった場合でも穴を通過したときは、ミスにしたくないので.
108
109 if(this.obstacle_hit_info.is_enable) {
110
111 is_collied_obstacle = true;
112
113 this.is_steel = this.obstacle_hit_info.is_steel;
114 }
115
116 //
117
118 if(this.shoji_hit_info.is_enable) {
119
120 // 組み木と当たった?.
121
122 ShojiControl shoji_control = this.shoji_hit_info.shoji_control;
123 ShojiControl.HoleIndex hole_index = this.shoji_hit_info.hole_index;
124
125 if(shoji_control.isValidHoleIndex(hole_index)) {
126
127 SyoujiPaperControl paper_control = shoji_control.papers[hole_index.x, hole_index.y];
128
129 if(paper_control.isSteel()) {
130
131 // 格子の穴が、鉄板だったとき.
132
133 is_collied_obstacle = true;
134
135 this.is_steel = true;
136
137 } else {
138
139 // 格子の穴が、「紙」「やぶれ紙」だったとき.
140
141 // 「格子の穴」にホーミングするときの、目標位置.
142 Vector3 position = NekoColiResult.get_hole_homing_position(shoji_control, hole_index);
143
144 //
145
146 Vector3 diff = this.neko.transform.position - position;
147
148 //Debug.Log(diff.x.ToString() + " " + diff.y);
149
150 if(Mathf.Abs(diff.x) < THROUGH_GAP_LIMIT && Mathf.Abs(diff.y) < THROUGH_GAP_LIMIT) {
151
152 // 穴の中心からある程度近い位置を通過したら、格子の穴を通りぬける.
153 // (ホーミング).
154
155 is_collied_obstacle = false;
156
157 this.lock_target.enable = true;
158 this.lock_target.hole_index = hole_index;
159 this.lock_target.position = position;
160
161
162 // 「格子の穴」モデルに、プレイヤーがヒットしたことを通知する.
163 paper_control.onPlayerCollided();
164
165 } else {
166
167 // 穴の中心から大きくずれていた場合は、格子にぶつかったことにする.
168
169 is_collied_obstacle = true;
170 }
171 }
172
173 } else {
174
175 // 障子の、格子の穴以外の場所にぶつかったとき.
176
177 is_collied_obstacle = true;
178 }
179
180 } else {
181
182 // 組み木と当たらなかったときは、二つ以上の「格子の穴」とヒットすることはないはず.
183 // (二つの「格子の穴」とヒットするときは、その間の組み木にもヒットするから)
184 // なので、組み木と当たらなかったときは this.hole_hit_infos[0] だけ調べれば十分.
185 if(this.hole_hit_infos.size() > 0) {
186
187 // 「格子の穴」のみにヒットした.
188
189 HoleHitInfo hole_hit_info = this.hole_hit_infos[0];
190 SyoujiPaperControl paper_control = hole_hit_info.paper_control;
191 ShojiControl shoji_control = paper_control.shoji_control;
192
193 paper_control.onPlayerCollided();
194
195 // 「格子の穴」を通りぬける.
196 // (ホーミング).
197
198 // ロックする(誘導の目標位置にする).
199
200 // 「格子の穴」の中心を求める.
201
202 ShojiControl.HoleIndex hole_index = paper_control.hole_index;
203
204 Vector3 position = NekoColiResult.get_hole_homing_position(shoji_control, hole_index);
205
206 this.lock_target.enable = true;
207 this.lock_target.hole_index = hole_index;
208 this.lock_target.position = position;
209 }
210 }
211
212
213 if(is_collied_obstacle) {
214
215 // 障害物(障子の組み木、ふすま)に当たった.
216
217 if(this.neko.step != NekoControl.STEP.MISS) {
218
219 this.neko.beginMissAction(this.is_steel);
220 }
221 }
222
223 }
224
225
226 // 「格子の穴」にホーミングするときの、目標位置.
227 private static Vector3 get_hole_homing_position(ShojiControl shoji_control, ShojiControl.HoleIndex hole_index)
228 {
229 Vector3 position;
230
231 position = shoji_control.getHoleWorldPosition(hole_index.x, hole_index.y);
232
233 // コリジョンの中心からオブジェクトの原点へのオフセット.
234 // コリジョンの中心が、「格子の穴」の中心を通るようにする.
235 position += -NekoControl.COLLISION_OFFSET;
236
237 return(position);
238 }
239
240 }

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 控制猫
6 /// </summary>
7 public class NekoControl : MonoBehaviour {
8
9 private RoomControl room_control = null;
10 private SceneControl scene_control = null;
11 public EffectControl effect_control = null;
12
13 // ---------------------------------------------------------------- //
14
15 public enum STEP {
16
17 NONE = -1,
18
19 STAND = 0, // たち.
20 RUN, // 走り.
21 JUMP, // ジャンプ.
22 MISS, // ミス.
23 GAMEOVER, // ゲームオーバー.
24
25 FREE_MOVE, // 自由移動(デバッグ用).
26
27 NUM,
28 };
29
30 public STEP step = STEP.NONE;
31 public STEP next_step = STEP.NONE;
32 public float step_timer = 0.0f;
33 public bool is_grounded; // 着地してる?.
34
35 // ---------------------------------------------------------------- //
36
37 // ジャンプ中のいろいろ.
38 public struct ActionStand {
39
40 public bool is_fade_anim; // アニメーションをフェードする?(毎フレーム true に戻る).
41 };
42
43 // ジャンプ中のいろいろ.
44 public struct ActionJump {
45
46 public STEP prevoius_step; // ジャンプする前のステップ(立ちジャンプ or 走りながらジャンプ).
47
48 public bool is_key_released; // ジャンプ後、スペースキーを離した?.
49
50 public Vector3 launch_velocity_xz;
51 };
52
53 // ミスしたときのいろいろ.
54 public struct ActionMiss {
55
56 public bool is_steel; // 鉄板に当たった?.
57 };
58
59 public ActionJump action_jump;
60 public ActionMiss action_miss;
61 public ActionStand action_stand;
62
63 public Vector3 previous_velocity;
64
65 private bool is_fallover = true;
66
67 private bool is_auto_drive = false; // 自動運転(クリアーした後).
68
69 // ---------------------------------------------------------------- //
70
71 public static float JUMP_HEIGHT_MAX = 5.0f; // ジャンプの高さ.
72 public static float JUMP_KEY_RELEASE_REDUCE = 0.5f; // ジャンプ中にキーを離したときの、上昇速度のスケール.
73
74 public static float RUN_SPEED_MAX = 5.0f; // 走りのスピードの最大値.
75 public static float RUN_ACCELE = RUN_SPEED_MAX/2.0f; // 走りのスピードの加速.
76
77 public static float SLIDE_SPEED_MAX = 2.0f; // 左右移動のスピード.
78 public static float SLIDE_ACCEL = SLIDE_SPEED_MAX/0.1f; // 左右移動の加速度.
79
80 public static float SLIDE_ACCEL_SCALE_JUMP = 0.1f; // 左右移動の加速度のスケール(ジャンプ中).
81
82 public static float RUN_SPEED_DECELE_MISS = RUN_SPEED_MAX/2.0f; // ミスした時の減速度.
83 public static float RUN_SPEED_DECELE_MISS_JUMP = RUN_SPEED_MAX/5.0f; // ミスした時の減速度(ジャンプ中).
84
85 public static Vector3 COLLISION_OFFSET = Vector3.up*0.2f;
86
87 // ---------------------------------------------------------------- //
88
89 public static float SLIDE_ROTATION_MAX = 0.2f; // 左右移動のローテーションスピード.
90 public static float SLIDE_ROTATION_SPEED = SLIDE_ROTATION_MAX/0.1f; // 左右移動のローテーション加速度.
91 public static float SLIDE_ROTATION_COEFFICIENT = 2.0f; // 左右移動のローテーション加速度の係数.
92
93 public static float JUMP_ROTATION_MAX = 0.25f; // 上下のローテーションスピード(ジャンプ中).
94 public static float JUMP_ROTATION_SPEED = JUMP_ROTATION_MAX/0.1f; // 上下のローテーション加速度(ジャンプ中).
95 public static float JUMP_ROTATION_COEFFICIENT = 0.25f; // 上下のローテーション加速度の係数(ジャンプ中).
96
97 public static float SLIDE_VELOCITY = 1.0f; // 左右移動のローテーション速度.
98 public static float JUMP_VELOCITY = 4.0f; // 上下のローテーション速度(ジャンプ中).
99
100 // ---------------------------------------------------------------- //
101
102 public AudioClip START_SOUND = null;
103 public AudioClip FAILED_STEEL_SOUND = null;
104 public AudioClip FAILED_FUSUMA_SOUND = null;
105 public AudioClip FAILED_NEKO_SOUND = null;
106 public AudioClip JUMP_SOUND = null;
107 public AudioClip LANDING_SOUND = null;
108 public AudioClip FALL_OVER_SOUND = null;
109
110 // ---------------------------------------------------------------- //
111
112 NekoColiResult coli_result;
113
114 // ---------------------------------------------------------------- //
115
116 public void onRoomProceed()
117 {
118 this.coli_result.shoji_hit_info_first.is_enable = false;
119 }
120
121
122 void Start ()
123 {
124 this.room_control = GameObject.FindGameObjectWithTag("RoomControl").GetComponent<RoomControl>();
125 this.scene_control = GameObject.FindWithTag("MainCamera").GetComponent<SceneControl>();
126 this.effect_control = GameObject.FindGameObjectWithTag("EffectControl").GetComponent<EffectControl>();
127
128
129 //
130
131 this.is_grounded = false;
132
133 GetComponent<AudioSource>().clip = START_SOUND;
134 GetComponent<AudioSource>().Play();
135
136 this.previous_velocity = Vector3.zero;
137
138 this.next_step = STEP.STAND;
139
140 this.coli_result = new NekoColiResult();
141 this.coli_result.neko = this;
142 this.coli_result.create();
143
144 this.action_stand.is_fade_anim = true;
145
146 }
147
148 // Update is called once per frame
149 void Update ()
150 {
151
152 Animation animation = this.GetComponentInChildren<Animation>();
153
154 // ---------------------------------------------------------------- //
155
156 // 着地するときに地面にめり込んでしまうので.
157 // (かっこ悪いけど).
158
159 if(this.transform.position.y < 0.0f) {
160
161 this.is_grounded = true;
162
163 Vector3 pos = this.transform.position;
164
165 pos.y = 0.0f;
166
167 this.transform.position = pos;
168 }
169
170 // ---------------------------------------------------------------- //
171 // ステップ内の経過時間を進める.
172
173 this.step_timer += Time.deltaTime;
174
175 // ---------------------------------------------------------------- //
176 // 次の状態に移るかどうかを、チェックする.
177
178 // 前のフレームのコリジョン結果を調べる.
179
180 if(this.step != STEP.MISS) {
181
182 this.coli_result.resolveCollision();
183 }
184
185 //
186
187 if(this.next_step == STEP.NONE) {
188
189 switch(this.step) {
190
191 case STEP.NONE:
192 {
193 this.next_step = STEP.STAND;
194 }
195 break;
196
197 case STEP.STAND:
198 {
199 // シフトキーで走り始める.
200 if(Input.GetKeyDown(KeyCode.LeftShift)) {
201
202 this.next_step = STEP.RUN;
203 }
204 // スペースキーでジャンプ.
205 if(Input.GetKeyDown(KeyCode.Space)) {
206
207 this.next_step = STEP.JUMP;
208 }
209 }
210 break;
211
212 case STEP.RUN:
213 {
214 if(!this.is_auto_drive) {
215
216 if(Input.GetKeyDown(KeyCode.Space)) {
217
218 this.next_step = STEP.JUMP;
219 }
220 }
221 }
222 break;
223
224 case STEP.JUMP:
225 {
226 // 着地したら立ち、または走りへ.
227 if(this.is_grounded) {
228
229 GetComponent<AudioSource>().clip = LANDING_SOUND;
230 GetComponent<AudioSource>().Play();
231 this.next_step = this.action_jump.prevoius_step;
232 }
233 }
234 break;
235
236 case STEP.MISS:
237 {
238 if(this.step_timer > 3.0f) {
239
240 GameObject.FindWithTag("MainCamera").transform.SendMessage("applyDamage", 1);
241
242 if(this.scene_control.getLifeCount() > 0) {
243
244 this.transform.position = this.room_control.getRestartPosition();
245
246 this.room_control.onRestart();
247
248 // アニメーションは補間しない.
249 this.action_stand.is_fade_anim = false;
250
251 this.next_step = STEP.STAND;
252
253 } else {
254
255 this.next_step = STEP.GAMEOVER;
256 }
257 }
258 }
259 break;
260 }
261 }
262
263 // ---------------------------------------------------------------- //
264 // 状態が遷移したときの初期化.
265
266 if(this.next_step != STEP.NONE) {
267
268 switch(this.next_step) {
269
270 case STEP.STAND:
271 {
272 Vector3 v = this.GetComponent<Rigidbody>().velocity;
273
274 v.x = 0.0f;
275 v.z = 0.0f;
276
277 this.GetComponent<Rigidbody>().velocity = v;
278
279 // 立ちアニメーションの再生.
280
281 if(this.action_stand.is_fade_anim) {
282
283 animation.CrossFade("M01_nekostanding", 0.2f);
284
285 } else {
286
287 animation.CrossFade("M01_nekostanding", 0.0f);
288 }
289
290 this.action_stand.is_fade_anim = true;
291 }
292 break;
293
294 case STEP.RUN:
295 {
296 animation.CrossFade("M02_nekodash", 0.2f);
297 }
298 break;
299
300 case STEP.JUMP:
301 {
302 Vector3 v = this.GetComponent<Rigidbody>().velocity;
303
304 v.y = Mathf.Sqrt(2.0f*9.8f*JUMP_HEIGHT_MAX);
305
306 this.GetComponent<Rigidbody>().velocity = v;
307
308 //
309
310 this.action_jump.is_key_released = false;
311 this.action_jump.prevoius_step = this.step;
312
313 this.action_jump.launch_velocity_xz = this.GetComponent<Rigidbody>().velocity;
314 this.action_jump.launch_velocity_xz.y = 0.0f;
315
316 //
317
318 animation.CrossFade("M03_nekojump", 0.2f);
319 GetComponent<AudioSource>().clip = JUMP_SOUND;
320 GetComponent<AudioSource>().Play();
321 }
322 break;
323
324 case STEP.MISS:
325 {
326 // 後ろに跳ね返る.
327
328 Vector3 v = this.GetComponent<Rigidbody>().velocity;
329
330 v.z *= -0.5f;
331
332 this.GetComponent<Rigidbody>().velocity = v;
333
334 // エフェクト
335 this.effect_control.createMissEffect(this);
336
337 // 鉄板に当たった音 or ふすまに当たった音.
338 //
339 if(this.action_miss.is_steel) {
340
341 GetComponent<AudioSource>().PlayOneShot(FAILED_STEEL_SOUND);
342
343 } else {
344
345 GetComponent<AudioSource>().PlayOneShot(FAILED_FUSUMA_SOUND);
346 }
347
348 // やられ声.
349 //
350 GetComponent<AudioSource>().PlayOneShot(FAILED_NEKO_SOUND);
351
352 animation.CrossFade("M03_nekofailed01", 0.2f);
353
354 this.coli_result.lock_target.enable = false;
355
356 this.is_fallover = false;
357 }
358 break;
359
360 case STEP.FREE_MOVE:
361 {
362 this.GetComponent<Rigidbody>().useGravity = false;
363
364 this.GetComponent<Rigidbody>().velocity = Vector3.zero;
365 }
366 break;
367
368 }
369
370 this.step = this.next_step;
371 this.next_step = STEP.NONE;
372
373 this.step_timer = 0.0f;
374 }
375
376 // ---------------------------------------------------------------- //
377 // 各状態での実行処理.
378
379 // 左右移動、ジャンプによるローテーション.
380 this.rotation_control();
381
382 switch(this.step) {
383
384 case STEP.STAND:
385 {
386 }
387 break;
388
389 case STEP.RUN:
390 {
391 // 前への加速.
392
393 Vector3 v = this.GetComponent<Rigidbody>().velocity;
394
395 v.z += (RUN_ACCELE)*Time.deltaTime;
396
397 v.z = Mathf.Clamp(v.z, 0.0f, RUN_SPEED_MAX);
398
399 // 左右への平行移動.
400
401 if(this.is_auto_drive) {
402
403 v = this.side_move_auto_drive(v, 1.0f);
404
405 } else {
406
407 v = this.side_move(v, 1.0f);
408 }
409
410 //
411
412 this.GetComponent<Rigidbody>().velocity = v;
413 }
414 break;
415
416 case STEP.JUMP:
417 {
418 Vector3 v = this.GetComponent<Rigidbody>().velocity;
419
420 // ジャンプ中にキーを離したら、上昇速度を減らす.
421 // (キーを押す長さでジャンプの高さを制御できるように).
422
423 do {
424
425 if(!Input.GetKeyUp(KeyCode.Space)) {
426
427 break;
428 }
429
430 // 一度離した後はやらない(連打対策).
431 if(this.action_jump.is_key_released) {
432
433 break;
434 }
435
436 // 下降中はやらない.
437 if(this.GetComponent<Rigidbody>().velocity.y <= 0.0f) {
438
439 break;
440 }
441
442 //
443
444 v.y *= JUMP_KEY_RELEASE_REDUCE;
445
446 this.GetComponent<Rigidbody>().velocity = v;
447
448 this.action_jump.is_key_released = true;
449
450 } while(false);
451
452 // 左右への平行移動.
453 // (ジャンプ中も多少は制御できるようにしたい).
454 //
455 if(this.is_auto_drive) {
456
457 this.GetComponent<Rigidbody>().velocity = this.side_move_auto_drive(this.GetComponent<Rigidbody>().velocity, SLIDE_ACCEL_SCALE_JUMP);
458
459 } else {
460
461 this.GetComponent<Rigidbody>().velocity = this.side_move(this.GetComponent<Rigidbody>().velocity, SLIDE_ACCEL_SCALE_JUMP);
462 }
463
464 //
465
466 // 組子に当たったときは、穴の中心の方へ誘導する.
467 if(this.coli_result.shoji_hit_info.is_enable) {
468
469 //
470
471 v = this.GetComponent<Rigidbody>().velocity;
472
473 if(this.coli_result.lock_target.enable) {
474
475 v = this.coli_result.lock_target.position - this.transform.position;
476 }
477
478 v.z = this.action_jump.launch_velocity_xz.z;
479
480 this.GetComponent<Rigidbody>().velocity = v;
481 }
482 }
483 break;
484
485
486 case STEP.MISS:
487 {
488 GameObject.FindWithTag("MainCamera").transform.SendMessage("nekoFailed");
489
490 // 徐々に減速する.
491
492 Vector3 v = this.GetComponent<Rigidbody>().velocity;
493
494 v.y = 0.0f;
495
496 float speed_xz = v.magnitude;
497
498 if(this.is_grounded) {
499
500 speed_xz -= RUN_SPEED_DECELE_MISS*Time.deltaTime;
501
502 } else {
503
504 speed_xz -= RUN_SPEED_DECELE_MISS_JUMP*Time.deltaTime;
505 }
506
507 speed_xz = Mathf.Max(0.0f, speed_xz);
508
509 v.Normalize();
510
511 v *= speed_xz;
512
513 v.y = this.GetComponent<Rigidbody>().velocity.y;
514
515 this.GetComponent<Rigidbody>().velocity = v;
516
517 do {
518
519 if(this.is_fallover) {
520
521 break;
522 }
523
524 if(!this.is_grounded) {
525
526 break;
527 }
528
529 if(animation["M03_nekofailed01"].normalizedTime < 1.0f) {
530
531 break;
532 }
533
534 animation.CrossFade("M03_nekofailed02", 0.2f);
535 GetComponent<AudioSource>().clip = FALL_OVER_SOUND;
536 GetComponent<AudioSource>().Play();
537
538 this.is_fallover = true;
539
540 } while(false);
541 }
542 break;
543
544 case STEP.FREE_MOVE:
545 {
546 float speed = 400.0f;
547
548 Vector3 v = Vector3.zero;
549
550 if(Input.GetKey(KeyCode.RightArrow)) {
551
552 v.x = +speed*Time.deltaTime;
553 }
554 if(Input.GetKey(KeyCode.LeftArrow)) {
555
556 v.x = -speed*Time.deltaTime;
557 }
558 if(Input.GetKey(KeyCode.UpArrow)) {
559
560 v.y = +speed*Time.deltaTime;
561 }
562 if(Input.GetKey(KeyCode.DownArrow)) {
563
564 v.y = -speed*Time.deltaTime;
565 }
566 if(Input.GetKey(KeyCode.LeftShift)) {
567
568 v.z = +speed*Time.deltaTime;
569 }
570 if(Input.GetKey(KeyCode.RightShift)) {
571
572 v.z = -speed*Time.deltaTime;
573 }
574
575 this.GetComponent<Rigidbody>().velocity = v;
576 }
577 break;
578
579 }
580
581 // ---------------------------------------------------------------- //
582
583 this.is_grounded = false;
584
585 this.coli_result.shoji_hit_info.is_enable = false;
586
587 this.coli_result.hole_hit_infos.clear();
588
589 this.coli_result.obstacle_hit_info.is_enable = false;
590
591 this.previous_velocity = this.GetComponent<Rigidbody>().velocity;
592
593 animation["M02_nekodash"].speed = 4.0f;
594 }
595
596 void OnGUI()
597 {
598 /*if(this.coli_result.lock_target.enable) {
599
600 GUI.Label(new Rect(10, 10, 100, 20), this.coli_result.lock_target.hole_index.x.ToString() + " " + this.coli_result.lock_target.hole_index.y.ToString());
601
602 } else {
603
604 GUI.Label(new Rect(10, 10, 100, 20), "disable");
605 }*/
606 }
607
608 // ---------------------------------------------------------------- //
609 // コリジョン関連.
610
611 void OnCollisionStay(Collision other)
612 {
613 this.on_collision_common(other);
614 }
615 void OnCollisionEnter(Collision other)
616 {
617 this.on_collision_common(other);
618 }
619 private void on_collision_common(Collision other)
620 {
621 // 障子のコリジョンに当たったかを調べる.
622 //
623 do {
624
625 if(other.gameObject.tag != "Syouji") {
626
627 break;
628 }
629
630 ShojiControl shoji_control = other.gameObject.GetComponent<ShojiControl>();
631
632 if(shoji_control == null) {
633
634 break;
635 }
636
637 // 障子のコリジョンにヒットしたことを記録しておく.
638
639
640 Vector3 position = this.transform.TransformPoint(NekoControl.COLLISION_OFFSET);
641
642 ShojiControl.HoleIndex hole_index = shoji_control.getClosetHole(position);
643
644 this.coli_result.shoji_hit_info.is_enable = true;
645 this.coli_result.shoji_hit_info.hole_index = hole_index;
646 this.coli_result.shoji_hit_info.shoji_control = shoji_control;
647
648 } while(false);
649
650 // ふすまにあたった?.
651
652 do {
653
654 if(other.gameObject.tag != "Obstacle") {
655
656 break;
657 }
658
659 this.coli_result.obstacle_hit_info.is_enable = true;
660 this.coli_result.obstacle_hit_info.go = other.gameObject;
661 this.coli_result.obstacle_hit_info.is_steel = false;
662
663 } while(false);
664 }
665
666 void OnTriggerEnter(Collider other)
667 {
668 this.on_trigger_common(other);
669 }
670
671 private void on_trigger_common(Collider other)
672 {
673 // 穴を通過した?.
674
675 do {
676
677 if(other.gameObject.tag != "Hole") {
678
679 break;
680 }
681
682
683 SyoujiPaperControl paper_control = other.GetComponent<SyoujiPaperControl>();
684
685 if(paper_control == null) {
686
687 break;
688 }
689
690 // 格子のトリガーを通過したことを記録しておく.
691
692 if(paper_control.step == SyoujiPaperControl.STEP.STEEL) {
693
694 // 鉄板の場合は、障害物にあたったことにする.
695
696 this.coli_result.obstacle_hit_info.is_enable = true;
697 this.coli_result.obstacle_hit_info.go = other.gameObject;
698 this.coli_result.obstacle_hit_info.is_steel = true;
699
700 } else {
701
702 // 紙だった場合.
703 if(!this.coli_result.hole_hit_infos.full()) {
704
705 NekoColiResult.HoleHitInfo hole_hit_info;
706
707 hole_hit_info.paper_control = paper_control;
708
709 this.coli_result.hole_hit_infos.push_back(hole_hit_info);
710 }
711 }
712
713 } while(false);
714 }
715
716 // ---------------------------------------------------------------- //
717
718 public void beginMissAction(bool is_steel)
719 {
720 this.GetComponent<Rigidbody>().velocity = this.previous_velocity;
721 this.action_miss.is_steel = is_steel;
722
723 this.next_step = STEP.MISS;
724 }
725
726 // ---------------------------------------------------------------- //
727
728 // 左右移動、ジャンプによるローテーション.
729 private void rotation_control()
730 {
731
732 // ---------------------------------------------------------------- //
733 // 上下のローテーション.
734 Quaternion current = this.transform.GetChild(0).transform.localRotation;
735 Quaternion rot = current;
736
737 if(this.transform.position.y > 0.0f || this.step == STEP.JUMP) {
738 // ↑処理の順番の都合上、ジャンプの1フレーム目は y == 0.0f なので、.
739 // step も見てジャンプの1フレーム目もここにくるようにする.
740
741 rot.x = -this.GetComponent<Rigidbody>().velocity.y/20.0f;
742
743 float rot_x_diff = rot.x - current.x;
744 float rot_x_diff_limit = 2.0f;
745
746 rot_x_diff = Mathf.Clamp(rot_x_diff, -rot_x_diff_limit*Time.deltaTime, rot_x_diff_limit*Time.deltaTime);
747
748 rot.x = current.x + rot_x_diff;
749
750 } else {
751
752 rot.x = current.x;
753 rot.x *= 0.9f;
754 }
755
756 if(this.step == STEP.MISS) {
757
758 rot.x = current.x;
759
760 if(this.is_grounded) {
761
762 rot.x *= 0.9f;
763 }
764 }
765
766 // ---------------------------------------------------------------- //
767 // 左右のローテーション.
768
769 rot.y = 0.0f;
770
771 rot.y = this.GetComponent<Rigidbody>().velocity.x/10.0f;
772
773 float rot_y_diff = rot.y - current.y;
774
775 rot_y_diff = Mathf.Clamp(rot_y_diff, -0.015f, 0.015f);
776
777 rot.y = current.y + rot_y_diff;
778
779
780 rot.z = 0.0f;
781
782 // ---------------------------------------------------------------- //
783
784 // 子供(モデル)のみを回転する.
785
786 this.transform.GetChild(0).transform.localRotation = Quaternion.identity;
787 this.transform.GetChild(0).transform.localPosition = Vector3.zero;
788
789 this.transform.GetChild(0).transform.Translate(COLLISION_OFFSET);
790 this.transform.GetChild(0).transform.localRotation *= rot;
791 this.transform.GetChild(0).transform.Translate(-COLLISION_OFFSET);
792 }
793
794 // 左右への平行移動.
795 private Vector3 side_move(Vector3 velocity, float slide_speed_scale)
796 {
797
798 if(Input.GetKey(KeyCode.LeftArrow)) {
799
800 velocity.x -= SLIDE_ACCEL*slide_speed_scale*Time.deltaTime;
801
802 } else if(Input.GetKey(KeyCode.RightArrow)) {
803
804 velocity.x += SLIDE_ACCEL*slide_speed_scale*Time.deltaTime;
805
806 } else {
807
808 // 左右キーがどちらも押されていないときは、速度0に戻る.
809
810 if(velocity.x > 0.0f) {
811
812 velocity.x -= SLIDE_ACCEL*slide_speed_scale*Time.deltaTime;
813
814 velocity.x = Mathf.Max(velocity.x, 0.0f);
815
816 } else {
817
818 velocity.x += SLIDE_ACCEL*slide_speed_scale*Time.deltaTime;
819
820 velocity.x = Mathf.Min(velocity.x, 0.0f);
821 }
822 }
823
824 velocity.x = Mathf.Clamp(velocity.x, -SLIDE_SPEED_MAX, SLIDE_SPEED_MAX);
825
826 return(velocity);
827 }
828
829 // 左右への平行移動(自動運転).
830 private Vector3 side_move_auto_drive(Vector3 velocity, float slide_speed_scale)
831 {
832 const float center_x = 0.0001f;
833
834 if(this.transform.position.x > center_x) {
835
836 velocity.x -= SLIDE_ACCEL*slide_speed_scale*Time.deltaTime;
837
838 } else if(this.transform.position.x < -center_x) {
839
840 velocity.x += SLIDE_ACCEL*slide_speed_scale*Time.deltaTime;
841
842 } else {
843
844 // 左右キーがどちらも押されていないときは、速度0に戻る.
845
846 if(velocity.x > 0.0f) {
847
848 velocity.x -= SLIDE_ACCEL*slide_speed_scale*Time.deltaTime;
849
850 velocity.x = Mathf.Max(velocity.x, 0.0f);
851
852 } else {
853
854 velocity.x += SLIDE_ACCEL*slide_speed_scale*Time.deltaTime;
855
856 velocity.x = Mathf.Min(velocity.x, 0.0f);
857 }
858 }
859
860 // 真中に近づいてきたら、徐々に横移動が少なくなる(直進に近くなる)ように.
861 velocity.x = Mathf.Clamp(velocity.x, -Mathf.Abs(this.transform.position.x), Mathf.Abs(this.transform.position.x));
862
863
864 velocity.x = Mathf.Clamp(velocity.x, -SLIDE_SPEED_MAX, SLIDE_SPEED_MAX);
865
866 return(velocity);
867 }
868
869 // 自動運転開始(クリアー後).
870 public void beginAutoDrive()
871 {
872 this.is_auto_drive = true;
873 }
874
875 }

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 控制所有的房间(房间模型的移动等)
6 /// </summary>
7 public class RoomControl : MonoBehaviour {
8
9 public GameObject roomPrefab = null;
10 public GameObject shojiPrefab = null;
11
12 private FloorControl[] rooms;
13
14 // カメラ.
15 private GameObject main_camera = null;
16
17 public static float MODEL_LENGTH = 15.0f;
18 public static float MODEL_Z_OFFSET = 0.0f;
19
20 public static float RESTART_Z_OFFSET = 5.0f; //リスタート位置のオフセット.
21
22 public static int MODEL_NUM = 3;
23
24 private int start_model_index = 0; // いちばん手前にあるモデルのインデックス.
25
26 private LevelControl level_control;
27 private ShojiControl shoji_control; // 障子(ひとつを使いまわす).
28 private SceneControl scene_control;
29
30 private int room_count = 0; // 進んだ部屋の数.
31 private bool is_closed = false; // 障子が閉まった?(次の部屋へ進むごとにリセット).
32
33 // ---------------------------------------------------------------- //
34
35 // Sound
36 public AudioClip CLOSE_SOUND = null;
37 public AudioClip CLOSE_END_SOUND = null;
38
39 // ---------------------------------------------------------------- //
40
41 // Use this for initialization
42 void Start () {
43
44 this.rooms = new FloorControl[MODEL_NUM];
45
46 for(int i = 0;i < 3;i++) {
47
48 this.rooms[i] = (Instantiate(this.roomPrefab) as GameObject).GetComponent<FloorControl>();
49
50 this.rooms[i].transform.position = new Vector3(0.0f, 0.0f, MODEL_Z_OFFSET + (float)i*MODEL_LENGTH);
51 }
52
53 this.start_model_index = 0;
54
55 this.rooms[(this.start_model_index + 0)%MODEL_NUM].setOpen();
56 this.rooms[(this.start_model_index + 1)%MODEL_NUM].setOpen();
57 this.rooms[(this.start_model_index + 2)%MODEL_NUM].setClose();
58
59 this.shoji_control = (Instantiate(this.shojiPrefab) as GameObject).GetComponent<ShojiControl>();
60
61 this.rooms[(this.start_model_index + 0)%MODEL_NUM].attachShouji(this.shoji_control);
62
63 //
64
65 // カメラのインスタンスを探しておく.
66 this.main_camera = GameObject.FindGameObjectWithTag("MainCamera");
67
68 this.scene_control = this.main_camera.GetComponent<SceneControl>();
69
70 this.level_control = GameObject.FindGameObjectWithTag("GameController").GetComponent<LevelControl>();
71 }
72
73 // Update is called once per frame
74 void Update()
75 {
76 FloorControl room = this.rooms[this.start_model_index];
77
78 // 一番後ろのモデルがカメラの後ろに来たら、奥に移動させる.
79 //
80 if(room.transform.position.z + MODEL_LENGTH < this.main_camera.transform.position.z) {
81
82 // 一番後ろのモデルを奥に移動させる.
83
84 Vector3 new_position = room.transform.position;
85
86 new_position.z += MODEL_LENGTH*MODEL_NUM;
87
88 room.transform.position = new_position;
89
90 //
91
92 this.rooms[(this.start_model_index + 0)%MODEL_NUM].attachShouji(null);
93
94 // 「一番手前にあるモデルのインデックス」を進める.
95 //
96 this.start_model_index = (this.start_model_index + 1)%MODEL_NUM;
97
98
99 // 一番手前の部屋 → 障子をアタッチして、開けた状態にしておく.
100
101 if(this.scene_control.step == SceneControl.STEP.GAME) {
102
103 this.rooms[(this.start_model_index + 0)%MODEL_NUM].attachShouji(this.shoji_control);
104 this.rooms[(this.start_model_index + 0)%MODEL_NUM].setOpen();
105
106 } else {
107
108 this.shoji_control.gameObject.SetActive(false);
109 }
110
111 // 二番目の部屋 → ふすまを開き始める.
112
113 this.rooms[(this.start_model_index + 1)%MODEL_NUM].beginOpen();
114
115 // 三番目番目の部屋 → ふすまが閉めきった状態にする.
116
117 this.rooms[(this.start_model_index + 2)%MODEL_NUM].setClose();
118
119 // 何度も通過した穴を鉄板にする.
120
121 foreach(var paper_control in this.shoji_control.papers) {
122
123 if(this.level_control.getChangeSteelCount() > 0) {
124
125 if(paper_control.through_count >= this.level_control.getChangeSteelCount()) {
126
127 paper_control.beginSteel();
128 }
129 }
130 }
131
132 //
133
134 this.room_count++;
135 this.is_closed = false;
136 }
137
138 // カメラが近づいたら、閉める.
139 //
140 // 本当はプレイヤーを見るべきだけど、部屋モデルのリピート処理がカメラを.
141 // みている関係上、こちらもカメラを見る.
142
143 float close_distance = MODEL_LENGTH - this.level_control.getCloseDistance();
144
145 if(room.transform.position.z + close_distance < this.main_camera.transform.position.z) {
146
147 do {
148
149 if(this.is_closed) {
150
151 break;
152 }
153
154 // スタート直後は閉まらないようにする.
155 if(this.room_count < 1) {
156
157 break;
158 }
159
160 // 障子を閉める.
161
162 if(this.scene_control.step == SceneControl.STEP.GAME) {
163
164 FloorControl.CLOSING_PATTERN_TYPE type;
165 bool is_flip;
166 FloorControl.ClosingPatternParam param;
167
168 this.level_control.getClosingPattern(out type, out is_flip, out param);
169
170 this.rooms[(this.start_model_index + 0)%MODEL_NUM].setClosingPatternType(type, is_flip, param);
171 this.rooms[(this.start_model_index + 0)%MODEL_NUM].beginCloseShoji();
172 }
173
174 this.is_closed = true;
175
176 } while(false);
177 }
178
179 #if false
180 // デバッグ機能.
181 // フルキーの数字キーで、障子の登場パターンを再生する.
182
183 for(int i = (int)KeyCode.Alpha1;i <= (int)KeyCode.Alpha9;i++) {
184
185 if(Input.GetKeyDown((KeyCode)i)) {
186
187 FloorControl.CLOSING_PATTERN_TYPE type = (FloorControl.CLOSING_PATTERN_TYPE)(i - (int)KeyCode.Alpha1);
188
189 bool is_flip = Input.GetKey(KeyCode.RightShift);
190
191 this.rooms[(this.start_model_index + 0)%MODEL_NUM].attachShouji(this.shoji_control);
192 this.rooms[(this.start_model_index + 0)%MODEL_NUM].setClosingPatternType(type, is_flip);
193 this.rooms[(this.start_model_index + 0)%MODEL_NUM].beginCloseShoji();
194 }
195 }
196 #endif
197 }
198
199 public void onRestart()
200 {
201 this.room_count = 0;
202 this.is_closed = false;
203
204 this.rooms[(this.start_model_index + 0)%MODEL_NUM].attachShouji(this.shoji_control);
205 this.rooms[(this.start_model_index + 0)%MODEL_NUM].setOpen();
206 this.rooms[(this.start_model_index + 1)%MODEL_NUM].setOpen();
207 this.rooms[(this.start_model_index + 2)%MODEL_NUM].setClose();
208 }
209
210 // ミスした後のリスタート位置を取得する.
211 public Vector3 getRestartPosition()
212 {
213 Vector3 position;
214
215 position = this.rooms[this.start_model_index].transform.position;
216
217 position.z += RESTART_Z_OFFSET;
218
219 return(position);
220 }
221
222 // 紙ののこり枚数を取得する.
223 public int getPaperNum()
224 {
225 return(this.shoji_control.getPaperNum());
226 }
227 }

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 游戏流程管理
6 /// </summary>
7 public class SceneControl : MonoBehaviour {
8
9 public enum STEP {
10
11 NONE = -1,
12
13 GAME = 0, // ゲーム中.
14 GAMEOVER, // ゲームオーバー.
15 CLEAR, // ゲームクリアー.
16
17 NUM,
18 };
19
20 public STEP step = STEP.NONE;
21 public STEP next_step = STEP.NONE;
22 public float step_timer = 0.0f;
23
24 // ---------------------------------------------------------------- //
25
26 private int combo_count = 0; // コンボカウント 連続して紙をやぶった回数.
27
28 // Life Setting
29 public Texture2D LifeTexture = null;
30 public static int init_lifecnt = 5;
31 public static int lifecnt = init_lifecnt;
32
33 public Texture2D FailedTexture = null;
34 public Texture2D Combo01Texture = null;
35 public Texture2D Combo02Texture = null;
36 public Texture2D EndTexture = null;
37
38 private float TextureWidth = 0.0f;
39 private float TextureHeight = 0.0f;
40 private float TextureScale = 200.0f;
41
42 private float TextureX = 10.0f;
43 private float TextureY = 480.0f;
44 private float TexturePosScale = 600.0f;
45
46 // ---------------------------------------------------------------- //
47
48 public bool clearflg = false; // 「おしまい」表示中?.
49 public float clear_timer = 0.0f;
50
51 public enum COMBO {
52
53 FAILED = -1,
54 NORMAL = 0,
55
56 CHAIN01,
57 CHAIN02,
58 };
59
60 public COMBO combo = COMBO.NORMAL;
61
62 // ---------------------------------------------------------------- //
63 // Audio
64 public AudioClip COMBO_SOUND_01 = null;
65 public AudioClip COMBO_SOUND_02 = null;
66 public AudioClip COMBO_SOUND_03 = null;
67
68 public AudioClip CLEAR_SOUND = null;
69 public AudioClip CLEAR_NEKO_SOUND = null;
70 public AudioClip CLEAR_LOOP_SOUND = null;
71 public AudioClip GAMEOVER_SOUND = null;
72 public AudioClip GAMEOVER_NEKO_SOUND = null;
73
74 public NekoControl neko_control = null;
75 public RoomControl room_control = null;
76
77 // ---------------------------------------------------------------- //
78 // Syouji Setting
79 public Transform syouji = null;
80 public Transform syouji_paper = null;
81 public GameObject syouji_steel = null;
82 private int SyoujiCnt = 0;
83
84 // ---------------------------------------------------------------- //
85
86 // Use this for initialization
87 void Start () {
88
89 this.neko_control = GameObject.FindGameObjectWithTag("NekoPlayer").GetComponent<NekoControl>();
90
91 this.room_control = GameObject.FindGameObjectWithTag("RoomControl").GetComponent<RoomControl>();
92
93 this.clearflg = false;
94 }
95
96 // Update is called once per frame
97 void Update () {
98
99 this.step_timer += Time.deltaTime;
100
101 // ---------------------------------------------------------------- //
102 // 次の状態に移るかどうかを、チェックする.
103
104 if(this.next_step == STEP.NONE) {
105
106 switch(this.step) {
107
108 case STEP.NONE:
109 {
110 this.next_step = STEP.GAME;
111 }
112 break;
113
114 case STEP.GAME:
115 {
116 int shoji_num = this.getPaperNum();
117
118 if(shoji_num == 0) {
119
120 this.next_step = STEP.CLEAR;
121 }
122
123 if(this.getLifeCount() <= 0) {
124
125 this.next_step = STEP.GAMEOVER;
126 }
127 }
128 break;
129 }
130 }
131
132 // ---------------------------------------------------------------- //
133 // 状態が遷移したときの初期化.
134
135 if(this.next_step != STEP.NONE) {
136
137 switch(this.next_step) {
138
139 case STEP.GAME:
140 {
141 this.clearComboCount();
142 this.clear_timer = 0.0f;
143 lifecnt = init_lifecnt;
144 }
145 break;
146
147 case STEP.CLEAR:
148 {
149 // 自動運転開始.
150 this.neko_control.beginAutoDrive();
151 StartCoroutine("gameClear");
152 }
153 break;
154
155 case STEP.GAMEOVER:
156 {
157 // 「おしまい」をすぐに表示.
158 this.clearflg = true;
159 }
160 break;
161 }
162
163 this.step = this.next_step;
164 this.next_step = STEP.NONE;
165
166 this.step_timer = 0.0f;
167 }
168
169 // ---------------------------------------------------------------- //
170 // 各状態での実行処理.
171
172 switch(this.step) {
173
174 case STEP.CLEAR:
175 {
176 if(!this.clearflg) {
177
178 // 一定時間たったら、「おしまい」を自動的に表示.
179 if(this.step_timer > CLEAR_NEKO_SOUND.length + CLEAR_SOUND.length + CLEAR_LOOP_SOUND.length) {
180
181 this.clearflg = true;
182 }
183 }
184 }
185 break;
186
187 }
188
189 // ---------------------------------------------------------------- //
190 }
191
192
193 void OnGUI () {
194
195 if(!LifeTexture) {
196
197 Debug.LogError("A Texture is not assigned.");
198 return;
199 }
200
201 for ( int i = 0; i < lifecnt - 1; i++ ) {
202
203 GUI.Label(new Rect(10, 4*Screen.height/5-25*i, LifeTexture.width/2, LifeTexture.height/2), LifeTexture);
204
205 }
206
207 if ( lifecnt > 0 ) {
208
209 switch(this.combo) {
210
211 case COMBO.FAILED:
212 {
213 this.TextureWidth -= this.TextureScale*Time.deltaTime;
214 this.TextureWidth = Mathf.Clamp(this.TextureWidth, FailedTexture.width/8, Combo02Texture.width/6);
215 this.TextureHeight -= this.TextureScale*Time.deltaTime;
216 this.TextureHeight = Mathf.Clamp(this.TextureHeight, FailedTexture.height/8, Combo02Texture.height/6);
217
218 this.TextureX += this.TexturePosScale*Time.deltaTime;
219 this.TextureX = Mathf.Clamp(this.TextureX, 0, 10);
220 this.TextureY += this.TexturePosScale*Time.deltaTime;
221 this.TextureY = Mathf.Clamp(this.TextureY, 4*Screen.height/5-35*(lifecnt - 1), 4*Screen.height/5-25*(lifecnt - 1));
222
223 GUI.Label(new Rect(this.TextureX, this.TextureY, this.TextureWidth, this.TextureHeight), FailedTexture);
224 }
225 break;
226
227 case COMBO.NORMAL:
228 {
229 this.TextureWidth -= this.TextureScale*Time.deltaTime;
230 this.TextureWidth = Mathf.Clamp(this.TextureWidth, LifeTexture.width/2, Combo02Texture.width/6);
231 this.TextureHeight -= this.TextureScale*Time.deltaTime;
232 this.TextureHeight = Mathf.Clamp(this.TextureHeight, LifeTexture.height/2, Combo02Texture.height/6);
233
234 this.TextureX += this.TexturePosScale*Time.deltaTime;
235 this.TextureX = Mathf.Clamp(this.TextureX, 0, 10);
236 this.TextureY += this.TexturePosScale*Time.deltaTime;
237 this.TextureY = Mathf.Clamp(this.TextureY, 4*Screen.height/5-35*(lifecnt - 1), 4*Screen.height/5-25*(lifecnt - 1));
238
239 GUI.Label(new Rect(this.TextureX, this.TextureY, this.TextureWidth, this.TextureHeight), LifeTexture);
240 }
241 break;
242
243 case COMBO.CHAIN01:
244 {
245 this.TextureWidth += this.TextureScale*Time.deltaTime;
246 this.TextureWidth = Mathf.Clamp(this.TextureWidth, LifeTexture.width/2, Combo01Texture.width/6);
247 this.TextureHeight += this.TextureScale*Time.deltaTime;
248 this.TextureHeight = Mathf.Clamp(this.TextureHeight, LifeTexture.height/2, Combo01Texture.height/6);
249
250 this.TextureX -= this.TexturePosScale*Time.deltaTime;
251 this.TextureX = Mathf.Clamp(this.TextureX, 7, 10);
252 this.TextureY -= this.TexturePosScale*Time.deltaTime;
253 this.TextureY = Mathf.Clamp(this.TextureY, 4*Screen.height/5-21*lifecnt, 4*Screen.height/5-14*lifecnt);
254
255 GUI.Label(new Rect(this.TextureX, this.TextureY, this.TextureWidth, this.TextureHeight), Combo01Texture);
256 }
257 break;
258
259 case COMBO.CHAIN02:
260 {
261 this.TextureWidth += this.TextureScale*Time.deltaTime;
262 this.TextureWidth = Mathf.Clamp(this.TextureWidth, Combo01Texture.width/6, Combo02Texture.width/4);
263 this.TextureHeight += this.TextureScale*Time.deltaTime;
264 this.TextureHeight = Mathf.Clamp(this.TextureHeight, Combo01Texture.height/6, Combo02Texture.height/4);
265
266 this.TextureX -= this.TexturePosScale*Time.deltaTime;
267 this.TextureX = Mathf.Clamp(this.TextureX, 0, 7);
268 this.TextureY -= this.TexturePosScale*Time.deltaTime;
269 this.TextureY = Mathf.Clamp(this.TextureY, 4*Screen.height/5-28*lifecnt, 4*Screen.height/5-24*lifecnt);
270
271 GUI.Label(new Rect(this.TextureX, this.TextureY, this.TextureWidth, this.TextureHeight), Combo02Texture);
272 }
273 break;
274 }
275 }
276
277 // Count SyoujiPaper from Tags
278 SyoujiCnt = this.getPaperNum();
279
280 if((SyoujiCnt <= 0) || (lifecnt <=0)) {
281
282 if ( Input.GetMouseButton(0) ) {
283
284 this.clearflg = true;
285
286 }
287
288 if (this.clearflg) {
289
290 this.clear_timer += Time.deltaTime;
291
292 GUI.Label(new Rect(64, 112, EndTexture.width, EndTexture.height), EndTexture);
293
294 if ( (Input.GetMouseButton(0)) && (clear_timer > 1.0f)) {
295
296 Application.LoadLevel("TitleScene");
297 }
298 }
299 }
300
301 //
302 }
303
304 void applyDamage(int damage) {
305
306 this.clearComboCount();
307 lifecnt -= damage;
308
309 if ( lifecnt <= 0 ) {
310
311 StartCoroutine("gameOver");
312 }
313 }
314
315 void nekoFailed() {
316
317 this.combo = COMBO.FAILED;
318 }
319
320 public int getLifeCount()
321 {
322 return(SceneControl.lifecnt);
323 }
324
325 // 紙の残り枚数を取得する.
326 public int getPaperNum()
327 {
328 return(this.room_control.getPaperNum());
329 }
330
331 // コンボカウントプラス.
332 public void addComboCount()
333 {
334 this.combo_count++;
335
336 switch(this.combo_count) {
337
338 case 0:
339 {
340 GetComponent<AudioSource>().clip = COMBO_SOUND_01;
341 }
342 break;
343
344 case 1:
345 {
346 GetComponent<AudioSource>().clip = COMBO_SOUND_01;
347 }
348 break;
349
350 case 2:
351 {
352 GetComponent<AudioSource>().clip = COMBO_SOUND_02;
353 this.combo = COMBO.CHAIN01;
354 }
355 break;
356
357 default:
358 {
359 GetComponent<AudioSource>().clip = COMBO_SOUND_03;
360 this.combo = COMBO.CHAIN02;
361 }
362 break;
363
364 }
365
366 GetComponent<AudioSource>().Play();
367 }
368
369 // コンボカウントを0にする.
370 public void clearComboCount()
371 {
372 this.combo_count = 0;
373 this.combo = COMBO.NORMAL;
374 }
375
376 private IEnumerator gameClear()
377 {
378 GetComponent<AudioSource>().clip = CLEAR_NEKO_SOUND;
379 GetComponent<AudioSource>().Play();
380
381 yield return new WaitForSeconds(CLEAR_NEKO_SOUND.length);
382 GetComponent<AudioSource>().clip = CLEAR_SOUND;
383 GetComponent<AudioSource>().Play();
384
385 yield return new WaitForSeconds(CLEAR_SOUND.length);
386 GetComponent<AudioSource>().clip = CLEAR_LOOP_SOUND;
387 GetComponent<AudioSource>().loop = true;
388 GetComponent<AudioSource>().Play();
389 }
390
391 private IEnumerator gameOver()
392 {
393 GetComponent<AudioSource>().clip = GAMEOVER_NEKO_SOUND;
394 GetComponent<AudioSource>().Play();
395
396 yield return new WaitForSeconds(GAMEOVER_NEKO_SOUND.length);
397 GetComponent<AudioSource>().clip = GAMEOVER_SOUND;
398 GetComponent<AudioSource>().Play();
399 }
400
401 }

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 控制窗户
6 /// </summary>
7 public class ShojiControl:MonoBehaviour {
8
9 /// <summary>
10 /// 洞索引
11 /// </summary>
12 public struct HoleIndex {
13 /// <summary>
14 /// x
15 /// </summary>
16 public int x;
17 /// <summary>
18 /// y
19 /// </summary>
20 public int y;
21
22 };
23
24 /// <summary>
25 /// 初始x位置
26 /// </summary>
27 public float init_x = 0.0f;
28 /// <summary>
29 /// 初始y位置
30 /// </summary>
31 public float init_y = 2.0f;
32 /// <summary>
33 /// 初始z位置
34 /// </summary>
35 public float init_z = 5.0f;
36
37 // 床の幅(Z方向).
38 public static float WIDTH = 15.0f;
39
40 // プレイヤーとの距離 (DIST < WIDTH).
41 public float DIST = 10.0f;
42
43 // 自オブジェクト移動距離.
44 public static float MOVE = 0.1f;
45
46 // 自オブジェクトニュートラルポジション.
47 public Vector3 neutral_position;
48
49 public GameObject paperPrefab;
50
51 /// <summary>
52 /// 窗户纸二维数组
53 /// </summary>
54 public SyoujiPaperControl[,] papers;
55
56 /// <summary>
57 /// 窗户纸x轴大小
58 /// </summary>
59 public static float TILE_SIZE_X = 0.85f;
60 /// <summary>
61 /// 窗户纸y轴大小
62 /// </summary>
63 public static float TILE_SIZE_Y = 0.94f;
64 /// <summary>
65 /// 窗户纸原始x
66 /// </summary>
67 public static float TILE_ORIGIN_X = -0.85f;
68 /// <summary>
69 /// 窗户纸原始y
70 /// </summary>
71 public static float TILE_ORIGIN_Y = 1.92f;
72
73 /// <summary>
74 /// x轴上窗户纸数量
75 /// </summary>
76 public static int TILE_NUM_X = 3;
77 /// <summary>
78 /// y轴上窗户纸数量
79 /// </summary>
80 public static int TILE_NUM_Y = 3;
81
82 /// <summary>
83 /// 窗户纸数量
84 /// </summary>
85 public int paper_num = TILE_NUM_X * TILE_NUM_Y;
86
87
88 void Start() {
89
90 this.neutral_position = this.transform.position;
91
92 this.papers = new SyoujiPaperControl[TILE_NUM_X,TILE_NUM_Y];
93
94 for(int x = 0;x < TILE_NUM_X;x++) {
95 for(int y = 0;y < TILE_NUM_Y;y++) {
96 //实例化窗户纸预设
97 GameObject go = Instantiate(this.paperPrefab) as GameObject;
98 go.transform.parent = this.transform;
99
100 //根据纸的索引计算实际显示的位置
101 Vector3 position = go.transform.localPosition;
102 position.x = TILE_ORIGIN_X + x * TILE_SIZE_X;
103 position.y = TILE_ORIGIN_Y + y * TILE_SIZE_Y;
104 position.z = 0.0f;
105 go.transform.localPosition = position;
106
107 //设置窗户纸的控制脚本
108 SyoujiPaperControl paper_control = go.GetComponent<SyoujiPaperControl>();
109 paper_control.shoji_control = this;
110 paper_control.hole_index.x = x;
111 paper_control.hole_index.y = y;
112
113 this.papers[x,y] = paper_control;
114 }
115 }
116 this.paper_num = this.papers.Length;
117 }
118
119 void Update() {
120
121 }
122
123 /// <summary>
124 /// 窗户纸被破坏
125 /// </summary>
126 public void onPaperBreak() {
127 //窗户纸数量减1
128 this.paper_num--;
129 //保证窗户纸数量不小于0
130 this.paper_num = Mathf.Max(0,this.paper_num);
131
132 // 空振りカウンター(破れた後に通過した回数)をリセットする.
133 //
134 // 1.紙Aをやぶる
135 // 2.紙Aを通過(紙Aの空振りカウンターが増加)
136 // 3.紙Bをやぶる
137 // 4.紙Bを通過 ←このタイミングで紙Aが鉄板化してしまうことがあるので.
138
139 for(int x = 0;x < TILE_NUM_X;x++) {
140
141 for(int y = 0;y < TILE_NUM_Y;y++) {
142
143 this.papers[x,y].resetThroughCount();
144 }
145 }
146 }
147
148 // 紙の残り枚数を取得する.
149 public int getPaperNum() {
150 return (this.paper_num);
151 }
152
153 // 『格子の穴』インデックスが有効?.
154 public bool isValidHoleIndex(HoleIndex hole_index) {
155 bool ret = false;
156
157 do {
158
159 ret = false;
160
161 if(hole_index.x < 0 || TILE_NUM_X <= hole_index.x) {
162
163 break;
164 }
165 if(hole_index.y < 0 || TILE_NUM_Y <= hole_index.y) {
166
167 break;
168 }
169
170 ret = true;
171
172 } while(false);
173
174 return (ret);
175 }
176
177 // いちばん近い『格子の穴』を取得する.
178 public HoleIndex getClosetHole(Vector3 position) {
179 HoleIndex hole_index;
180
181 position = this.transform.InverseTransformPoint(position);
182
183 hole_index.x = Mathf.RoundToInt((position.x - TILE_ORIGIN_X) / TILE_SIZE_X);
184 hole_index.y = Mathf.RoundToInt((position.y - TILE_ORIGIN_Y) / TILE_SIZE_Y);
185
186 return (hole_index);
187 }
188
189 // 『格子の穴』の位置座標を取得する.
190 public Vector3 getHoleWorldPosition(int hole_pos_x,int hole_pos_y) {
191 Vector3 position;
192
193 position.x = (float)hole_pos_x * TILE_SIZE_X + TILE_ORIGIN_X;
194 position.y = (float)hole_pos_y * TILE_SIZE_Y + TILE_ORIGIN_Y;
195 position.z = 0.0f;
196
197 position = this.transform.TransformPoint(position);
198
199 return (position);
200 }
201
202 }

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 窗户,拉门的共通处理
6 /// </summary>
7 public class ShutterControl:MonoBehaviour {
8
9 /// <summary>
10 /// 设置x位置
11 /// </summary>
12 public void setX(float x) {
13 Vector3 position = this.transform.localPosition;
14 position.x = x;
15 this.transform.localPosition = position;
16 }
17 }

1 //using UnityEngine;
2 using System.Collections;
3
4 // std::vector っぽい配列(ただしサイズは固定、値型じゃないとだめかも).
5 public class StaticArray<T> {
6
7
8 public StaticArray(int max_num)
9 {
10 this.entity = new T[max_num];
11
12 this.num_max = max_num;
13 this.num_current = 0;
14
15 }
16
17 //
18
19 public void push_back(T x)
20 {
21 if(this.num_current < this.num_max) {
22
23 this.entity[this.num_current++] = x;
24 }
25 }
26 public int size()
27 {
28 return(this.num_current);
29 }
30 public int capacity()
31 {
32 return(this.num_max);
33 }
34 public bool full()
35 {
36 return(this.num_current >= this.num_max);
37 }
38
39 public void resize(int size)
40 {
41 this.num_current = size;
42 }
43 public void clear()
44 {
45 this.resize(0);
46 }
47
48 public void erase_by_index(int index)
49 {
50 for(int i = index;i < this.num_current - 1;i++) {
51
52 this.entity[i] = this.entity[i + 1];
53 }
54
55 this.num_current--;
56 }
57
58 public void swap(int i, int j)
59 {
60 T temp;
61
62 temp = this.entity[i];
63 this.entity[i] = this.entity[j];
64 this.entity[j] = temp;
65 }
66
67 public T this[int i]
68 {
69 get { return(this.entity[i]); }
70 set { this.entity[i] = value; }
71 }
72 public IEnumerator GetEnumerator()
73 {
74 int i = 0;
75
76 for(i = 0;i < this.num_max;i++) {
77
78 yield return(this.entity[i]);
79 }
80 }
81
82 private int num_max;
83 private int num_current;
84
85 private T[] entity;
86 };

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 播放猫的脚步声
6 /// </summary>
7 public class StepSoundControl:MonoBehaviour {
8
9 /// <summary>
10 /// 行走声音1
11 /// </summary>
12 public AudioClip stepSE1 = null;
13 /// <summary>
14 /// 行走声音2
15 /// </summary>
16 public AudioClip stepSE2 = null;
17
18 /// <summary>
19 /// 当前行走声音
20 /// </summary>
21 public int step_sound_sel = 0;
22
23 void Start() {
24 //给动画剪辑添加播放声音事件
25 AnimationEvent ev = new AnimationEvent();
26 ev.time = this.GetComponent<Animation>()["M02_nekodash"].clip.length / 2.0f; ;
27 ev.functionName = "PlayStepSound";
28 this.GetComponent<Animation>()["M02_nekodash"].clip.AddEvent(ev);
29 }
30
31 /// <summary>
32 /// 播放声音
33 /// </summary>
34 public void PlayStepSound(AnimationEvent ev) {
35 if(this.step_sound_sel == 0) {
36 this.GetComponent<AudioSource>().PlayOneShot(this.stepSE1);
37 } else {
38 this.GetComponent<AudioSource>().PlayOneShot(this.stepSE2);
39 }
40 this.step_sound_sel = (this.step_sound_sel + 1) % 2;
41 }
42 }

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 控制单张窗户纸(状态[普通/破损/铁板]管理等)
6 /// </summary>
7 public class SyoujiPaperControl:MonoBehaviour {
8
9 /// <summary>
10 /// 木窗纸状态
11 /// </summary>
12 public enum STEP {
13 /// <summary>
14 /// 默认
15 /// </summary>
16 NONE = -1,
17 /// <summary>
18 /// 纸
19 /// </summary>
20 PAPER = 0,
21 /// <summary>
22 /// 损坏
23 /// </summary>
24 BROKEN,
25 /// <summary>
26 /// 铁
27 /// </summary>
28 STEEL,
29 };
30
31 /// <summary>
32 /// 当前状态
33 /// </summary>
34 public STEP step = STEP.NONE;
35 /// <summary>
36 /// 下一个状态
37 /// </summary>
38 public STEP next_step = STEP.NONE;
39 /// <summary>
40 /// 状态计时器
41 /// </summary>
42 public float step_timer = 0.0f;
43
44 /// <summary>
45 /// 流程管理
46 /// </summary>
47 private SceneControl scene_control = null;
48 /// <summary>
49 /// 窗户控制
50 /// </summary>
51 public ShojiControl shoji_control = null;
52
53 /// <summary>
54 /// 在木窗中的洞索引
55 /// </summary>
56 public ShojiControl.HoleIndex hole_index;
57
58 /// <summary>
59 /// 纸
60 /// </summary>
61 public GameObject paper_object = null;
62 /// <summary>
63 /// 破坏的纸
64 /// </summary>
65 public GameObject broken_object = null;
66 /// <summary>
67 /// 铁
68 /// </summary>
69 public GameObject steel_object = null;
70
71 /// <summary>
72 /// 成功穿过的声音
73 /// </summary>
74 public AudioClip SUCCESS_SOUND = null;
75
76 /// <summary>
77 /// 穿过的次数
78 /// </summary>
79 public int through_count = 0;
80
81 void Start() {
82 //查找场景管理
83 this.scene_control = GameObject.FindWithTag("MainCamera").GetComponent<SceneControl>();
84 //设置子物体
85 for(int i = 0;i < this.transform.childCount;i++) {
86 GameObject child = this.transform.GetChild(i).gameObject;
87 switch(child.tag) {
88 case "SyoujiPaper": {
89 this.paper_object = child;
90 }
91 break;
92 case "SyoujiPaperBroken": {
93 this.broken_object = child;
94 }
95 break;
96 case "SyoujiSteel": {
97 this.steel_object = child;
98 }
99 break;
100 }
101 }
102
103 this.paper_object.SetActive(false);
104 this.broken_object.SetActive(false);
105 this.steel_object.SetActive(false);
106
107 //设置下一个状态为纸
108 this.next_step = STEP.PAPER;
109 }
110
111 void Update() {
112 //计时器加上本帧时间
113 this.step_timer += Time.deltaTime;
114
115 //根据下一个状态设置 子物体的显隐
116 if(this.next_step != STEP.NONE) {
117 switch(this.next_step) {
118 case STEP.PAPER: {
119 this.paper_object.SetActive(true);
120 this.broken_object.SetActive(false);
121 this.steel_object.SetActive(false);
122 }
123 break;
124 case STEP.BROKEN: {
125 this.paper_object.SetActive(false);
126 this.broken_object.SetActive(true);
127 this.steel_object.SetActive(false);
128 //播放成功声音
129 this.GetComponent<AudioSource>().PlayOneShot(SUCCESS_SOUND);
130 }
131 break;
132 case STEP.STEEL: {
133 this.paper_object.SetActive(false);
134 this.broken_object.SetActive(false);
135 this.steel_object.SetActive(true);
136 }
137 break;
138 }
139
140 //当前状态设为下一个状态
141 this.step = this.next_step;
142 //重置下一个状态
143 this.next_step = STEP.NONE;
144 //重置状态计时器
145 this.step_timer = 0.0f;
146 }
147 }
148
149 /// <summary>
150 /// 铁状态
151 /// </summary>
152 public void beginSteel() {
153 this.next_step = STEP.STEEL;
154 }
155
156 /// <summary>
157 /// 是否是铁
158 /// </summary>
159 public bool isSteel() {
160 bool ret;
161 ret = (this.step == STEP.STEEL);
162 return (ret);
163 }
164
165 /// <summary>
166 /// 重置穿越次数
167 /// </summary>
168 public void resetThroughCount() {
169 this.through_count = 0;
170 }
171
172 /// <summary>
173 /// 处理玩家碰撞
174 /// </summary>
175 public void onPlayerCollided() {
176 //判断当前状态
177 switch(this.step) {
178 //纸
179 case STEP.PAPER: {
180 //下一个状态为破坏的纸
181 this.next_step = STEP.BROKEN;
182 //场景管理添加连击
183 this.scene_control.addComboCount();
184 //木窗控制调用纸被破坏事件
185 this.shoji_control.onPaperBreak();
186 //创建木窗破坏特效
187 this.scene_control.neko_control.effect_control.createBreakEffect(this,this.scene_control.neko_control);
188 }
189 break;
190 //破坏的纸
191 case STEP.BROKEN: {
192 //添加穿过次数
193 this.through_count++;
194 //场景控制 清空连击数
195 this.scene_control.clearComboCount();
196 }
197 break;
198 }
199 }
200 }

1 using UnityEngine;
2 using System.Collections;
3
4 /// <summary>
5 /// 主题画面
6 /// </summary>
7 public class TitleControl:MonoBehaviour {
8 /// <summary>
9 /// 标题纹理
10 /// </summary>
11 public Texture2D TitleTexture = null;
12 /// <summary>
13 /// 简单纹理
14 /// </summary>
15 public Texture2D TitleEasy = null;
16 /// <summary>
17 /// 普通纹理
18 /// </summary>
19 public Texture2D TitleNormal = null;
20 /// <summary>
21 /// 难纹理
22 /// </summary>
23 public Texture2D TitleHard = null;
24
25 /// <summary>
26 /// 是否按下play按钮
27 /// </summary>
28 private bool PlayButtonPushed = false;
29
30 void Start() {
31 PlayButtonPushed = false;
32 }
33
34 void Update() {
35
36 }
37
38 void OnGUI() {
39 //没有标题,debug
40 if(!TitleTexture) {
41 Debug.LogError("Assign a Texture in the inspector.");
42 return;
43 }
44 //画标题纹理
45 GUI.DrawTexture(new Rect(0,0,TitleTexture.width,TitleTexture.height),TitleTexture);
46
47 //简单按钮
48 if(GUI.Button(new Rect(0,3 * Screen.height / 4 - TitleEasy.height / 2 + 40,TitleEasy.width,TitleEasy.height),TitleEasy,GUI.skin.label)) {
49 if(!PlayButtonPushed) {
50 PlayButtonPushed = true;
51 GlobalParam.GetInstance().SetMode(0);
52 Application.LoadLevel("GameScene");
53 }
54 }
55 //正常按钮
56 if(GUI.Button(new Rect(Screen.width / 2 - TitleNormal.width / 2,3 * Screen.height / 4 - TitleNormal.height / 2 + 40,TitleNormal.width,TitleNormal.height),TitleNormal,GUI.skin.label)) {
57 if(!PlayButtonPushed) {
58 PlayButtonPushed = true;
59 GlobalParam.GetInstance().SetMode(1);
60 Application.LoadLevel("GameScene");
61 }
62 }
63 //难按钮
64 if(GUI.Button(new Rect(Screen.width - TitleHard.width,3 * Screen.height / 4 - TitleHard.height / 2 + 40,TitleHard.width,TitleHard.height),TitleHard,GUI.skin.label)) {
65 if(!PlayButtonPushed) {
66 PlayButtonPushed = true;
67 GlobalParam.GetInstance().SetMode(2);
68 Application.LoadLevel("GameScene");
69 }
70 }
71 }
72
73 }
视频:https://pan.baidu.com/s/1geBDjJP
项目:https://pan.baidu.com/s/1eSooRWA
本文介绍了一个Unity游戏开发中的镜头控制、特效控制及声音播放控制等关键组件的实现方式。包括如何实现平滑的相机跟随效果、特效的自动销毁机制以及播放特定声音的方法。
126

被折叠的 条评论
为什么被折叠?



