Giter Club home page Giter Club logo

roguesharp's Introduction

Tutorials: Github.io Documentation: Github.io Posts: Blog License: MIT

Build status Build status Nuget

Test status Code coverage

Build History

RogueSharp with SadConsole

What is RogueSharp?

RogueSharp is a free library written in C# to help roguelike developers get a head start on their game. RogueSharp provides many utility functions for dealing with map generation, field-of-view calculations, path finding, random number generation and more.

It is loosely based on the popular libtcod or "Doryen Library" though not all features overlap.

Getting Started

  1. Visit the RogueSharp Blog for tips and tutorials.
  2. The quickest way to add RogueSharp to your project is by using the RogueSharp nuget package.
  3. If building the assembly yourself, the solution file "RogueSharp.sln" contains the main library and unit tests. This should be all you need.
  4. Class documentation is located on Github Pages.

Features

Pathfinding

With or without diagonals

Pathfinding with Diagonals

/// Constructs a new PathFinder instance for the specified Map 
/// that will consider diagonal movement by using the specified diagonalCost
public PathFinder( IMap map, double diagonalCost )

/// Returns a shortest Path containing a list of Cells 
/// from a specified source Cell to a destination Cell
public Path ShortestPath( ICell source, ICell destination )

Cell Selection

Select rows, columns, circles, squares and diamonds with and without borders.

Cell Selection

/// Get an IEnumerable of Cells in a circle around the center Cell up 
/// to the specified radius using Bresenham's midpoint circle algorithm
public IEnumerable<ICell> GetCellsInCircle( int xCenter, int yCenter, int radius )
  
/// Get an IEnumerable of outermost border Cells in a circle around the center 
/// Cell up to the specified radius using Bresenham's midpoint circle algorithm
public IEnumerable<ICell> GetBorderCellsInCircle( int xCenter, int yCenter, int radius )

Weighted Goal Maps

Set multiple goals weights for desirability. Add obstacles to avoid.

Weighted Goal Maps

/// Constructs a new instance of a GoalMap for the specified Map 
/// that will consider diagonal movements to be valid if allowDiagonalMovement is set to true.
public GoalMap( IMap map, bool allowDiagonalMovement )

/// Add a Goal at the specified location with the specified weight
public void AddGoal( int x, int y, int weight )

/// Add an Obstacle at the specified location. Any paths found must not go through Obstacles
public void AddObstacle( int x, int y )

Field-of-View

Efficient field-of-view calulation for specified distance. Option to light walls or not.

Field of View

/// Constructs a new FieldOfView objec for the specified Map
public FieldOfView( IMap map )

/// Performs a field-of-view calculation with the specified parameters.
public ReadOnlyCollection<ICell> ComputeFov( int xOrigin, int yOrigin, int radius, bool lightWalls )

/// Performs a field-of-view calculation with the specified parameters
/// and appends it any existing field-of-view calculations.
public ReadOnlyCollection<ICell> AppendFov( int xOrigin, int yOrigin, int radius, bool lightWalls )

Creating a Map

Most interactions with RogueSharp is based around the concept of a Map which is a rectangular grid of Cells.

Each Cell in a Map has the following properties:

  • IsTransparent: true if visibility extends through the Cell.
  • IsWalkable: true if a the Cell may be traversed by the player
  • IsExplored: true if the player has ever had line-of-sight to the Cell
  • IsInFov: true if the Cell is currently in the player's field-of-view

To instantiate a new Map you can use its constructor which takes a width and height and will create a new map of those dimensions with the properties of all Cells set to false.

Usage

IMap boringMapOfSolidStone = new Map( 5, 3 );
Console.WriteLine( boringMapOfSolidStone.ToString() );

Output

#####
#####
#####

Notice that the ToString() operator is overridden on the Map class to provide a simple visual representation of the map. An optional bool parameter can be provided to ToString() to indicate if you want to use the field-of-view or not. If the parameter is not given it defaults to false.

The symbols used are as follows:

  • %: Cell is not in field-of-view
  • .: Cell is transparent, walkable, and in field-of-view
  • s: Cell is walkable and in field-of-view (but not transparent)
  • o: Cell is transparent and in field-of-view (but not walkable)
  • #: Cell is in field-of-view (but not transparent or walkable)

A more interesting way to create a map is to use the Map class's static method Create which takes an IMapCreationStrategy. Some simple classes implementing IMapCreationStrategy are provided with RogueSharp but this is easily extended by creating your own class that implements the strategy.

Usage

IMapCreationStrategy<Map> mapCreationStrategy = new RandomRoomsMapCreationStrategy<Map>( 17, 10, 30, 5, 3 )
IMap somewhatInterestingMap = Map.Create( mapCreationStrategy );
Console.WriteLine( somewhatInterestingMap.ToString() );

Output

#################
#################
##...#######...##
##.............##
###.###....#...##
###...##.#####.##
###...##...###..#
####............#
##############..#
#################

Credits

License

RogueSharp

MIT License

Copyright (c) 2014 - 2023 Faron Bracy

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Other Licenses

See links to licenses in the credits for respective libraries

roguesharp's People

Contributors

aodendaal avatar cstrachan88 avatar faronbracy avatar flend avatar james0x0a avatar jannef avatar mattiascibien avatar stilgarisca avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

roguesharp's Issues

3D / Layer support?

Any plans on adding a third dimension with pathing information?

  • First of all having the option to add layers allows apply the logics to up/down too.
  • Secondly with a proper pathing information and algorythm one could implement either flying things (free vertical movement) or grounded pathing (only transition between layers on special transition cells).

DijkstraShortestPath Check method should be used or removed

The DijkstraShortestPath class has a Check method that is currently only used by unit tests.
https://github.com/FaronBracy/RogueSharp/blob/master/RogueSharp/Algorithms/DijkstraShortestPath.cs#L153

It was originally intended to be a private method and called from the bottom of the constructor.

Investigate if this method is useful or not. If it's not get rid of it. If it is useful consider making it private and make the class use it where appropriate.

Consider unsealing the Point class

Edit: I guess I should say "convert from struct to class". My editor said it was "sealed" but I checked the code and it's a struct. Maybe you have compelling perf reasons to keep it a struct.

I was very surprised that I couldn't subclass the Point class. I know I can use composition instead. I'm using an ECS pattern where components implement an IComponent interface (for serialization). Some of the components are just points with a different name. LocationComponent and DestinationComponent for example. It would be a lot cleaner for them to inherit point so I can do things like subtract them.

var delta = location - destination
entity.AddComponent(delta);

V.S.

var delta = location.point - destination.point
var deltaComponent = new DeltaComponent(){point = delta};
entity.AddComponent(deltaComponent)

Consider adding a way to override the behavior of FieldOfView

Currently the existing behavior of FoV creates a diagonal pattern rather than a circular pattern FoV. I was going to try to override the behavior of FoV, but there's no way to do so because of how tightly bound and hidden the logic is in Map & Cell. I saw a similar issue posted on the old Bitbucket site. Also saw your post here: https://roguesharp.wordpress.com/2017/04/25/roguesharp-4-0-pre-release/ but that won't allow us to overwrite the behavior of Cell.IsInFov.

Map class should have custom Indexer to get Cells

If the Map class had a custom indexer it would allow us to call Map[X,Y] to get a cell at an X,Y coordinate.

I have received feedback that this would be slightly nicer than calling Map.GetCell( X, Y ) as is available now.

消耗内存巨大

一个400*400的地图寻路一次消耗1-2M 内存。同时多个怪物寻路导致内存不足,大概在1小时后。需要调用GC.Collect(); 才能回收内存。

Consider targeting .NET Standard 2

RogueSharp currently multi-targets .NET Standard 1.0 and .NET Framework 4.0.

Consider bumping this up to .NET Standard 2.0.

Pros

  • Additional features available to make development more pleasant
  • Unity now supports .NET Standard 2.0

Cons

  • Platforms that don't support .NET Standard 2.0 but that did support 1.0 will no longer be able to use the latest version of RogueSharp

Methods that return IEnumerable<T> should be consistent with yields

DijkstraShortestPath.PathTo method returns an IEnumerable and could yield return DirectedEdge.
https://github.com/FaronBracy/RogueSharp/blob/master/RogueSharp/Algorithms/DijkstraShortestPath.cs#L130

Currently it does not, yet many other methods in the solution that return IEnumerable do.
https://github.com/FaronBracy/RogueSharp/blob/master/RogueSharp/Map.cs#L293

Investigate which approach is better and be consistent within the project.

GetCell should be virtual and generic

Currently the GetCell method of Map returns a concrete Cell class. While you can inherit Map and implement your own features, there's no way to stuff your implementation of the ICell interface into your implementation of Map as the GetCell method always returns a concrete type of Cell.

To be able to have your own ICell implementations maybe Map needs a generic or something (similar to IMapCreationStrategy) or GetCell should be virtual with GetCell where T is ICell.

Map.Clone should return the same type and not base type of Map

Im subclassing the Map class and using the CaveMapCreationStrategy, during the point of CellularAutomataBigAreaAlgorithm the map is cloned and cast as the type specified in the IMapCreationStrategy interface. however this clone returns null and throws a null reference exception.

I think the clone method should create a new T() rather than a new Map()

For example, this will throw the error:

public class CavesMap : Map
{
}

void Test()
{
CaveMapCreationStrategy<CavesMap> strategy = new CaveMapCreationStrategy<CavesMap>(width, height, 40, 4, 3);

CavesMap map = strategy.CreateMap();
}



Methods that return paths should be consistent with inclusion of source and destination

The DepthFirstPaths class has a PathTo method that returns a list of vertices from source to destination
https://github.com/FaronBracy/RogueSharp/blob/master/RogueSharp/PathFinder.cs#L100
The source vertex is not included in the list.

This behavior is different from the PathFinder class's ShortestPath method which does include the source cell.
https://github.com/FaronBracy/RogueSharp/blob/master/RogueSharp/PathFinder.cs#L100

The behavior should be consistent across all methods that return paths

Get border cell methods on map class include the center point when near the edge of the map.

Steps to reproduce:

  1. Create a new map of any size
  2. Call the map.GetBorderCellsInSquare(x: 0, y: 0, distance: 1) method with the given parameters

Expected results:
Since we are in the corner of the map and choose a distance of 1, the border cells returned in the list should be only the following three cells: {1,0},{1,1},{0,1}

Actual results:
Besides the three cells stated above, the center cell from which the border selection began is also in the list. {0,0}

v5.0 upgrade guide

Seems there's a lot of changes to v5.0 that I took a look at but it broke most of my code and I can't find alternative ways to figure out the way to move forward, so I have to go back to the last release until either I write my own functions to replace the old missing ones or figure out how to migration v4 RogueSharp to v5. Would like to see some documentation on how to do this.

Specifically here's a few things that break in v5 that I don't see a clear path to fix:

  • ComputeFov is no longer in the Map class. I know there's a FieldOfView class but it doesn't seem to be used anywhere. I think you're supposed to use the FieldOfView class on the fly and pass the Map in and use it's ComputeFov from it?
  • Cells no longer have a value for if they're explored or not (IsExplored) so do we have to keep track of this ourselves in our own Cell implementations?

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.