A Familiar’s Tale Source code


As the project were closed source and there were other members I can only post my own code and not the entire project.

Room.cs

The code for handling individual rooms in the game.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Drawing;
using Microsoft.Xna.Framework;
using A_Familiars_Tale.Path;

namespace A_Familiars_Tale
{
    /// <summary>
    /// Class for the Room object
    /// </summary>
    public class Room
    {
        private readonly int roomWidth;
        private readonly int roomHeight;
        private LevelTile[,] room;
        private bool isLoaded = false;
        private List<GameObject> units = new List<GameObject>();

        public LevelTile[,] GetLevelTiles { get => room; }
        PathfindingNode[,] nodeGrid = new PathfindingNode[0,0];

        /// <summary>
        /// Constuctor for building a room from a spicefic png.
        /// </summary>
        /// <param name="roomImageName"></param>
        public Room(string roomImageName)
        {
            room = BuildRoomFromBitmap(AppDomain.CurrentDomain.BaseDirectory + $"Content\\Rooms\\{roomImageName}");
            roomHeight = room.GetLength(0);
            roomWidth = room.GetLength(1);
        }
        #region Room Load/unloading
        /// <summary>
        /// Loads the room into the gameworld.
        /// </summary>
        /// <returns>Returns is the room load were successful or not</returns>
        public bool LoadRoom()
        {
            if (isLoaded) return false;
            GameWorld gw = GameWorld.Instance;
            foreach (LevelTile tile in room)
            {
                gw.AddGameObject(tile);
            }
            foreach (GameObject unit in units)
            {
                gw.AddGameObject(unit);
            }
            isLoaded = true;
            return true;
        }

        /// <summary>
        /// Unloads the room from the gameworld;
        /// </summary>
        /// <returns>Returns is the room unload were successful or not</returns>
        public bool UnloadRoom()
        {
            if (!isLoaded) return false;
            GameWorld gw = GameWorld.Instance;
            foreach (GameObject unit in units)
            {
                gw.RemoveGameObject(unit);
            }
            foreach (LevelTile tile in room)
            {
                gw.RemoveGameObject(tile);
            }
            isLoaded = false;
            return true;
        }

        #region unit handling
        public void AddUnitToRoom(GameObject unit)
        {
            if (isLoaded)
            {
                GameWorld.Instance.AddGameObject(unit);
            }
            units.Add(unit);
        }

        public void RemoveUnitFromRoom(GameObject unit)
        {
            if (isLoaded)
            {
                GameWorld.Instance.RemoveGameObject(unit);
            }
            units.Remove(unit);
        }
        #endregion
        #endregion
        #region Room building
        /// <summary>
        /// Builds a room from a bitmap.
        /// </summary>
        /// <param name="bitmapFileLocation">The file location of the bitmap</param>
        /// <returns>returns a 2d array of LevelTiles</returns>
        private LevelTile[,] BuildRoomFromBitmap(string bitmapFileLocation)
        {

            LevelTile[,] tempRoomGrid;
            try
            {
                Bitmap bitmap = new Bitmap(bitmapFileLocation);

                tempRoomGrid = new LevelTile[(int)(bitmap.Height -1) / 2  , (int)(bitmap.Width -1)/ 2];
                
                int roomX = 0;
                int roomY = 0;


                for (int y = 1; y < (bitmap.Height -1); y+= 2)
                {
                    for (int x = 1; x < (bitmap.Width -1 ); x+= 2)
                    {
                        uint argb = (uint)bitmap.GetPixel(x, y).ToArgb();
                        Microsoft.Xna.Framework.Point gridPos = new Microsoft.Xna.Framework.Point(x, y);
                        switch (argb)
                        {
                            ////Black
                            //case 0xFF000000:
                            //    tempRoomGrid[roomY, roomX] = TileFactory.Instance.Create("SimpleWall", gridPos, ReadIsPassable(y,x, new Vector2(roomX, roomY),bitmap));
                            //    break;
                            //Red
                            case 0xFFFFFF00:
                                tempRoomGrid[roomY, roomX] = TileFactory.Instance.Create("TrapTile", new Microsoft.Xna.Framework.Point(roomX, roomY), ReadIsPassable(y, x, new Vector2(roomX, roomY), bitmap));
                                break;
                            case 0xFFFF0000:
                                tempRoomGrid[roomY, roomX] = TileFactory.Instance.Create("SimpleFloor", new Microsoft.Xna.Framework.Point(roomX, roomY), ReadIsPassable(y, x, new Vector2(roomX, roomY), bitmap));
                                break;
                            case 0xFFFFFFFF:
                                tempRoomGrid[roomY, roomX] = TileFactory.Instance.Create("empty", new Microsoft.Xna.Framework.Point(roomX, roomY), ReadIsPassable(y, x, new Vector2(roomX, roomY), bitmap));

                                break;
                            case 0xFF00ff00:
                                tempRoomGrid[roomY, roomX] = TileFactory.Instance.Create("SimpleFloor", new Microsoft.Xna.Framework.Point(roomX, roomY), ReadIsPassable(y, x, new Vector2(roomX, roomY), bitmap));
                                DestructableFactory.Instance.Create("item_barrel", new Microsoft.Xna.Framework.Point(roomX, roomY));
                                break;
                            case 0xFFff00ff:
                                tempRoomGrid[roomY, roomX] = TileFactory.Instance.Create("exit", new Microsoft.Xna.Framework.Point(roomX, roomY), ReadIsPassable(y, x, new Vector2(roomX, roomY), bitmap));
                                break;
                            //case
                            default:
                                tempRoomGrid[roomY, roomX] = null;
                                break;
                        }
                        roomX++;
                    }
                    roomX = 0;
                    roomY++;
                }
            }
            catch (Exception e)
            {
                Debug.Print(e.Message);
                tempRoomGrid = null;               
            }
            return tempRoomGrid;
        }
        #endregion
        #region unit tile binding

        private IsPassable ReadIsPassable(int y, int x, Vector2 gridPos, Bitmap bitmap)
        {
           
            bool n = true;
            bool e = true;
            bool s = true;
            bool w = true;

            uint argb = (uint)bitmap.GetPixel(x, y - 1).ToArgb();
            if (argb == 0xFF0000FF)
            {
                PlaceWall(argb, "n_door", new Vector2(gridPos.X, gridPos.Y - 1));
                n = false;
            }

            else if (argb != 0xFF737373)
            {
                n = false;
                PlaceWall(argb, "n", new Vector2(gridPos.X, gridPos.Y -1));
            }

            argb = (uint)bitmap.GetPixel(x, y + 1).ToArgb();
            if (argb != 0xFF737373)
                s = false;

            argb = (uint)bitmap.GetPixel(x - 1, y).ToArgb();
            if (argb != 0xFF737373)
            {
                w = false;
                PlaceWall(argb, "w", new Vector2(gridPos.X - 1, gridPos.Y));
            }

            argb = (uint)bitmap.GetPixel(x + 1, y).ToArgb();
            if (argb != 0xFF737373)
                e = false;


            return new IsPassable(n, e, s, w);
        }

        private void PlaceWall(uint argb, string dir, Vector2 gridPos)
        {
            if (dir == "w")
            {
                WallFactory.Instance.Create("wall_vertical", gridPos);
            }
            else if (dir == "n")
            {
                WallFactory.Instance.Create("wall_horizontal", gridPos);
            }
            else if (dir == "n_door")
            {
                WallFactory.Instance.Create("wall_door_horizontal", gridPos);
            }
        }

        //TODO: return persistent nodegrid
        /// <summary>
        /// NOOP
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="gridPos"></param>
        /// <returns></returns>
        public bool PlaceUnitOnTile(GameObject unit, Microsoft.Xna.Framework.Point gridPos)
        {
            if (gridPos.X < 0 || gridPos.Y < 0 || gridPos.X >= roomWidth || gridPos.Y >= roomHeight) return false;
            return room[gridPos.Y, gridPos.X].PlaceUnitOnTile(unit);
        }

        /// <summary>
        /// NOOP
        /// </summary>
        /// <param name="gridPos"></param>
        /// <returns></returns>
        public bool RemoveUnitFromTile(Microsoft.Xna.Framework.Point gridPos)
        {
            if (gridPos.X < 0 || gridPos.Y < 0 || gridPos.X >= roomWidth || gridPos.Y >= roomHeight) return false;
            return room[gridPos.Y, gridPos.X].RemoveUnitFromTile();
        }
        #endregion

        /// <summary>
        /// Gets the node grid from the room
        /// </summary>
        /// <returns></returns>
        public PathfindingNode[,] GetRoomNodeGrid()
        {
            if (nodeGrid.GetLength(0) == 0) //TODO: fix hack
            {
                nodeGrid = new PathfindingNode[roomHeight, roomWidth];
                for (int x = 0; x < roomWidth; x++)
                {
                    for (int y = 0; y < roomHeight; y++)
                    {
                        nodeGrid[y, x] = room[y, x].CreateNodeFromTile();
                    }
                }
            }
            return nodeGrid;
        }

        /// <summary>
        /// Gets the tile grid of the room.
        /// </summary>
        /// <returns>returns the tile grid of the room</returns>
        public LevelTile[,] GetRoomTiles()
        {
            return room;
        }

        /// <summary>
        /// Gets the tile in the room at a given grid position
        /// </summary>
        /// <param name="gridPos"></param>
        /// <returns></returns>
        public LevelTile GetTileFromRoom(Microsoft.Xna.Framework.Point gridPos)
        {
            if (gridPos.X < 0 || gridPos.Y < 0 || gridPos.X >= roomWidth || gridPos.Y >= roomHeight) return null;
            return room[gridPos.Y, gridPos.X];
        }
    }
}