public override void Update(float deltaTime) { base.Update(deltaTime); if (burstCounter > 0) { burstTimer -= deltaTime; if (burstTimer <= 0f) { Assets.pew.Play(1f, (float)rand.NextDouble() - 0.5f, 0f); Vector3 direction = Vector3.Normalize(Camera.CameraPos - Position); float delta = (float)rand.NextDouble() * 0.125f - 0.0625f; direction = Vector3.Transform(direction, Mathg.RotationMatrix(delta)); Fire(direction); burstCounter--; if (burstCounter > 0) { burstTimer = burstDelay; } else { burstTimer = 0f; } } } }
public bool CheckMovement(Vector3 from, Vector3 direction, float radius, int layerMask) { Vector2 from2 = new Vector2(from.X, from.Z); Vector2 direction2 = new Vector2(direction.X, direction.Z); Vector2 to2 = from2 + direction2; foreach (Obstacle obstacle in obstacles) { if (ObstacleLayerMask.CheckMask(layerMask, obstacle.Layer)) { Vector2 v0 = obstacle.Start; Vector2 v1 = obstacle.End; Vector2 normal2 = Vector2.Normalize(new Vector2((v1 - v0).Y, -(v1 - v0).X)); if (Mathg.Cross2D(v1 - v0, from2 - v0) > 0) { normal2 *= -1; } v0 += normal2 * radius; v1 += normal2 * radius; if (Mathg.Cross2D(v1 - v0, from2 - v0) * Mathg.Cross2D(v1 - v0, to2 - v0) < 0 && Mathg.Cross2D(to2 - from2, v0 - from2) * Mathg.Cross2D(to2 - from2, v1 - from2) < 0) { return(false); } } } return(true); }
protected override PopulateRoomResults PopulateRoom(Scene scene, Zone zone, int x, int y, PopulateSchemeFlags flags) { PopulateRoomResults results = new PopulateRoomResults { GenerateFloor = true }; float left = x * tileSize - size * tileSize / 2; float right = left + tileSize; float bottom = y * tileSize - size * tileSize / 2; float top = bottom + tileSize; Vector3 roomCenter = new Vector3((left + right) / 2, 0f, (top + bottom) / 2); if (!flags.IsSpecial) { int monsterCount = rand.Next(flags.ClearCenter ? 1 : 2, monstersPerRoom + 1); game.PlayerStats.totalMonsters += monsterCount; Vector2 shift = monsterCount == 1 ? Vector2.Zero : new Vector2(30f, 0f); float angleOffset = (float)(rand.NextDouble() * Math.PI * 2f); for (int i = 0; i < monsterCount; i++) { Vector2 position = new Vector2(roomCenter.X, roomCenter.Z); position += Vector2.Transform(shift, Mathg.RotationMatrix2D(angleOffset + i * (float)Math.PI * 2f / monsterCount)); Vector3 position3 = new Vector3(position.X, -1f, position.Y); Monster monster = Mathg.DiscreteChoiceFn(rand, new Func <Monster>[] { () => new BasicMonster(position3, monsterHP, monsterDamage), () => new IceMonster(position3, monsterHP, monsterDamage * 0.3f), () => new ShotgunDude(position3, monsterHP, monsterDamage), () => new IceShotgunDude(position3, monsterHP, monsterDamage * 0.3f), () => new SpinnyBoi(position3, monsterHP * 2, monsterDamage), () => new Spooper(position3, monsterHP * 1.5f, monsterDamage) }, monsterChances); scene.AddGameObject(monster); } if (monsterCount != 1) { flags.ClearPerimeter = false; } else { flags.ClearCenter = false; } } if (rand.Next(4) == 0 || (flags.ClearPerimeter && rand.Next(2) == 0)) // special room { PopulateSpecialRoom(scene, zone, roomCenter, flags, ref results); } else { PopulateRoomCenter(scene, zone, roomCenter, flags); PopulateRoomWalls(scene, zone, roomCenter, flags); } return(results); }
protected override void Attack(Vector3 towardsTarget) { Assets.pew.Play(1f, 0f, 0f); Assets.pew.Play(1f, -0.5f, 0f); Assets.pew.Play(1f, -1f, 0f); for (int i = -5; i <= 5; i++) { float delta = i * 0.4f / 5; Vector3 direction = Vector3.Transform(towardsTarget, Mathg.RotationMatrix(delta)); Fire(direction); } }
protected override void Attack(Vector3 towardsTarget) { counter++; Assets.btsch.Play(); float dispersion = (float)Math.Atan(0.75f); for (int i = 0; i < 16; i++) { float delta = i * 2f * (float)Math.PI / 16f + (counter % 3 - 1) * dispersion; Vector3 direction = Vector3.Transform(towardsTarget, Mathg.RotationMatrix(delta)); Fire(direction, 20f); } }
// Given start position and movement vector, return the real movement vector taking into account collisions public Vector3 SmoothMovement(Vector3 from, Vector3 direction, float radius, int layerMask) { Vector3 ret = direction; while (!CheckMovement(from, ret, radius, layerMask, out Vector3 normal, out float relativeLength)) { relativeLength *= 0.9f; if (relativeLength < 0.01f) { relativeLength = 0f; } ret = relativeLength * ret + Mathg.OrthogonalComponent((1f - relativeLength) * ret, normal); } return(ret); }
public bool CheckMovement(Vector3 from, Vector3 direction, float radius, int layerMask, out Vector3 normal, out float relativeLength) { normal = Vector3.Zero; relativeLength = float.MaxValue; bool ret = true; Vector2 from2 = new Vector2(from.X, from.Z); Vector2 direction2 = new Vector2(direction.X, direction.Z); Vector2 to2 = from2 + direction2; foreach (Obstacle obstacle in obstacles) { if (ObstacleLayerMask.CheckMask(layerMask, obstacle.Layer)) { Vector2 v0 = obstacle.Start; Vector2 v1 = obstacle.End; Vector2 normal2 = Vector2.Normalize(new Vector2((v1 - v0).Y, -(v1 - v0).X)); Vector2 orth = new Vector2(normal2.Y, -normal2.X); v0 += (normal2 + orth) * radius; v1 += (normal2 - orth) * radius; if (Mathg.Cross2D(v1 - v0, from2 - v0) * Mathg.Cross2D(v1 - v0, to2 - v0) < 0 && Mathg.Cross2D(to2 - from2, v0 - from2) * Mathg.Cross2D(to2 - from2, v1 - from2) < 0 && Vector2.Dot(normal2, Vector2.Normalize(direction2)) < 0.1f) { float t = Vector2.Dot(v0 - from2, normal2) / Vector2.Dot(direction2, normal2); if (t < relativeLength) { relativeLength = t; normal = new Vector3(normal2.X, 0f, normal2.Y); } ret = false; } } } return(ret); }
protected override PopulateRoomResults PopulateRoom(Scene scene, Zone zone, int x, int y, PopulateSchemeFlags flags) { PopulateRoomResults results = new PopulateRoomResults { GenerateFloor = true }; float left = x * tileSize - size * tileSize / 2; float right = left + tileSize; float bottom = y * tileSize - size * tileSize / 2; float top = bottom + tileSize; Vector3 roomCenter = new Vector3((left + right) / 2, 0f, (top + bottom) / 2); bool[] roomCorridors = Enumerable.Range(0, 4).Select(t => corridorLayout[x, y, t]).ToArray(); if ((x != exitRoom.X || y != exitRoom.Y) && (x != size / 2 || y != size / 2)) { int monsterCount = rand.Next(2, monstersPerRoom + 1); game.PlayerStats.totalMonsters += monsterCount; List <Vector3> spawnPoints = new List <Vector3>(); Vector2 shift = monsterCount == 1 ? Vector2.Zero : new Vector2(30f, 0f); float angleOffset = (float)(rand.NextDouble() * Math.PI * 2f); for (int i = 0; i < monsterCount; i++) { Vector2 position = new Vector2(roomCenter.X, roomCenter.Z); position += Vector2.Transform(shift, Mathg.RotationMatrix2D(angleOffset + i * (float)Math.PI * 2f / monsterCount)); Vector3 position3 = new Vector3(position.X, -1f, position.Y); Monster monster = Mathg.DiscreteChoiceFn(rand, new Func <Monster>[] { () => new BasicMonster(position3, monsterHP, monsterDamage), () => new BasicMonster(position3, monsterHP, monsterDamage), () => new ShotgunDude(position3, monsterHP, monsterDamage), () => new SpinnyBoi(position3, monsterHP * 2, monsterDamage), () => new Spooper(position3, monsterHP * 1.5f, monsterDamage) }, monsterChances); scene.AddGameObject(monster); } } if (rand.Next(7) == 0) { SceneStructures.PitWithBridges(FloorTexture, WallTexture, FloorTexture, roomCorridors).Invoke(scene, zone, roomCenter); SceneGenUtils.AddFloor(zone, -50f * Vector2.One, 50f * Vector2.One, -10f, Assets.lavaTexture, true, roomCenter, 75f); results.GenerateFloor = false; } else if (rand.Next(3) == 0) { if (x != size / 2 || y != size / 2) { SpawnPools(scene, x, y, roomCenter, flags); } List <Generator> generators = new List <Generator> { SceneStructures.Pillars4Inner(WallTexture), SceneStructures.Pillars4Outer(WallTexture) }; if (flags.ClearCenter) { generators.Add(SceneStructures.PillarBig(WallTexture)); generators.Add(SceneStructures.PillarSmall(WallTexture)); } Mathg.DiscreteChoice(rand, generators).Invoke(scene, zone, roomCenter); } return(results); }