private Vector2 GetForceOnLeftOrRight(BallBase ball, CollisionSide colSide) { Vector2 forceVector = StrikerCollisionForceManager.GetCollisionEndVelocity(CollisionType, colSide, isMovingOrMovedUp, isForceModeOn); float endSpeed = PhysicsConstants.BallSpeedAfterStrikerIdleHit; return((ball.LastFrameVelocity.normalized + forceVector).normalized * endSpeed); }
private void Update() { bool isKeyDown = GamePad.GetButtonDown(GamePad.Button.Y, GamePad.Index.Any) || Input.GetKeyDown(KeyCode.Space); if (isKeyDown) { BallBase ball = BallPool.TryTakeBallToPlay(); if (ball != null) { ball.enabled = false; Vector2 pos = PhysicsTools.GetRandomPositionBetweenVectors(BallSpawnPositionMin.position, BallSpawnPositionMax.position); ball.SetGravityState(false); ball.ResetTrailEmitter(); ball.transform.position = pos; ball.Rigidbody.velocity = Vector2.zero; ball.Rigidbody.AddForce(Vector2.down * PhysicsConstants.BallSpeedAtStart, ForceMode2D.Impulse); BallsInPlay.Add(ball); ball.ResetLastFrameVelocityAndPosition(); ball.enabled = true; } CallOnGameStateChanged(); GameStarted = true; EnemyController.Instance.TryInitEnemySpawning(); } if (GameStarted) { GameTime += Time.deltaTime; } }
private Vector2 GetForceOnBottomSide(BallBase ball) { Vector2 forceVector = StrikerCollisionForceManager.GetCollisionEndVelocity(CollisionType, CollisionSide.Top, isMovingOrMovedUp, isForceModeOn); float endSpeed = isForceModeOn ? PhysicsConstants.BallSpeedAfterStrikerForceHit : PhysicsConstants.BallSpeedAfterStrikerIdleHit; return((ball.LastFrameVelocity.normalized + forceVector).normalized * endSpeed); }
public void RemoveBallFromPlay(BallBase ball) { if (BallsInPlay.Contains(ball)) { BallsInPlay.Remove(ball); } Destroy(ball.gameObject, 1f); }
private BallBase SpawnBallOnRandomPoint() { Vector3 pos = new Vector3(BallTestSpawnPosition.position.x, BallTestSpawnPosition.position.y, BallTestSpawnPosition.position.z + UnityEngine.Random.Range(0, 2f)); BallBase ball = Instantiate(BallToSpawn, pos, Quaternion.identity, null); ball.gameObject.name = "Ball " + ballCounter; ballCounter++; return(ball); }
public BallBase TryTakeBallToPlay() { if (ballsInPool.Count > 0) { int randomIndex = UnityEngine.Random.Range(0, ballsInPool.Count); BallBase randomBall = ballsInPool[randomIndex]; ballsInPool.RemoveAt(randomIndex); return(randomBall); } return(null); }
private void AddBallToPool() { Vector3 randomPos = PhysicsTools.GetRandomPositionBetweenVectors(BallSpawnPlaceMin.position, BallSpawnPlaceMax.position); BallBase ball = Instantiate(BallPrefab, randomPos, Quaternion.identity); ball.SetGravityState(true); ballsInPool.Add(ball); ball.gameObject.name = "Ball " + ballCounter; ballCounter++; GameController.Instance.CallOnGameStateChanged(); }
public BallBase Copy() { BallBase c = new BallBase(); c.Initialize(this.BType); c.ObjNo = this.ObjNo; c.DisplayName = this.DisplayName; c.ThrowDexterity = this.ThrowDexterity; if (CommonFunction.IsNull(this.Options) == false) { c.Options = this.Options; } return(c); }
//private void OnCollisionEnter2D(Collision2D collision) //{ // if (collision.collider.CompareTag(GameTags.Ball)) // { // BallBase ball = collision.collider.GetComponent<BallBase>(); // if(ball != null) // { // ContactPoint2D contactPoint = collision.GetContact(0); // CollisionSide colSide = CollisionSideDetect.GetCollisionSide(ball.LastFrameCenterPoint, contactPoint.point); // ball.SetOppositeVelocity(colSide, PhysicsConstants.BallSpeedAfterEnemyHit); // if (ball.LastFrameVelocity.magnitude < PhysicsConstants.BallSpeedPowerShotThreshold) // { // currentHealth--; // } // else // { // currentHealth -= 3; // } // SetColor(); // } // if(currentHealth <= 0) // { // associatedSpawner.TryToDestroy(this); // } // } //} public void OnCollisionWithBall(BallBase ball) { if (ball.LastFrameVelocity.magnitude < PhysicsConstants.BallSpeedPowerShotThreshold) { currentHealth--; } else { currentHealth -= 3; } if (currentHealth <= 0) { associatedSpawner.TryToDestroy(this); } }
/// <summary> /// Updates the score. Points are calculated here before it's added to player's score /// </summary> public override void UpdatePoint(int score = 0, BallBase baseObj = null) { if (!_stopScoreUpdate) { base.UpdatePoint(score, baseObj); if (score < 0) { _cueBallSunk = true; _stopScoreUpdate = true; //Stop subsequent point being added into the score } else if (score > 0) { _colourBallSunk = true; } } }
public Vector2 GetForceOnBallHit(BallBase ball, CollisionSide colSide) { switch (colSide) { case CollisionSide.Top: return(GetForceOnTopSide(ball)); case CollisionSide.Bottom: return(GetForceOnBottomSide(ball)); case CollisionSide.Left: case CollisionSide.Right: return(GetForceOnLeftOrRight(ball, colSide)); default: return(Vector2.one); } }
private void OnCollisionWithBall(BallBase ball, RaycastHit2D rayHit, CollisionSide colSide, Vector2 direction, out float distanceForRay) { Vector2 lastFramePos = LastFrameCenterPoint; Vector2 velocity = LastFrameVelocity; Vector2 actualPos = currentPosition; Vector2 centroidPoint = rayHit.centroid; Vector2 contactPoint = rayHit.point; float distanceToCollision = (lastFramePos - centroidPoint).magnitude; float totalDistance = (actualPos - lastFramePos).magnitude; float distanceAfterHit = totalDistance - distanceToCollision; distanceForRay = distanceAfterHit; Vector2 distanceToAdd = distanceAfterHit * direction.normalized; ball.AddToPosition(distanceToAdd); ball.RaycastAndSkipThisFrameCollision(); }
public CollisionSide GetCollisionSideWithBall(BallBase ball, Vector2 ballLastFramePosition) { CollisionSide colSide = CollisionSide.Top; Vector2 centerPoint = Collider.bounds.center; Vector2 targetPoint = ballLastFramePosition; float objectCenterToTargetLength = (targetPoint - centerPoint).magnitude; float bottomToTargetLength = (targetPoint - LastFrameBottomPoint).magnitude; if (objectCenterToTargetLength < bottomToTargetLength) { colSide = CollisionSide.Bottom; } else { colSide = CollisionSide.Top; } return(colSide); }
public static BallBase GetItem(long objNo) { TableBallData data = Array.Find(Table, i => i.ObjNo == objNo); BallBase item = new BallBase(); item.Initialize(data.BallType); item.RestCount = (sbyte)CommonFunction.ConvergenceRandom(data.StartGap, data.Startprob, data.Con, data.MaxGap); item.ObjNo = data.ObjNo; if (GameStateInformation.IsEnglish == false) { item.DisplayName = data.DisplayName; item.Description = data.Description; } else { item.DisplayName = data.DisplayNameEn; item.Description = data.DescriptionEn; } item.ThrowDexterity = data.ThrowDexterity; return(item); }
public virtual void UpdatePoint(int score = 0, BallBase baseObj = null) { UpdatePlayerScore(score); }
/// <summary> /// 投げる効果(誰かに当たった時) /// </summary> private bool ThrowActionEffect(ManageDungeon dun, PlayerCharacter player, BaseCharacter target) { switch (BType) { case BallType.Fire: //サウンドを鳴らす SoundInformation.Sound.Play(SoundInformation.SoundType.Bomb); int damage = FireBallFixDamage + Mathf.FloorToInt(player.BaseAttack * 2); AttackState atState = target.AddDamage(damage); //ボールエフェクト EffectFireBallLanding.CreateObject(target).Play(); //ダメージエフェクト EffectDamage d = EffectDamage.CreateObject(target); d.SetText(damage.ToString(), AttackState.Hit); d.Play(); //ヒットメッセージ DisplayInformation.Info.AddMessage( target.GetMessageAttackHit(damage)); //対象が死亡したら if (atState == AttackState.Death) { if (target.Type == ObjectType.Player) { ScoreInformation.Info.CauseDeath = string.Format(CommonConst.DeathMessage.Item, this.DisplayNameNormal); ScoreInformation.Info.CauseDeathType = DeathCouseType.Item; } DisplayInformation.Info.AddMessage( target.GetMessageDeath(target.HaveExperience)); player.Death(target, player.AttackInfo); target.DeathAction(dun); } break; case BallType.Gyro: SoundInformation.Sound.Play(SoundInformation.SoundType.BucketFall); //ターゲットが吹き飛ぶ先のポイントを取得 bool isWall; MapPoint point = dun.GetBlow(target.CurrentPoint, Direction, out isWall); //対象のポイントが取得できなければ if (CommonFunction.IsNull(point) == true) { } //対象ポイントが取得できればそこに移動 else { if (typeof(BaseEnemyCharacter) == target.GetType()) { ((BaseEnemyCharacter)target).MoveState = EnemySearchState.FightPlayer; } DisplayInformation.Info.AddMessage( string.Format(CommonConst.Message.BlowCharacter, target.DisplayNameInMessage)); target.BlowDirection = Direction; target.BlowPoint = point; target.MoveSpeed = CommonConst.SystemValue.MoveSpeedDash; dun.MoveCharacter(point, target); //対象に衝突ダメージ if (isWall == true) { target.BlowAfterDamage = GyroFixDamage; } //吹っ飛び先に誰かがいた場合 MapPoint vector = CommonFunction.CharacterDirectionVector[Direction]; MapPoint next = MapPoint.Get(point.X + vector.X, point.Y + vector.Y); BaseCharacter second = dun.CharacterMap.Get(point.X, point.Y); if (CommonFunction.IsNull(second) == false) { second.BlowAfterDamage = GyroFixDamage; second.BlowPoint = second.CurrentPoint; } } break; case BallType.Change: //サウンドを鳴らす SoundInformation.Sound.Play(SoundInformation.SoundType.Smoke); if (typeof(BaseEnemyCharacter) == target.GetType()) { ((BaseEnemyCharacter)target).MoveState = EnemySearchState.FightPlayer; } //ターゲットとプレイヤーの場所を交換 EffectSmoke.CreateObject(target).Play(); EffectSmoke.CreateObject(player).Play(); MapPoint tarp = target.CurrentPoint; target.SetPosition(player.CurrentPoint.X, player.CurrentPoint.Y); player.SetPosition(tarp.X, tarp.Y); DisplayInformation.Info.AddMessage( string.Format(CommonConst.Message.ChangePoint, target.DisplayNameInMessage)); break; case BallType.Pickoff: //サウンドを鳴らす SoundInformation.Sound.Play(SoundInformation.SoundType.Smoke); //対象に混乱を付与 int result = target.AddStateAbnormal((int)StateAbnormal.Confusion); //対象が混乱になったらメッセージを表示 if (result != 0) { EffectSmoke.CreateObject(target).Play(); DisplayInformation.Info.AddMessage( CommonFunction.GetAbnormalMessage(StateAbnormal.Confusion, target)); } break; case BallType.Bean: //サウンドを鳴らす SoundInformation.Sound.Play(SoundInformation.SoundType.Smoke); //対象に麻痺を付与 int bresult = target.AddStateAbnormal((int)StateAbnormal.Palalysis); //対象が麻痺になったらメッセージを表示 if (bresult != 0) { EffectSmoke.CreateObject(target).Play(); DisplayInformation.Info.AddMessage( CommonFunction.GetAbnormalMessage(StateAbnormal.Palalysis, target)); } break; case BallType.Decoy: //サウンドを鳴らす SoundInformation.Sound.Play(SoundInformation.SoundType.Smoke); //対象にデコイを付与 int dresult = target.AddStateAbnormal((int)StateAbnormal.Decoy); //対象がデコイになったらメッセージを表示 if (dresult != 0) { EffectSmoke.CreateObject(target).Play(); DisplayInformation.Info.AddMessage( CommonFunction.GetAbnormalMessage(StateAbnormal.Decoy, target)); } break; case BallType.Slow: //サウンドを鳴らす SoundInformation.Sound.Play(SoundInformation.SoundType.Smoke); //対象にスローを付与 int sresult = target.AddStateAbnormal((int)StateAbnormal.Slow); //対象がスローになったらメッセージを表示 if (sresult != 0) { EffectSmoke.CreateObject(target).Play(); DisplayInformation.Info.AddMessage( CommonFunction.GetAbnormalMessage(StateAbnormal.Slow, target)); } break; //ナックル case BallType.Knuckle: List <BallType> blist = new List <BallType>(); foreach (BallType val in Enum.GetValues(typeof(BallType))) { blist.Add(val); } blist.Remove(BallType.Knuckle); blist.Remove(BallType.Handmaid); //ナックル以外の効果をランダムで取得 BallType temp = blist[UnityEngine.Random.Range(0, blist.Count)]; BallBase b = new BallBase(); b.CurrentPoint = CurrentPoint; b.Direction = Direction; b.BType = temp; //効果を発動 b.ThrowActionEffect(dun, player, target); break; case BallType.Trap: TrapBreaker(dun, player); break; case BallType.Handmaid: //ヒットエフェクト EffectFireBallLanding.CreateObject(target).Play(); //サウンドを鳴らす SoundInformation.Sound.Play(SoundInformation.SoundType.AttackHit); //範囲拡大がついているとき int plus; float cf; int dist = 0; if (CommonFunction.HasOptionType(this.Options, OptionType.Wildfire, out plus, out cf) == true) { dist = plus; } dun.SetUpCharacterMap(); List <BaseCharacter> targets = dun.GetNearCharacters(target.CurrentPoint, dist, true); foreach (BaseCharacter t in targets) { //int damage2 = FireBallFixDamage + Mathf.FloorToInt(player.BaseAttack * 2); int damage2 = Mathf.FloorToInt((15 + player.BaseAttack) / (target.CurrentPoint.DistanceAbs(t.CurrentPoint) + 1)); //効果増幅があったら if (CommonFunction.HasOptionType(this.Options, OptionType.EffectUp, out plus, out cf) == true) { damage2 = damage2 + plus * (int)cf; } //効果縮小があったら if (CommonFunction.HasOptionType(this.Options, OptionType.EffectDown, out plus, out cf) == true) { damage2 = damage2 - plus * (int)cf; } //ダメージ増減30% float rand = 0.3f; if (CommonFunction.HasOptionType(this.Options, OptionType.EffectStabile, out plus, out cf) == true) { rand -= cf * plus; } else if (CommonFunction.HasOptionType(this.Options, OptionType.EffectNotStabile, out plus, out cf) == true) { rand += cf * plus; } damage2 += Mathf.CeilToInt(UnityEngine.Random.Range(-rand * damage2, rand * damage2)); //通常ダメージの場合 if (CommonFunction.HasOptionType(this.Options, OptionType.ReverceDamage) == false) { AttackState atState2 = t.AddDamage(damage2); //ダメージエフェクト EffectDamage d2 = EffectDamage.CreateObject(t); d2.SetText(damage2.ToString(), AttackState.Hit); d2.Play(); //ヒットメッセージ DisplayInformation.Info.AddMessage( t.GetMessageAttackHit(damage2)); //対象が死亡したら if (atState2 == AttackState.Death) { DisplayInformation.Info.AddMessage( t.GetMessageDeath(t.HaveExperience)); if (t.Type == ObjectType.Player) { ScoreInformation.Info.CauseDeath = string.Format(CommonConst.DeathMessage.Item, this.DisplayNameNormal); ScoreInformation.Info.CauseDeathType = DeathCouseType.Item; t.Death(); } else { if (IsExp == true) { player.Death(t, player.AttackInfo); } else { t.Death(); } } t.DeathAction(dun); } } //基本効果反転 else { t.RecoverHp(damage2); //ヒットエフェクト EffetHitShockWave.CreateObject(t).Play(); //ダメージエフェクト EffectDamage d2 = EffectDamage.CreateObject(t); d2.SetText(damage2.ToString(), AttackState.Heal); d2.Play(); //ヒットメッセージ DisplayInformation.Info.AddMessage( string.Format(CommonConst.Message.RecoverHp, t.DisplayNameInMessage)); } } //状態異常の付与 EffectAbnormal(targets); //火柱があれば火柱を立てる if (CommonFunction.HasOptionType(this.Options, OptionType.CatchingFire) == true) { dun.SetUpTrapMap(); if (CommonFunction.IsNull(dun.TrapMap.Get(CurrentPoint)) == true) { BaseTrap trap = TableTrap.GetTrap(CommonConst.ObjNo.Ember); trap.Options = CommonFunction.CloneOptions(this.Options); trap.IsVisible = true; trap.SetThisDisplayTrap(CurrentPoint.X, CurrentPoint.Y); dun.AddNewTrap(trap); DisplayInformation.Info.AddMessage( CommonConst.Message.TrapEmber); } } break; case BallType.Fumble: //対象のレベルが2以上ならレベルを下げる if (target.Level > 1) { if (target.Type == ObjectType.Enemy) { BaseEnemyCharacter enemy = ((BaseEnemyCharacter)target); enemy.Level--; TableEnemy.SetLevel(enemy, enemy.Level, DisplayInformation.Info.Floor, DungeonInformation.Info.EnemyHpProb, DungeonInformation.Info.EnemyAtkProb, DungeonInformation.Info.EnemyExpProb, DungeonInformation.Info.StartProbHp, DungeonInformation.Info.StartProbAtk, DungeonInformation.Info.StartProbExp); DisplayInformation.Info.AddMessage( string.Format(CommonConst.Message.LevelDownPlayer, enemy.DisplayNameInMessage)); EffectBadSmoke.CreateObject(enemy).Play(); } } break; case BallType.Winning: if (target.Type == ObjectType.Enemy) { BaseEnemyCharacter enemy = ((BaseEnemyCharacter)target); enemy.Level++; TableEnemy.SetLevel(enemy, enemy.Level, DisplayInformation.Info.Floor, DungeonInformation.Info.EnemyHpProb, DungeonInformation.Info.EnemyAtkProb, DungeonInformation.Info.EnemyExpProb, DungeonInformation.Info.StartProbHp, DungeonInformation.Info.StartProbAtk, DungeonInformation.Info.StartProbExp); DisplayInformation.Info.AddMessage( string.Format(CommonConst.Message.LevelUpPlayer, enemy.DisplayNameInMessage)); EffectFlareCore.CreateObject(enemy).Play(); } break; case BallType.Four: if (target.Type == ObjectType.Enemy) { BaseEnemyCharacter enemy = ((BaseEnemyCharacter)target); if (enemy.IsFourBallCount() == true) { int dam = Mathf.CeilToInt(enemy.MaxHp); AttackState atstate = target.AddDamage(dam); //ボールエフェクト EffetHitShockWave.CreateObject(enemy).Play(); //ダメージエフェクト EffectDamage dt = EffectDamage.CreateObject(target); dt.SetText(dam.ToString(), AttackState.Hit); dt.Play(); //ヒットメッセージ DisplayInformation.Info.AddMessage( target.GetMessageAttackHit(dam)); SoundInformation.Sound.Play(SoundInformation.SoundType.AttackHit); //対象が死亡したら if (atstate == AttackState.Death) { if (target.Type == ObjectType.Player) { ScoreInformation.Info.CauseDeath = string.Format(CommonConst.DeathMessage.Item, this.DisplayNameNormal); ScoreInformation.Info.CauseDeathType = DeathCouseType.Item; } DisplayInformation.Info.AddMessage( target.GetMessageDeath(target.HaveExperience)); player.Death(target, player.AttackInfo); target.DeathAction(dun); } } else { SoundInformation.Sound.Play(SoundInformation.SoundType.AttackHit); //ボールエフェクト EffetHitShockWave.CreateObject(enemy).Play(); } } break; case BallType.Emery: if (target.Type == ObjectType.Enemy) { BaseEnemyCharacter enemy = ((BaseEnemyCharacter)target); if (enemy.IsBoss() == false) { GameStateInformation.Info.EmeryTarget = target.ObjNo; DisplayInformation.Info.AddMessage( string.Format(CommonConst.Message.EmeryCharacter, target.DisplayNameInMessage)); List <BaseCharacter> emeryies = dun.Characters.FindAll(i => i.ObjNo == target.ObjNo); SoundInformation.Sound.Play(SoundInformation.SoundType.Summon); foreach (BaseCharacter c in emeryies) { EffectSmoke.CreateObject(c, false).Play(); dun.RemoveCharacter(c); ManageDungeon.KillObjectNow(c); } } } break; } Options = null; return(true); }
private void OnCollision(BallBase ball, RaycastHit2D rayHit, CollisionSide colSide, CollisionType colType, float totalDistance, float endSpeed, int safe, ICollider collidingObject, out float distanceAfterHit) { if (totalDistance <= 0) { rayHits = new RaycastHit2D[0]; Debug.LogWarning("TOTAL DISTNANCE <= 0!"); distanceAfterHit = 0; return; } Vector2 lastFramePos = ball.LastFrameCenterPoint; Vector2 velocity = LastFrameVelocity; Vector2 actualPos = currentCenterPoint; Vector2 centroidPoint = rayHit.centroid; float colRadius = Collider.radius / 2; float distanceToCollision = rayHit.distance; distanceAfterHit = totalDistance - distanceToCollision; // Debug.LogFormat("[{3}] distanceToCollision: {0}, total distance: {1} distanceAfterHit: {2}", distanceToCollision, totalDistance, distanceAfterHit, safe); Debug.DrawLine(centroidPoint, rayHit.point, Color.blue, 2); Debug.DrawLine(actualPos, lastFramePos, safe == 0 ? Color.black : Color.yellow, 2); Debug.DrawLine(actualPos, centroidPoint, Color.green, 2); Vector2 newPos; bool overlapping = distanceToCollision == 0; Debug.LogFormat("Collision. side: {0} type: {1} overlap: {2}, last framePos: {3} actualPos: {4}", colSide, colType, overlapping, lastFramePos, actualPos); if (overlapping) { Debug.LogWarningFormat("OVERLAPPING! To collision: {0} total distance: {1}", distanceToCollision, totalDistance); overlapping = true; newPos = GetNewPositionWhenOverlaping(colType, colSide, collidingObject, rayHit, actualPos, colRadius); distanceAfterHit = totalDistance - (newPos - lastFramePos).magnitude; Debug.Log("new distance after hit: " + distanceAfterHit); if (distanceAfterHit <= -100) { Debug.Log("FAIL"); } // newPos = GetNewPositionBasedOnCollisionType(colType, colSide, newPos, velocity, distanceAfterHit); // Debug.LogFormat("Pos changed: {0} to {1}", lastFramePos, newPos); } else { newPos = GetNewPositionBasedOnCollisionType(colType, colSide, centroidPoint, velocity, collidingObject, distanceAfterHit); Vector2 endVel = SetVelocityBasedOnCollisionType(colType, colSide, collidingObject, endSpeed, LastFrameVelocity); LastFrameVelocity = endVel; Debug.Log("change velocity to " + (endVel.y < 0 ? "DOWN" : "UP")); } ball.transform.position = newPos; Debug.DrawLine(centroidPoint, newPos, safe == 0 ? Color.red : Color.grey, 2); currentCenterPoint = newPos; if (overlapping) { rayHit.centroid = newPos; rayHit.distance = distToMoveOnOverlap; //rayHits = new RaycastHit2D[1] { rayHit }; //rayHits = Physics2D.CircleCastAll(newPos, colRadius, newPos - actualPos, distanceAfterHit, ColliderLayerMask); OnCollision(ball, rayHit, colSide, colType, distanceAfterHit, endSpeed, safe, collidingObject, out distanceAfterHit); LastFrameCenterPoint = newPos; } else { rayHits = Physics2D.CircleCastAll(centroidPoint, colRadius, newPos - centroidPoint, distanceAfterHit, ColliderLayerMask); LastFrameCenterPoint = rayHit.centroid; rayHits = rayHits.Remove(rayHit); } // Debug.LogFormat("col Y: {0}, end Y: {1}", centroidPoint.y, newPos.y); // Debug.LogFormat("start vel: {0} end vel: {1}", velocity.normalized, endVel.normalized); }