private void Update() { if (MVMain.Core.haltGame) { return; } deltaTime = Time.deltaTime; if (!stayAlive) { lifeTime -= Time.deltaTime; if (MVUtility.Leq0(lifeTime)) { Destroy(gameObject); } } if (_source == null) { Destroy(gameObject); } if (!localHalt) { AI(); } }
/// <summary> /// Tick for Player, override BuffTick for buff effects /// </summary> /// <param name="deltaTime">time since last tick</param> /// <returns>continuity and buff alive status</returns> public Tuple <bool, bool> Tick(float deltaTime) { timeleft -= deltaTime; bool alive = (!MVUtility.Leq0(timeleft)); return(new Tuple <bool, bool>(BuffTick(deltaTime), alive)); }
/// <summary> /// Control player weapon using behaviour /// </summary> private void PlayerShoot() { if (Input.GetButtonDown("Fire1") && !freezeInput && MVUtility.Geq(weaponPower, ActiveWeapon.WeaponUsage)) { weaponRechargeDelay = weaponRechargeDelayMax; weaponRechargeDelayStart = false; weaponCanRecharge = false; ActiveWeapon.StartUse(); weaponAttackMovingPenalty = weaponAttackMovingPenaltyMax; // animator.SetTrigger("Attack"); // animator.SetBool("HoldFire", true); } else if (Input.GetButtonUp("Fire1") || freezeInput) { weaponRechargeDelayStart = true; ActiveWeapon.EndUse(); // animator.SetBool("HoldFire", false); } else if (Input.GetButton("Fire1") && !freezeInput) { if (ActiveWeapon.chargeUse && MVUtility.Geq(weaponPower, ActiveWeapon.WeaponUsage) && ActiveWeapon.fired) { weaponRechargeDelay = weaponRechargeDelayMax; weaponRechargeDelayStart = false; weaponCanRecharge = false; weaponAttackMovingPenalty = weaponAttackMovingPenaltyMax; } else { weaponRechargeDelayStart = true; } ActiveWeapon.HoldUse(); } }
/// <summary> /// Method for giving enemy buff /// </summary> /// <param name="name">name of buff</param> public void GetBuff(string name) { if (!buffs.ContainsKey(name)) { BaseEnemyBuff newBuff = MVUtility.CreateEnemyBuff(name, this); buffs.Add(newBuff.name, newBuff); } }
/// <summary> /// load data from persistentPath /// </summary> /// <returns>true if save file exist</returns> private bool LoadAllData() { data = new GameScriptData(); bool loadExist = false; string savePath = Path.Combine(Application.persistentDataPath, "Save"); if (Directory.Exists(savePath)) { string saveFile = Path.Combine(savePath, "main.json"); if (File.Exists(saveFile)) { using (StreamReader dat = new StreamReader(saveFile)) { string datJSON = dat.ReadToEnd(); data = JsonUtility.FromJson <GameScriptData>(datJSON); loadExist = true; } } } if (!loadExist) { return(false); } Vector2Int mapSize = MVMain.World.mapSize; savedMap = new ChunkData[mapSize.x, mapSize.y]; for (int i = 0; i < mapSize.x; i++) { for (int j = 0; j < mapSize.y; j++) { savedMap[i, j] = data.savedMapRow[i].rowData[j]; } } LoadMinimapData(); score = dead ? 0 : data.score; lastRoom = data.lastRoom; lastSpawn = data.lastSpawn; lastMaxHealth = data.lastMaxHealth; playerPlayer.weapons = data.weapons.Select(x => MVUtility.CreateWeapon(x.name, x.level)).ToList(); playerPlayer.maxHealth = lastMaxHealth; playerPlayer.health = lastMaxHealth; MVMain.Room.activeRoomName = lastRoom; MVMain.Room.spawnFrom = lastSpawn; MVMain.Room.LoadRoomData(); if (room != null) { Destroy(room); } LoadRoom(TeleporterData.TeleporterType.Direct); return(true); }
/// <summary> /// Spawn new projectile /// </summary> /// <param name="worldPos">position in 2D space</param> /// <param name="speed">speed</param> /// <param name="direction">direction</param> /// <param name="friendly">friendly to player?</param> /// <param name="source">source of projectile</param> /// <param name="damage">damage</param> /// <param name="projectileName">name of the projectile prefab</param> /// <param name="behaviourName">name of the projectile AI class</param> /// <param name="color">projectile color</param> /// <param name="sound">projectile sound when spawning</param> /// <returns>GameObject of spawned projectile</returns> public GameObject Spawn(Vector2 worldPos, float speed, Vector2 direction, bool friendly, GameObject source, int damage = 5, string projectileName = "Bullet", string behaviourName = "DefaultBullet", Color?color = null, string sound = null) { Type type; Color targetColor; GameObject prefab = Resources.Load <GameObject>(MVMain.settings.projectilePrefabPath + projectileName); try { type = Type.GetType(behaviourName); } catch { //type = typeof(DefaultBullet); return(null); } if (color == null) { if (friendly) { targetColor = Color.white; } else { targetColor = Color.red; } } else { targetColor = (Color)color; } direction.Normalize(); projectileCount++; GameObject result = GameObject.Instantiate <GameObject>(prefab, worldPos, Quaternion.identity, MVMain.Core.room.transform); result.GetComponent <SpriteRenderer>().color = targetColor; result.AddComponent(type); result.transform.rotation = MVUtility.TopDownRotationFromDirection(direction); BaseProjectile projectile = result.GetComponent(type) as BaseProjectile; projectile.Source = source; projectile.Friendly = friendly; projectile.defaultSpeed = speed; projectile.defaultDirection = direction; projectile.Speed = speed; projectile.Direction = direction; projectile.damage = damage; if (sound != null) { MVMain.Sound.Play(sound); } return(result); }
private bool CheckNonSquare() { bool found = false; for (int i = 0; i < toggled.GetLength(0) && !found; i++) { for (int j = 0; j < toggled.GetLength(1) && !found; j++) { if (toggled[i, j]) { minIdx = new Vector2Int(j - 2, -(i - 2)); found = true; } } } found = false; for (int i = toggled.GetLength(0) - 1; i >= 0 && !found; i--) { for (int j = toggled.GetLength(1) - 1; j >= 0 && !found; j--) { if (toggled[i, j]) { maxIdx = new Vector2Int(j - 2, -(i - 2)); found = true; } } } Vector2Int nowIdx; for (int i = 0; i < toggled.GetLength(0); i++) { for (int j = 0; j < toggled.GetLength(1); j++) { nowIdx = new Vector2Int(j - 2, -(i - 2)); if (toggled[i, j] ^ MVUtility.BetweenVector2Int(nowIdx, minIdx, maxIdx)) { return(true); } } } return(false); }
/// <summary> /// Method for giving player damage /// </summary> /// <param name="direction">direction of attack</param> /// <param name="damage">damage</param> /// <param name="ignoreInvincible">is the attack ignoring the invincible status?</param> /// <param name="knockbackMultiplier">knockback power</param> /// <param name="playSound">should it playing hurt sound?</param> /// <param name="drawNumber">should it draw damage number?(currently unused)</param> public void GetHit(Vector2 direction, int damage, bool ignoreInvincible = false, float knockbackMultiplier = 1f, bool playSound = true, bool drawNumber = false) { if (godMode) { return; } if (!invincible || ignoreInvincible) { if (playSound) { MVMain.Sound.Play("hit1", 1.5f, 1); } int damageF = Mathf.RoundToInt((float)damage * MVMain.Difficulty.difficulty); if (damage > 0) { damageF = Mathf.Max(1, damageF); } health -= damageF; if (health < 0) { health = 0; } if (!ignoreInvincible) { invincible = true; invincibleTime = invincibleTimeMax; blinking = true; blinkRate = blinkRateMax; } if (drawNumber) { //GameUtility.SpawnPopupText("-" + damageF.ToString(), rb2d.position + Random.insideUnitCircle * 0.25f, Color.red); } if (!MVUtility.Leq0(knockbackMultiplier)) { Knockback(direction, knockbackMultiplier); } } }
/// <summary> /// Scan all rooms and create new world data /// </summary> private void Scan() { foreach (var room in MVMain.Room.rooms) { string debugString = room.Key + " : "; foreach (var receiver in room.Value.receivers) { debugString += receiver.name + " "; } Debug.Log(debugString); } roomQueue = new Queue <Tuple <string, Vector2Int> >(); roomQueueList = new HashSet <string>(); string startMap = MVMain.Room.activeRoomName; roomQueue.Enqueue(new Tuple <string, Vector2Int>(startMap, startScan)); roomQueueList.Add(startMap); while (roomQueue.Count > 0) { var now = roomQueue.Dequeue(); roomPos.Add(now.Item1, now.Item2); if (MVMain.Room.rooms.ContainsKey(now.Item1)) { RoomData roomNow = MVMain.Room.rooms[now.Item1]; for (int i = 0; i < roomNow.chunkSize.x; i++) { for (int j = 0; j < roomNow.chunkSize.y; j++) { ChunkData nowChunk = map[now.Item2.x + i, now.Item2.y + j]; nowChunk.roomName = now.Item1; nowChunk.localChunkPos = new Vector2Int(i, j); //nowChunk.roomColor = roomNow.mapColor; nowChunk.roomColor = Resources.Load <StageData>(MVMain.settings.stageDataPath + roomNow.stage).color; bool up = false; bool down = false; bool left = false; bool right = false; //have up sibling if (i > 0) { nowChunk.SetBig(Direction.Up); up = true; } //have down sibling if (i < roomNow.chunkSize.x - 1) { nowChunk.SetBig(Direction.Down); down = true; } //have left sibling if (j > 0) { nowChunk.SetBig(Direction.Left); left = true; } //have right sibling if (j < roomNow.chunkSize.y - 1) { nowChunk.SetBig(Direction.Right); right = true; } //topleft if (up && left) { nowChunk.diagonal[3] = true; } //topright if (up && right) { nowChunk.diagonal[2] = true; } //bottomright if (down && right) { nowChunk.diagonal[1] = true; } //topleft if (down && left) { nowChunk.diagonal[0] = true; } } } for (int i = 0; i < roomNow.teleporters.Count; i++) { TeleporterData connector = roomNow.teleporters[i]; ChunkData nowChunk = map[now.Item2.x + connector.chunkPos.x, now.Item2.y + connector.chunkPos.y]; nowChunk.SetSmall(connector.teleporterDirection); if (!roomQueueList.Contains(connector.targetRoom)) { Vector2Int nextPos = now.Item2 + connector.chunkPos + MVUtility.DirectionToVector2Int(connector.teleporterDirection); if (MVMain.Room.rooms.ContainsKey(connector.targetRoom)) { RoomData nextRoom = MVMain.Room.rooms[connector.targetRoom]; ReceiverData nextReceiver = nextRoom.receivers.FirstOrDefault(x => x.name == connector.targetTeleporter); nextPos -= nextReceiver.chunkPos; roomQueue.Enqueue(new Tuple <string, Vector2Int>(nextRoom.name, nextPos)); roomQueueList.Add(nextRoom.name); } } } } } }
private void Update() { if (MVMain.Core.haltGame) { // animator.speed = 0; return; } else { // animator.speed = 1; } VelocityFromEffects = Vector2.zero; deltaTime = Time.deltaTime; if (health <= 0) { health = 0; Dead(); } freezeInput = false; if (weapons.Count > 0) { foreach (BaseWeapon wep in weapons) { wep.Update(deltaTime); } } #region buff deadBuff = new List <string>(); foreach (var item in buffs) { var resBuff = item.Value.Tick(deltaTime); if (!resBuff.Item1) { freezeInput = true; } if (!resBuff.Item2) { deadBuff.Add(item.Key); } } foreach (var item in deadBuff) { buffs.Remove(item); } #endregion if (!MVUtility.Leq0(weaponAttackMovingPenalty)) { weaponAttackMovingPenalty -= deltaTime; } if (invincibleTime > 0f) { invincibleTime -= deltaTime; } else { invincibleTime = 0f; if (invincible) { spriteRenderer.color = defaultColor; } invincible = false; blinking = false; } if (velocity.y <= 0f) { inJumpBack = false; jumpBack = false; } else if (jumpBack) { inJumpBack = true; } PlayerController(); activeWeaponIndex = (weapons.Count > 0) ? activeWeaponIndex % weapons.Count : 0; /*if (!GameUtility.Geq(weaponPower, (weapons.Count > 0) ? ActiveWeapon.WeaponUsage : 50f)) { * weaponCanRecharge = true; * } * else*/ if (Mathf.Approximately(weaponPower, weaponPowerMax)) { weaponCanRecharge = false; } if (!weaponCanRecharge && weaponRechargeDelayStart) { weaponRechargeDelay -= deltaTime; if (MVUtility.Leq0(weaponRechargeDelay)) { weaponRechargeDelay = weaponRechargeDelayMax; weaponRechargeDelayStart = false; weaponCanRecharge = true; } } else if (weaponCanRecharge) { weaponRechargeDelay = weaponRechargeDelayMax; weaponRechargeDelayStart = false; weaponPower += weaponRechargeSpeed * deltaTime; } weaponPower = Mathf.Clamp(weaponPower, 0f, weaponPowerMax); if (weapons.Count > 0) { PlayerShoot(); } if (blinking) { if (blinkRate > blinkRateMax / 2f) { spriteRenderer.color = new Color(1, 1, 1, .5f); } else { spriteRenderer.color = defaultColor; } blinkRate -= deltaTime; if (blinkRate <= 0) { blinkRate = blinkRateMax; } } velocity += VelocityFromEffects; }
/// <summary> /// Control of player /// </summary> private void PlayerController() { float xMove = 0f; if (!inJumpBack || grounded) { if (MVUtility.Leq0(weaponAttackMovingPenalty)) { xMove = freezeInput? 0 : Input.GetAxis("Horizontal"); } else if (freezeInput) { xMove = 0; } } else { xMove = knockBackXSpeed * knockBackResistance * knockBackDirection; } if (Input.GetButtonDown("Jump") && grounded && !freezeInput) { MVMain.Sound.Play("jump1"); // animator.SetBool("StartJumpBool", true); velocity.y = jumpTakeOffSpd + (godMode ? 5f : 0f); } else if (Input.GetButtonUp("Jump") || freezeInput) { // animator.SetBool("StartJumpBool", false); if (velocity.y > 0) { velocity.y *= .5f; } } else if (Input.GetButton("Jump")) { // animator.SetBool("StartJumpBool", false); } if (weapons.Count > 0 && !ActiveWeapon.fired && !freezeInput) { if (Input.GetButtonDown("Scroll+")) { activeWeaponIndex++; if (activeWeaponIndex >= weapons.Count) { activeWeaponIndex -= weapons.Count; } } else if (Input.GetButtonDown("Scroll-")) { activeWeaponIndex--; if (activeWeaponIndex < 0) { activeWeaponIndex += weapons.Count; } } } velocity.x = xMove * (maxSpeed + (godMode ? 5f : 0f)); bool flipSprite = (SpriteFlipX ? (xMove > 0.01f) : (xMove < -0.01f)); if (flipSprite && !inJumpBack) { transform.localScale = new Vector3(transform.localScale.x * -1, transform.localScale.y, transform.localScale.z); } // animator.SetFloat("Speed", Mathf.Abs(velocity.x)); // animator.SetFloat("VelY", velocity.y); // animator.SetBool("Grounded", grounded); }
/// <summary> /// Recalculate RoomData /// </summary> public void RecalculateData() { receivers = new List <ReceiverData>(); Grid grid = Room.GetComponentInChildren <Grid>(); foreach (Tilemap map in grid.GetComponentsInChildren <Tilemap>()) { if (map.name == "Teleporter") { foreach (Vector3Int pos in map.cellBounds.allPositionsWithin) { Vector3Int localplace = new Vector3Int(pos.x, pos.y, pos.z); if (!map.HasTile(localplace)) { continue; } string tileName = map.GetTile(pos).name; Vector2Int tileChunkPos = MVUtility.TilePosToLocalChunkPos(pos.x, pos.y, chunkTopLeft, new Vector2Int(24, 16)); if (tileName[0] == 'O' && tileName.Length == 2 && char.IsDigit(tileName[1])) { //Receiver ReceiverData receiverData = new ReceiverData { name = tileName, chunkPos = tileChunkPos }; receivers.Add(receiverData); } else if (tileName[0] == 'I' && tileName.Length == 2 && char.IsDigit(tileName[1])) { //Teleporter TeleporterData teleporter = teleporters.FirstOrDefault(x => x.teleporter == tileName); if (teleporter == null) { continue; } //atas if (tileChunkPos.x < 0) { teleporter.teleporterType = TeleporterData.TeleporterType.Vertical; teleporter.teleporterDirection = Direction.Up; teleporter.chunkPos = tileChunkPos + Vector2Int.right; } //bawah else if (tileChunkPos.x >= chunkSize.x) { teleporter.teleporterType = TeleporterData.TeleporterType.Vertical; teleporter.teleporterDirection = Direction.Down; teleporter.chunkPos = tileChunkPos + Vector2Int.left; } //kiri else if (tileChunkPos.y < 0) { teleporter.teleporterType = TeleporterData.TeleporterType.Horizontal; teleporter.teleporterDirection = Direction.Left; teleporter.chunkPos = tileChunkPos + Vector2Int.up; } //kanan else if (tileChunkPos.y >= chunkSize.y) { teleporter.teleporterType = TeleporterData.TeleporterType.Horizontal; teleporter.teleporterDirection = Direction.Right; teleporter.chunkPos = tileChunkPos + Vector2Int.down; } //bug :v else { teleporter.teleporterType = TeleporterData.TeleporterType.Direct; teleporter.teleporterDirection = Direction.Up; teleporter.chunkPos = tileChunkPos; } } } } } }
/// <summary> /// Get local chunk position based from tile position /// </summary> /// <param name="pos">tile position</param> /// <returns>position of chunk in room</returns> public Vector2Int GetLocalChunkPos(Vector3Int pos) { return(MVUtility.TilePosToLocalChunkPos(pos.x, pos.y, activeRoomData.chunkTopLeft, new Vector2Int(24, 16))); }