První 3 monstra z plánovaných pěti. Kompletní pathfinding i zrcadlení do clienta. Útoky implementované nejsou. Lurk a Neko jsou hardcoded aby útočili na P1.
This commit is contained in:
parent
4484b127c5
commit
9bfe63a166
27 changed files with 772 additions and 47 deletions
21
FNAF_Clone/ClientEnemy.cs
Normal file
21
FNAF_Clone/ClientEnemy.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using FNAF_Clone.GUI;
|
||||
using FNAF_Clone.Map;
|
||||
using GlobalClassLib;
|
||||
using MonoGameLibrary.Graphics;
|
||||
|
||||
namespace FNAF_Clone;
|
||||
|
||||
public class ClientEnemy : GlobalEnemy<MapTileProjection, TileConnectorProjection> {
|
||||
public ClientEnemy(int typeId, string name, int id, UIElement sprite, int difficulty, MapTileProjection location) : base(difficulty, id) {
|
||||
Name = name;
|
||||
TypeId = typeId;
|
||||
Sprite = sprite;
|
||||
Location = location;
|
||||
}
|
||||
|
||||
// public TextureRegion Sprite { get; set; }
|
||||
|
||||
public UIElement Sprite { get; set; }
|
||||
public override string Name{ get; }
|
||||
public override int TypeId{ get; }
|
||||
}
|
||||
53
FNAF_Clone/ClientEnemyManager.cs
Normal file
53
FNAF_Clone/ClientEnemyManager.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using FNAF_Clone.GUI;
|
||||
using FNAF_Clone.Map;
|
||||
using GlobalClassLib;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FNAF_Clone;
|
||||
|
||||
public class ClientEnemyManager {
|
||||
private static Dictionary<int, ClientEnemy> enemies = new();
|
||||
private static Point cameraCorner = new Point(64, 64);
|
||||
|
||||
public static void AddEnemy(ClientEnemy enemy) {
|
||||
enemies.Add(enemy.Id, enemy);
|
||||
UIManager.AddEnemySprite(enemy.Id, enemy.Sprite);
|
||||
}
|
||||
|
||||
public static void AddEnemyByTemplate(EnemyType type, int id, int difficulty, MapTileProjection location) {
|
||||
switch (type){
|
||||
case EnemyType.LURK:
|
||||
AddEnemy(new ClientEnemy((int)type, "Lurk", id, new UIElement(UIManager.enemyAtlas[0], cameraCorner), difficulty, location));
|
||||
break;
|
||||
case EnemyType.NEKO:
|
||||
AddEnemy(new ClientEnemy((int)type, "Neko", id, new UIElement(UIManager.enemyAtlas[1], cameraCorner), difficulty, location));
|
||||
break;
|
||||
case EnemyType.SPOT:
|
||||
UIElement element =
|
||||
new UIElement([UIManager.enemyAtlas[2], UIManager.enemyAtlas[3], UIManager.enemyAtlas[4], UIManager.enemyAtlas[5]], cameraCorner);
|
||||
element.SetTexture(2);
|
||||
AddEnemy(new ClientEnemy((int)type, "Spot", id, element, difficulty, location));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Move(int id, MapTileProjection tile) {
|
||||
enemies[id].Location = tile;
|
||||
}
|
||||
|
||||
public static ClientEnemy Get(int id) => enemies[id];
|
||||
|
||||
public static ClientEnemy[] GetByLocation(MapTileProjection tile) {
|
||||
List<ClientEnemy> output = new();
|
||||
foreach (var e in enemies.Values){
|
||||
if (e.Location == tile){
|
||||
output.Add(e);
|
||||
}
|
||||
}
|
||||
|
||||
return output.ToArray();
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,8 @@ public class CommandManager {
|
|||
SendToggleRemoteDoor(direction);
|
||||
return;
|
||||
}
|
||||
|
||||
if (direction == Direction.SOUTH) return;
|
||||
Client.Player.state.doorStates[(int)direction] = !Client.Player.state.doorStates[(int)direction];
|
||||
UIManager.ChangeDoorState(direction, Client.Player.state.doorStates[(int)direction]);
|
||||
Client.SendCommands([PlayerCommand.SET_DOOR_OFFICE(direction, Client.Player.state.doorStates[(int)direction])]);
|
||||
|
|
|
|||
|
|
@ -13,12 +13,27 @@
|
|||
|
||||
#---------------------------------- Content ---------------------------------#
|
||||
|
||||
#begin images/enemies-definition.xml
|
||||
/copy:images/enemies-definition.xml
|
||||
|
||||
#begin images/monitor-definition.xml
|
||||
/copy:images/monitor-definition.xml
|
||||
|
||||
#begin images/office-definition.xml
|
||||
/copy:images/office-definition.xml
|
||||
|
||||
#begin images/SpriteSheet_enemies.png
|
||||
/importer:TextureImporter
|
||||
/processor:TextureProcessor
|
||||
/processorParam:ColorKeyColor=255,0,255,255
|
||||
/processorParam:ColorKeyEnabled=True
|
||||
/processorParam:GenerateMipmaps=False
|
||||
/processorParam:PremultiplyAlpha=True
|
||||
/processorParam:ResizeToPowerOfTwo=False
|
||||
/processorParam:MakeSquare=False
|
||||
/processorParam:TextureFormat=Color
|
||||
/build:images/SpriteSheet_enemies.png
|
||||
|
||||
#begin images/SpriteSheet_monitor.png
|
||||
/importer:TextureImporter
|
||||
/processor:TextureProcessor
|
||||
|
|
|
|||
BIN
FNAF_Clone/Content/images/SpriteSheet_enemies.png
Normal file
BIN
FNAF_Clone/Content/images/SpriteSheet_enemies.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
15
FNAF_Clone/Content/images/enemies-definition.xml
Executable file
15
FNAF_Clone/Content/images/enemies-definition.xml
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextureAtlas count="9">
|
||||
<Texture>images/SpriteSheet_enemies</Texture>
|
||||
<Regions>
|
||||
<Region id = "0" name="lurk" x="0" y="0" width="240" height="240"/>
|
||||
<Region id = "1" name="neko" x="0" y="240" width="240" height="240"/>
|
||||
<Region id = "2" name="spot-awake-lit" x="0" y="480" width="240" height="240"/>
|
||||
<Region id = "3" name="spot-awake-unlit" x="240" y="480" width="240" height="240"/>
|
||||
<Region id = "4" name="spot-asleep-lit" x="0" y="720" width="240" height="240"/>
|
||||
<Region id = "5" name="spot-asleep-unlit" x="240" y="720" width="240" height="240"/>
|
||||
<Region id = "6" name="dash" x="0" y="960" width="240" height="240"/>
|
||||
<Region id = "7" name="mare-lit" x="0" y="1200" width="240" height="240"/>
|
||||
<Region id = "8" name="mare-unlit" x="240" y="1200" width="240" height="240"/>
|
||||
</Regions>
|
||||
</TextureAtlas>
|
||||
|
|
@ -64,9 +64,30 @@ public class EventProcessor {
|
|||
UIManager.ChangeRemoteDoorState((e.Args[1], e.Args[2]), e.Args[3] == 1);
|
||||
break;
|
||||
|
||||
case -1: // movement
|
||||
throw new NotImplementedException();
|
||||
|
||||
case 6: // spawn
|
||||
Console.WriteLine($"E: Spawned enemy {e.Args[0]} at {e.Args[3]}");
|
||||
ClientEnemyManager.AddEnemyByTemplate((EnemyType)e.Args[0], e.Args[1], e.Args[2], ClientMapManager.Get(e.Args[3]));
|
||||
UIManager.UpdateCameras([e.Args[3]]);
|
||||
break;
|
||||
|
||||
case 7: // movement
|
||||
Console.WriteLine($"E: Enemy {e.Args[0]} moved to {e.Args[1]}");
|
||||
int oldPos = ClientEnemyManager.Get(e.Args[0]).Location!.Id;
|
||||
ClientEnemyManager.Move(e.Args[0], ClientMapManager.Get(e.Args[1]));
|
||||
UIManager.UpdateCameras([oldPos, e.Args[1]]);
|
||||
break;
|
||||
|
||||
case 9:
|
||||
Console.WriteLine($"E: Enemy {e.Args[0]} reset to {e.Args[1]}");
|
||||
int preResetPos = ClientEnemyManager.Get(e.Args[0]).Location!.Id;
|
||||
ClientEnemyManager.Move(e.Args[0], ClientMapManager.Get(e.Args[1]));
|
||||
UIManager.UpdateCameras([preResetPos, e.Args[1]]);
|
||||
break;
|
||||
|
||||
case 10:
|
||||
Console.WriteLine($"E: Spot:{e.Args[0]} turned {(e.Args[1] == 1 ? "on" : " off")}");
|
||||
ClientEnemyManager.Get(e.Args[0]).Sprite.SetTexture(e.Args[1] == 1 ? 0 : 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ public class Screen {
|
|||
}
|
||||
|
||||
public UIElement this[string id] => elements[id];
|
||||
public UIElement TryGetElement(string id) => elements.TryGetValue(id, out var val) ? val : null;
|
||||
|
||||
public void AddElement(string id, UIElement element) {
|
||||
elements.Add(id, element);
|
||||
|
|
@ -80,8 +81,6 @@ public class Screen {
|
|||
}
|
||||
|
||||
public void Update() {
|
||||
|
||||
|
||||
foreach (var keyValuePair in elements){
|
||||
keyValuePair.Value.Update();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,9 +69,7 @@ public class UIElement {
|
|||
|
||||
currentTextureId = textureId;
|
||||
}
|
||||
public void Update() {
|
||||
|
||||
}
|
||||
public virtual void Update() { }
|
||||
|
||||
public bool IsWithinBounds(Point pos) {
|
||||
return pos.X >= Math.Min(screenSpaceBounds.Item1.X, screenSpaceBounds.Item2.X) && pos.X <= Math.Max(screenSpaceBounds.Item1.X, screenSpaceBounds.Item2.X) &&
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using FNAF_Clone.Map;
|
||||
using GlobalClassLib;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
|
@ -21,15 +23,19 @@ public class UIManager {
|
|||
private static TextureAtlas testAtlas;
|
||||
private static TextureAtlas officeAtlas;
|
||||
private static TextureAtlas monitorAtlas;
|
||||
public static TextureAtlas enemyAtlas;
|
||||
|
||||
public static int GlobalPixelMultiplier{ get; private set; }
|
||||
|
||||
private Dictionary<(int, int), UIElement> doorElements = new();
|
||||
private static Dictionary<int, UIElement> enemyElements = new();
|
||||
public static void InitUI() {
|
||||
GlobalPixelMultiplier = Core.graphicsDevice.Viewport.Height / 360;
|
||||
|
||||
testAtlas = TextureAtlas.FromFile(Core.content, "images/testBlocks-definition.xml");
|
||||
officeAtlas = TextureAtlas.FromFile(Core.content, "images/office-definition.xml");
|
||||
monitorAtlas = TextureAtlas.FromFile(Core.content, "images/monitor-definition.xml");
|
||||
enemyAtlas = TextureAtlas.FromFile(Core.content, "images/enemies-definition.xml");
|
||||
|
||||
Screen.AddScreens([officeScreen, monitorScreen]);
|
||||
Screen.SetScreen(ScreenTypes.OFFICE);
|
||||
|
|
@ -67,6 +73,7 @@ public class UIManager {
|
|||
monitorScreen.AddElement("eye-player", new UIElement(monitorAtlas[24], monitorScreen["room"+Client.Player.state.camera].Bounds.Item1));
|
||||
monitorScreen.AddElement("eye-opponent", new UIElement([monitorAtlas[23], monitorAtlas[22]], monitorScreen["room"+Client.Opponent.state.camera].Bounds.Item1));
|
||||
|
||||
UpdateCameras([Client.Player.state.camera]);
|
||||
}
|
||||
|
||||
public static void SpawnDoors(TileConnectorProjection[] doors) {
|
||||
|
|
@ -91,6 +98,13 @@ public class UIManager {
|
|||
monitorScreen.AddElement("p2-office-door-left", new UIElement([monitorAtlas[17], monitorAtlas[18]], new Point(400, 144)));
|
||||
|
||||
}
|
||||
|
||||
public static void AddEnemySprite(int id, UIElement sprite) {
|
||||
monitorScreen.AddElement($"enemy{id}", sprite);
|
||||
enemyElements.Add(id, sprite);
|
||||
sprite.Visible = false;
|
||||
}
|
||||
|
||||
|
||||
public static void ChangeDoorState(Direction dir, bool state) {
|
||||
int stateInt = state ? 1 : 0;
|
||||
|
|
@ -141,12 +155,25 @@ public class UIManager {
|
|||
|
||||
public static void ChangeCamera(int id) {
|
||||
monitorScreen["eye-player"].SetPosition(monitorScreen["room"+id].Bounds.Item1);
|
||||
UpdateCameras([id]);
|
||||
}
|
||||
|
||||
public static void UpdateCameras(int[] camIds) {
|
||||
if (camIds.Contains(Client.Player.state.camera)){
|
||||
enemyElements.Values.Where(e => e.Visible).ToList().ForEach(e => e.Visible = false);
|
||||
ClientEnemy[] enemies = ClientEnemyManager.GetByLocation(ClientMapManager.Get(Client.Player.state.camera));;
|
||||
foreach (var enemy in enemies){
|
||||
enemyElements.TryGetValue(enemy.Id, out var element);
|
||||
if (element == null) continue;
|
||||
element.Visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void ChangeCameraOpponent(int id) {
|
||||
monitorScreen["eye-opponent"].SetPosition(monitorScreen["room"+id].Bounds.Item1);
|
||||
|
||||
}
|
||||
|
||||
// private static Point GetRoomUIPos((int x, int y) pos) {
|
||||
// return new Point(336 + (32 * pos.x), 144 + (32 * pos.y));
|
||||
// }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue