猫跳窗户 学习
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