public Block.CARD selectBlockColor() { Block.CARD color = Block.CARD.FIRST; // 이번 레벨의 레벨 데이터를 가져온다. LevelControl.LevelData level_data = this.level_control.getCurrentLevelData(); float rand = Random.Range(0.0f, 1.0f); // 0.0~1.0 사이의 난수. float sum = 0.0f; // 출현 확률의 합계. int i = 0; // 블록의 종류 전체를 처리하는 루프. for (i = 0; i < level_data.probability.Length - 1; i++) { if (level_data.probability[i] == 0.0f) { continue; // 출현 확률이 0이면 루프의 처음으로 점프. } sum += level_data.probability[i]; // 출현 확률을 더한다. if (rand < sum) { // 합계가 난숫값을 웃돌면. break; // 루프를 빠져나온다. } } color = (Block.CARD)i; // i번째 색을 반환한다. return(color); }
// 낙하했을 때 위아래 블록을 교체한다. public void fallBlock(BlockControl block0, Block.DIR4 dir, BlockControl block1) { // block0과 block1의 색, 크기, 사라질 때까지 걸리는 시간, 표시, 비표시, 상태 // 를 기록. Block.CARD color0 = block0.color; Block.CARD color1 = block1.color; Vector3 scale0 = block0.transform.localScale; Vector3 scale1 = block1.transform.localScale; float vanish_timer0 = block0.vanish_timer; float vanish_timer1 = block1.vanish_timer; bool visible0 = block0.isVisible(); bool visible1 = block1.isVisible(); Block.STEP step0 = block0.step; Block.STEP step1 = block1.step; // block0과 block1의 각종 속성을 교체한다. block0.setColor(color1); block1.setColor(color0); block0.transform.localScale = scale1; block1.transform.localScale = scale0; block0.vanish_timer = vanish_timer1; block1.vanish_timer = vanish_timer0; block0.setVisible(visible1); block1.setVisible(visible0); block0.step = step1; block1.step = step0; block0.beginFall(block1); }
// 실제로 블록을 교체한다. public void swapBlock(BlockControl block0, Block.DIR4 dir, BlockControl block1) { // 각각의 블록 색을 기억해 둔다. Block.CARD color0 = block0.color; Block.CARD color1 = block1.color; // 각각의 블록의 확대율을 기억해 둔다. Vector3 scale0 = block0.transform.localScale; Vector3 scale1 = block1.transform.localScale; // 각각의 블록의 '사라지는 시간'을 기억해 둔다. float vanish_timer0 = block0.vanish_timer; float vanish_timer1 = block1.vanish_timer; // 각각의 블록의 이동할 곳을 구한다. Vector3 offset0 = BlockRoot.getDirVector(dir); Vector3 offset1 = BlockRoot.getDirVector(BlockRoot.getOppositDir(dir)); // 색을 교체한다. block0.setColor(color1); block1.setColor(color0); // 확대율을 교체한다. block0.transform.localScale = scale1; block1.transform.localScale = scale0; // '사라지는 시간'을 교체한다. block0.vanish_timer = vanish_timer1; block1.vanish_timer = vanish_timer0; block0.beginSlide(offset0); // 원래 블록 이동을 시작한다. block1.beginSlide(offset1); // 이동할 위치의 블록 이동을 시작한다. }
// 색이 바꿔 낙하 상태로 하고 지정한 위치에 재배치한다. public void beginRespawn(int start_ipos_y) { // 지정 위치까지 y좌표를 이동. this.position_offset.y = (float)(start_ipos_y - this.i_pos.y) * Block.COLLISION_SIZE; this.next_step = Block.STEP.FALL; //int color_index = //Random.Range((int)Block.COLOR.FIRST, (int)Block.COLOR.LAST + 1); //this.setColor((Block.COLOR)color_index); // 현재 레벨의 출현 확률을 바탕으로 블록의 색을 결정한다. Block.CARD color = this.block_root.selectBlockColor(); this.setColor(color); }
/// <summary> /// //////////////////////////////////////////////////////////////////////// /// </summary> // 블록을 만들어 내고 가로 9칸, 세로 9칸에 배치한다. public void initialSetUp() { // 그리드의 크기를 9×9로 한다. this.blocks = new BlockControl[Block.BLOCK_NUM_X, Block.BLOCK_NUM_Y]; // 블록의 색 번호. int color_index = 0; Block.CARD color = Block.CARD.FIRST; for (int y = 0; y < Block.BLOCK_NUM_Y; y++) { // 처음~마지막행 for (int x = 0; x < Block.BLOCK_NUM_X; x++) { // 왼쪽~오른쪽 // BlockPrefab의 인스턴스를 씬에 만든다. GameObject game_object = Instantiate(this.BlockPrefab) as GameObject; // 위에서 만든 블록의 BlockControl 클래스를 가져온다. BlockControl block = game_object.GetComponent <BlockControl>(); // 블록을 그리드에 저장한다. this.blocks[x, y] = block; // 블록의 위치 정보(그리드 좌표)를 설정한다. block.i_pos.x = x; block.i_pos.y = y; // 각 BlockControl이 연계할 GameRoot는 자신이라고 설정한다. block.block_root = this; // 그리드 좌표를 실제 위치(씬의 좌표)로 변환한다. Vector3 position = BlockRoot.calcBlockPosition(block.i_pos); // 씬의 블록 위치를 이동한다. block.transform.position = position; //// 블록의 색을 변경한다. //block.setColor((Block.COLOR)color_index); // 현재 출현 확률을 바탕으로 색을 결정한다. color = this.selectBlockColor(); block.setColor(color); // 블록의 이름을 설정(후술)한다. 나중에 블록 정보 확인때 필요. block.name = "block(" + block.i_pos.x.ToString() + "," + block.i_pos.y.ToString() + ")"; // 전체 색 중에서 임의로 하나의 색을 선택한다. color_index = Random.Range(0, (int)Block.CARD.NORMAL_CARD_NUM); } } }
/// //////////////////////////////////////////////////////////////////////////// // 인수 color의 색으로 블록을 칠한다. public void setColor(Block.CARD color) { this.color = color; // 이번에 지정된 색을 멤버 변수에 보관한다. Color color_value; // Color 클래스는 색을 나타낸다. Material card_mt; switch (this.color) { // 칠할 색에 따라서 갈라진다. default: case Block.CARD.HEART: card_mt = Resources.Load("Fire", typeof(Material)) as Material; //Material[] mts = renderer.materials; //mts[1] = mts; //renderer.materials = mts; break; case Block.CARD.DIAMOND: card_mt = Resources.Load("Water", typeof(Material)) as Material; break; case Block.CARD.SPADE: card_mt = Resources.Load("Ground", typeof(Material)) as Material; break; case Block.CARD.CLOBER: card_mt = Resources.Load("Heal", typeof(Material)) as Material; break; //case Block.CARD.MAGENTA: // color_value = Color.magenta; // break; //case Block.CARD.ORANGE: // 이런 컬러들은 유니티에 미리 지정되어있지 않아서 따로 색상 지정해줘야함 // color_value = new Color(1.0f, 0.46f, 0.0f); // break; } // 이 게임 오브젝트의 머티리얼 색상을 변경한다. this.GetComponent <Renderer>().material = card_mt; }
void Update() { Vector3 mouse_position; // 마우스 위치. this.block_root.unprojectMousePosition( // 마우스 위치 획득. out mouse_position, Input.mousePosition); // 획득한 마우스 위치를 X와 Y만으로 한다. Vector2 mouse_position_xy = new Vector2(mouse_position.x, mouse_position.y); // '다음 블록' 상태가 '정보 없음' 이외인 동안. // ='다음 블록' 상태가 변경된 경우. if (this.vanish_timer >= 0.0f) { // 타이머가 0 이상이면. this.vanish_timer -= Time.deltaTime; // 타이머의 값을 줄인다. if (this.vanish_timer < 0.0f) { // 타이머가 0 미만이면. if (this.step != Block.STEP.SLIDE) { // 슬라이드 중이 아니라면. this.vanish_timer = -1.0f; this.next_step = Block.STEP.VACANT; // 상태를 ‘소멸 중’으로. } else { this.vanish_timer = 0.0f; } } } this.step_timer += Time.deltaTime; float slide_time = 0.2f; if (this.next_step == Block.STEP.NONE) { // '상태 정보 없음'의 경우. switch (this.step) { case Block.STEP.SLIDE: if (this.step_timer >= slide_time) { // 슬라이드 중인 블록이 소멸되면 VACANT(사라진) 상태로 이행. if (this.vanish_timer == 0.0f) { this.next_step = Block.STEP.VACANT; // vanish_timer가 0이 아니면 IDLE(대기) 상태로 이행. } else { this.next_step = Block.STEP.IDLE; } } break; case Block.STEP.IDLE: this.GetComponent <Renderer>().enabled = true; break; case Block.STEP.FALL: if (this.position_offset.y <= 0.0f) { this.next_step = Block.STEP.IDLE; this.position_offset.y = 0.0f; } break; } } while (this.next_step != Block.STEP.NONE) { this.step = this.next_step; this.next_step = Block.STEP.NONE; switch (this.step) { case Block.STEP.IDLE: // '대기' 상태. this.position_offset = Vector3.zero; // 블록 표시 크기를 보통 크기로 한다. this.transform.localScale = Vector3.one * 1.0f; break; case Block.STEP.GRABBED: // '잡힌' 상태. // 블록 표시 크기를 크게 한다. this.transform.localScale = Vector3.one * 1.2f; break; case Block.STEP.RELEASED: // '떨어져 있는' 상태. this.position_offset = Vector3.zero; // 블록 표시 크기를 보통 사이즈로 한다. this.transform.localScale = Vector3.one * 1.0f; break; case Block.STEP.VACANT: this.position_offset = Vector3.zero; this.setVisible(false); // 블록을 표시하지 않게 한다. break; case Block.STEP.RESPAWN: // 색을 랜덤하게 선택하여 블록을 그 색으로 설정. //int color_index = Random.Range( //0, (int)Block.COLOR.NORMAL_COLOR_NUM); //this.setColor((Block.COLOR)color_index); int color_index = Random.Range( 0, (int)Block.CARD.NORMAL_CARD_NUM); this.setColor((Block.CARD)color_index); this.next_step = Block.STEP.IDLE; break; case Block.STEP.FALL: this.setVisible(true); // 블록을 표시. this.fall.velocity = 0.0f; // 낙하 속도 리셋. break; } this.step_timer = 0.0f; } switch (this.step) { case Block.STEP.GRABBED: // 잡힌 상태. // 잡힌 상태일 때는 항상 슬라이드 방향을 체크. this.slide_dir = this.calcSlideDir(mouse_position_xy); break; case Block.STEP.SLIDE: // 슬라이드(교체) 중. // 블록을 서서히 이동하는 처리. float rate = this.step_timer / slide_time; rate = Mathf.Min(rate, 1.0f); rate = Mathf.Sin(rate * Mathf.PI / 2.0f); this.position_offset = Vector3.Lerp(this.position_offset_initial, Vector3.zero, rate); break; case Block.STEP.FALL: // 속도에 중력의 영향을 부여한다. this.fall.velocity += Physics.gravity.y * Time.deltaTime * 0.3f; // 세로 방향 위치를 계산. this.position_offset.y += this.fall.velocity * Time.deltaTime; if (this.position_offset.y < 0.0f) { // 다 내려왔다면. this.position_offset.y = 0.0f; // 그 자리에 머무른다. } break; } // 그리드 좌표를 실제 좌표(씬의 좌표)로 변환하고. // position_offset을 추가한다. Vector3 position = BlockRoot.calcBlockPosition(this.i_pos) + this.position_offset; // 실제 위치를 새로운 위치로 변경한다. this.transform.position = position; this.setColor(this.color); if (this.vanish_timer >= 0.0f) { // 현재 레벨의 연소시간으로 설정. float vanish_time = this.block_root.level_control.getVanishTime(); // 현재 색과 흰색의 중간 색. Color color0 = Color.Lerp(this.GetComponent <Renderer>().material.color, Color.white, 0.5f); // 현재 색과 검은색의 중간 색. Color color1 = Color.Lerp(this.GetComponent <Renderer>().material.color, Color.black, 0.5f); // 불붙는 연출 시간이 절반을 지났다면. if (this.vanish_timer < Block.VANISH_TIME / 2.0f) { // 투명도(a)를 설정. color0.a = this.vanish_timer / (Block.VANISH_TIME / 2.0f); color1.a = color0.a; // 반투명 머티리얼을 적용. this.GetComponent <Renderer>().material = this.transparent_material; } // vanish_timer가 줄어들수록 1에 가까워진다. float rate = 1.0f - this.vanish_timer / Block.VANISH_TIME; // 서서히 색을 바꾼다. this.GetComponent <Renderer>().material.color = Color.Lerp(color0, color1, rate); } countBlockDestroy(); }