Power - spotřebovává se když jsou zavřené dveře. Hráči mohou zavírat pouze dveře na svojí polovině mapy. Oprava bugu v MovementOpportunity, který způsoboval zpožďování intervalu.

This commit is contained in:
Perry 2026-03-12 22:33:35 +01:00
parent 7656707177
commit 25a62af483
22 changed files with 240 additions and 59 deletions

View file

@ -96,13 +96,14 @@ public class Client {
Player.state = packet.state;
}
#nullable enable
private static void OnMapInit(MapInitPacket packet) {
(int id1, int id2, ConnectorType type)[] connectorsData = new (int id1, int id2, ConnectorType type)[packet.Connectors.Length / 3];
for (int i = 0; i < packet.Connectors.Length / 3; i++){
connectorsData[i] = (packet.Connectors[i * 3], packet.Connectors[i * 3 + 1], (ConnectorType)packet.Connectors[i * 3 + 2]);
(int id1, int id2, ConnectorType type, ClientPlayer? owner)[] connectorsData = new (int, int , ConnectorType, ClientPlayer?)[packet.Connectors.Length / 4];
for (int i = 0; i < packet.Connectors.Length / 4; i++){
connectorsData[i] = (packet.Connectors[i * 4], packet.Connectors[i * 4 + 1], (ConnectorType)packet.Connectors[i * 4 + 2], packet.Connectors[i * 4 + 3] == -1 ? null : GetPlayer(packet.Connectors[i * 4 + 3]));
}
ClientMapManager.InitMap(packet.UpsideDown);
TileConnectorProjection[] connectors = connectorsData.Select(c => new TileConnectorProjection(ClientMapManager.Get(c.id1), ClientMapManager.Get(c.id2), c.type)).ToArray();
TileConnectorProjection[] connectors = connectorsData.Select(c => new TileConnectorProjection(ClientMapManager.Get(c.id1), ClientMapManager.Get(c.id2), c.type){Owner = c.owner}).ToArray();
ClientMapManager.InitConnectors(connectors);
UIManager.SpawnMapElements(connectors.Where(c => c.Type == ConnectorType.DOOR_REMOTE).ToArray());

View file

@ -55,8 +55,9 @@ public class CommandManager {
}
private static void SendToggleRemoteDoor(Direction direction) {
if (!currentDoorBinds.TryGetValue(direction, out var val)) return;
TileConnectorProjection connector = val;
if (!currentDoorBinds.TryGetValue(direction, out var connector)) return;
if (connector.Owner != Client.Player) return;
connector.Blocked = !connector.Blocked;
Client.SendCommands([PlayerCommand.SET_DOOR_REMOTE(connector.Id, connector.Blocked)]);
UIManager.ChangeRemoteDoorState(connector.Id, connector.Blocked);
@ -65,6 +66,8 @@ public class CommandManager {
}
public static void SendChangeCamera(int id) {
if (id == Client.Player.state.officeTileId || id == Client.Opponent.state.officeTileId) return;
Client.Player.state.camera = id;
UIManager.ChangeCamera(id);
Client.SendCommands([PlayerCommand.SWITCH_CAM(id)]);

View file

@ -1,7 +1,9 @@
using System;
using System.Linq;
using FNAF_Clone.GUI;
using FNAF_Clone.Map;
using GlobalClassLib;
using MonoGameLibrary.Input;
using PacketLib;
namespace FNAF_Clone;
@ -102,10 +104,50 @@ public class EventProcessor {
break;
case 12:
Console.WriteLine($"E: Game started");
Console.WriteLine("E: Game started");
UIManager.DisplayGameUI();
UIManager.StartTimer();
break;
case 13:
Console.WriteLine($"E: power tick {e.Args[0]}: {e.Args[1]}");
if (e.Args[0] == Client.Player.state.pid){
Client.Player.state.power = e.Args[1];
}
else{
Client.Opponent.state.power = e.Args[1];
}
break;
case 14:
Console.WriteLine($"E: Player {e.Args[0]} powered out");
ClientMapManager.GetAllConnectors().Where(c =>
(c.Type == ConnectorType.DOOR_REMOTE || c.Type == ConnectorType.DOOR_OFFICE) &&
c.Owner == Client.GetPlayer(e.Args[0])).ToList().ForEach(c =>
{
c.Blocked = false;
if(c.Type == ConnectorType.DOOR_REMOTE)
UIManager.ChangeRemoteDoorState(c.Id, false);
});
if (e.Args[0] == Client.Player.state.pid){
UIManager.ChangeDoorState(Direction.EAST, false);
UIManager.ChangeDoorState(Direction.NORTH, false);
UIManager.ChangeDoorState(Direction.WEST, false);
CommandManager.AllowGameControls(false);
UIManager.ChangeMonitorState(false);
}
else{
UIManager.ChangeDoorStateOpponent(Direction.EAST, false);
UIManager.ChangeDoorStateOpponent(Direction.NORTH, false);
UIManager.ChangeDoorStateOpponent(Direction.WEST, false);
UIManager.ChangeMonitorStateOpponent(false);
}
break;
}
}
}

View file

@ -0,0 +1,26 @@
using GlobalClassLib;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace FNAF_Clone.GUI;
public class PowerIndicator : TextUIElement {
private string label;
private ClientPlayer player;
private int lastPowerValue;
public PowerIndicator(Point corner1, SpriteFont font, ClientPlayer player, string label, Alignment alignment = Alignment.LEFT) : base(corner1, font, alignment, autoBounds:true) {
this.player = player;
this.label = label;
lastPowerValue = player.state.power;
Text = GetText();
}
public override void Update() {
if (player.state.power == lastPowerValue) return;
lastPowerValue = player.state.power;
Text = GetText();
}
private string GetText() => $"{label}{(int)(((float)player.state.power / Power.MAX_POWER_VALUE) * 100)}";
}

View file

@ -9,8 +9,9 @@ public class TimerUIElement : TextUIElement{
private Stopwatch stopwatch = new();
public TimerUIElement(Point corner1, SpriteFont font) : base(corner1, corner1, font) {
public TimerUIElement(Point corner1, SpriteFont font) : base(corner1, font) {
Text = "00:00.000";
Bounds = (corner1, corner1 + new Point((int)Measure().X, (int)Measure().Y));
}
public override void Update() {

View file

@ -79,28 +79,18 @@ public class UIManager {
timerElement = new(new(0, 0), PixelMonoFont);
overlayScreen.AddElement("timer", timerElement);
officeScreen.AddElement("power-p1-office", new PowerIndicator(new(timerElement.Bounds.Item1.X, timerElement.Bounds.Item2.Y + 5), PixelMonoFont, Client.Player, "POWER: "));
TextUIElement powerLabel = (TextUIElement)
monitorScreen.AddElement("power-label", new TextUIElement(new(510, 150), PixelMonoFont){Text = "POWER:"});
TextUIElement powerP1 = (TextUIElement)
monitorScreen.AddElement("power-p2", new PowerIndicator(new(powerLabel.Bounds.Item1.X + 10, powerLabel.Bounds.Item2.Y + 10), PixelMonoFont, Client.Opponent, ""){Color = new Color(220, 10, 10, 255)});
monitorScreen.AddElement("power-p1", new PowerIndicator( new (powerP1.Bounds.Item1.X, powerP1.Bounds.Item2.Y + 5), PixelMonoFont, Client.Player, ""){Color = new Color(15, 190, 247, 255)});
winScreen.AddElement("win-text", new TextUIElement(new(320, 180), PixelMonoFont, TextUIElement.Alignment.CENTER){Text = "YOU WIN", Color = Color.Green});
loseScreen.AddElement("lose-text", new TextUIElement(new(320, 180), PixelMonoFont, TextUIElement.Alignment.CENTER){Text = "YOU LOSE", Color = Color.Red});
// overlayScreen.AddElement("test", new TextBoxUIElement(PixelMonoFont, Point.Zero, new(200, 100)));
// Main menu
// TextUIElement serverIpLabel = (TextUIElement) menuScreen.AddElement("server-ip-label", new TextUIElement(new (20, 20), PixelMonoFont){Text = "ENTER SERVER IP: ", Color = Color.Gray});
// TextBoxUIElement serverIpTextBox = (TextBoxUIElement)menuScreen.AddElement("server-ip-textbox",
// new TextBoxUIElement(PixelMonoFont,
// new(serverIpLabel.Bounds.Item1.X + (int)serverIpLabel.Measure().X, serverIpLabel.Bounds.Item1.Y),
// new(640, serverIpLabel.Bounds.Item2.Y + (int)serverIpLabel.Measure().Y)));
// serverIpTextBox.OnFocused = () => {
// serverIpTextBox.Color = Color.LightGreen;
// serverIpLabel.Color = Color.DarkGreen;
// };
// serverIpTextBox.OnUnfocused = () => {
// serverIpTextBox.Color = Color.White;
// serverIpLabel.Color = Color.Gray;
// };
MenuInputField usernameField = (MenuInputField)menuScreen.AddElement("username-field", new MenuInputField(PixelMonoFont, new(20, 20), "USERNAME: "));
MenuInputField field = (MenuInputField)menuScreen.AddElement("server-ip-field", new MenuInputField(PixelMonoFont, new(usernameField.Bounds.Item1.X, usernameField.Bounds.Item2.Y + 20), "SERVER IP: ", "127.0.0.1"));
UIElement connectButton = menuScreen.AddElement("server-ip-submit", new TextUIElement(new Point(field.Bounds.Item1.X, field.Bounds.Item2.Y), PixelMonoFont)

View file

@ -37,8 +37,6 @@ public class GameMain() : Core("fnafkooo", 1280, 720, false) {
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
// TODO: Add your update logic here
InputManager.NextInputCycle();
Screen.UpdateAll();

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.JavaScript;
using GlobalClassLib;
@ -18,7 +19,7 @@ public class ClientMapManager {
for (int i = 0; i < 5; i++){
for (int j = 0; j < 2; j++){
map[i, j] = new MapTileProjection(CoordsToId(i, j)); // TODO: implement ownership
map[i, j] = new MapTileProjection(CoordsToId(i, j));
}
map[i, 2] = new MapTileProjection(CoordsToId(i, 2));
for (int j = 3; j < 5; j++){
@ -26,8 +27,6 @@ public class ClientMapManager {
}
}
}
public static void InitConnectors(TileConnectorProjection[] connectors) {
@ -42,6 +41,21 @@ public class ClientMapManager {
public static TileConnectorProjection[] GetConnectors(int tileId) => Get(IdToCoords(tileId)).GetAllConnectors();
public static TileConnectorProjection[] GetAllConnectors() {
List<TileConnectorProjection> connectors = new();
for (int i = 0; i < 5; i++){
for (int j = 0; j < 5; j++){
MapTileProjection tile = map[i, j];
Array.ForEach(tile.GetAllConnectors(), c => {
if(tile.Id < c.OtherTile(tile).Id)
connectors.Add(c);
});
}
}
return connectors.ToArray();
}
public const int ID_X_OFFSET = 5; // map grid height

View file

@ -3,6 +3,7 @@ using GlobalClassLib;
namespace FNAF_Clone.Map;
public class MapTileProjection : GlobalMapTile<TileConnectorProjection, MapTileProjection> {
public ClientPlayer? Owner { get; set; }
public MapTileProjection(int id) : base(id, ClientMapManager.IdToCoords(id)) {
}
}

View file

@ -3,11 +3,12 @@ using GlobalClassLib;
namespace FNAF_Clone.Map;
public class TileConnectorProjection : GlobalTileConnector<MapTileProjection, TileConnectorProjection> {
public ClientPlayer? Owner { get; set; }
public TileConnectorProjection(MapTileProjection tile1, MapTileProjection tile2, ConnectorType type) : base(tile1, tile2, type) {
}
public TileConnectorProjection(MapTileProjection tile2, ConnectorType type) : base(tile2, type) {
}
public override TileConnectorProjection Clone() => new(Tiles.tile1, Tiles.tile2, Type);
public override TileConnectorProjection Clone() => new(Tiles.tile1, Tiles.tile2, Type){Owner = Owner};
}