With Statement in C# like that of AS3/GML - c#

I'm making a game using Monogame, and I've been trying to figure out how to implement a function that acts similarly to AS3's and GML's with statement.
So far I have a system that works, but not entirely the way I want it to. I store my GameObjects in a Dictionary of Lists. This is so I can get to the specific type of object I want to access without having to loop through a list of ALL objects. The key used is the name of the type.
public static Dictionary<string, List<GameObject>> All =
new Dictionary<string, List<GameObject>>();
I access all of a specific type of object using AllOf. If a List containing that type exists in the Dictionary, it returns that List, else it returns an empty list.
public static List<GameObject> AllOf(Type type)
{
string key = type.Name;
if(All.ContainsKey(key))
{
return All[key];
}
return new List<GameObject>();
}
An example of how these are implemented
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
}
}
But I'd rather use something similar to the AS3/GML with statement, which would also allow for other, non-member codes to be executed.
with(typeof(Dummy))
{
Update(gameTime);
foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
Is there a way to accomplish this? My end goal is just to make my code look a little cleaner, and make it easier to make a lot of changes without having to type out a for loop each time.

No such syntax exists in C#, but you can access methods within the for that have nothing to do with the collection:
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
}
Note that you can also use foreach, which is a little cleaner if you don't need the indexer:
foreach(var item in list)
{
item.Update(gameTime);
item.foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}

try
using(Object myObject = new Object()){
}
i think this might be what your looking to use?

I have a small solution for this use case. This may be a bit of a necropost, but it is a pretty neat solution. Additionally, I think all of the C# features that are required existed back when this question was asked.
You can do something very similar to the GML with(x){} by using some form of delegate as a parameter to a static method, and passing a lambda as that parameter. The function can even be genericised, and you can call it without the class name by the using static statement. You will need to explicitly provide the typed/named parameter, but it is possible. You would need to hook it up to your own types, but the general idea is:
namespace NiftyStuff {
public static class With {
public static void with<T>(Action<T> proc) where T : GameObj {
var typeName = typeof(T).Name;
foreach (var item in GameObj.AllOf(typeName)) { proc((T)item); }
}
}
public class GameObj {
private static Dictionary<string, List<GameObj>> All = new Dictionary<string, List<GameObj>>();
public static List<GameObj> AllOf(string name) {
return All.ContainsKey(name) ? All[name] : null;
}
public static void Add(GameObj foo) {
string typeName = foo.GetType().Name;
List<GameObj> foos = All.ContainsKey(typeName) ? All[typeName] : (All[typeName] = new List<GameObj>());
foos.Add(foo);
}
public float x, y, angle;
public GameObj() { x = y = angle = 0; }
public void Destroy() { AllOf(GetType().Name)?.Remove(this); }
}
public class Enemy : GameObj {
public float maxHealth, curHealth;
public Enemy() : base() { maxHealth = curHealth = 300; }
public Enemy(float health) : base() { maxHealth = curHealth = health; }
public bool Damage(float amt) {
if (curHealth > 0) {
curHealth -= amt;
return curHealth <= 0;
}
return false;
}
}
public class Pumpkin : GameObj {
public bool exists = false;
public Pumpkin() : base() { exists = true; }
public bool LookAt() { return (exists = !exists); }
}
}
Actually using the above code would work as follows:
using NiftyStuff;
using static NiftyStuff.With;
//...
with ((Enemy e) => {
if (e.Damage(50)) {
Log("Made a kill!"); // Whatever log function you have...
}
});
with ((Pumpkin p) => {
if (p.LookAt()) {
Log("You see the pumpkin");
} else {
Log("You no longer see the pumpkin");
}
});
While not exactly like GML's with statement, it would at least let you run code against all of the registered objects of some type.
One important note is that you can't destroy objects inside of a with this way (due to concurrent modification of a collection while iterating it). You would need to collect all objects to be destroyed, and then remove them from the list in All, typically in a game loop this is done at the end of a frame.
Hope this helps, despite being 2 years out of date.

Related

Struggling with how methods and classes interact

I'm new to learning C# and am trying to implement the below code however, I am unable to do so, receiving the error "A namespace cannot directly contain members such as fields or methods".
namespace Grades
{
public string LetterGrade
{
get
{
string result;
if (RoundResult(AverageGrade) >= 90)
{
result = "A";
}
else if (RoundResult(AverageGrade) >= 80)
{
result = "B";
}
else if (RoundResult(AverageGrade) >= 70)
{
result = "C";
}
else
{
result = "F";
}
return result;
}
}
private double RoundResult(double result)
{
double r;
r = Math.Round(result);
return r;
}
public class GradeStatistics
{
public float AverageGrade = 50;
public float HighestGrade = 78;
public float LowestGrade = 11;
}
}
What I am trying to accomplish is to create a method called "RoundResult" which will round the "AverageGrade" result. I am merely doing this as an experiment to try and understand how methods interact with each other.
The biggest hurdle I am facing while learning C# is in regards to methods and classes, how to use them correctly, when to place them within an existing class or create there own separate class etc. If someone has any recommended resource that goes into extensive step by step detail on how to implement methods and classes, that would be greatly appreciated.
Edit: Thanks to Reputation Farmer and wazdev for their answers. I'd like to add an additional question....
Why is the "GradeStatistic" method a valid method to call the "AverageGrade" from within the same class yet my "RoundResult" method can not be within the same class?
This error message is occurring because you have two methods directly inside your namespace declaration- they need to be wrapped inside a class.
One possible solution is to create a "GradeCalculator" class and put your two methods inside that ... please note that this is not an optimal solution, but I've tried to modify as little as posssible:
namespace Grades
{
public class GradeCalculator
{
public string LetterGrade
{
get
{
string result;
if (RoundResult(GradeStatistics.AverageGrade) >= 90)
{
result = "A";
}
else if (RoundResult(GradeStatistics.AverageGrade) >= 80)
{
result = "B";
}
else if (RoundResult(GradeStatistics.AverageGrade) >= 70)
{
result = "C";
}
else
{
result = "F";
}
return result;
}
}
private double RoundResult(double result)
{
double r;
r = Math.Round(result);
return r;
}
}
public static class GradeStatistics
{
public static float AverageGrade = 50;
public static float HighestGrade = 78;
public static float LowestGrade = 11;
}
}
As the error says, namespace can't contain methods. You should put them inside a class:
namespace Grades
{
public static class GradeUtil {
public static string LetterGrade { ... }
private static double RoundResult(double result) { ... }
}
public class GradeStatistics
{
public float AverageGrade = 50;
public float HighestGrade = 78;
public float LowestGrade = 11;
}
}
Note the word static. It allows you to call a method without object instance. I.e. you can write GradeUtil.LetterGrade .... It's unclear, cut looks like this is what you intended.

C# Mock a Class With an Internal Property Setter

I am trying to build a unit test.
The class Position is implemented in a third party library. But for my unit test I need the Size property to be set to a specific value.
public class Position
{
private double _size;
private double Size
{
get
{
return _size;
}
internal set
{
_size = value;
}
}
}
I read this post: How do you create a unit-testing stub for an interface containing a read-only member?
but could not figure out how to make it work for me.
This is the class under test (just a simplified example). The posargument in the CalcPositionMetric() method must be of type Position:
public class PositionMetrics
{
public PositionMetrics()
{}
public double CalcPositionMetric(Position pos)
{
return 2 * pos.Size;
}
}
Here is a piece of my unit test:
using NUnit.Framework;
using NMock;
[TestFixture]
public class PositionUnitTests
{
[Test]
public void TestPosition()
{
Mock<Position> tmpPosMock = mFactory.CreateMock<Position>();
tmpPosMock.Expects.One.GetProperty(v => v.Size).WillReturn(7); /* !!! Exception !!! System.ArgumentException : mock object position has a getter for property Size, but it is not virtual or abstract */
/* Execute Test with tmpPositions*/
PositionMetrics pm = new PositionMetrics();
double result = pm.CalcPositionMetric(tmpPosMock.MockObject)
Assert.AreEqual(14, result);
}
}
But as you can see I get an exception. Could somebody help me to resolve this problem? Any other solutions are also welcome!
Cheers
Konstantin
New answer for the updated question I suggest you to introduce some kind of a proxy interface for that. See the code below:
interface IPosition {
int Size { get; }
}
class Position { //in 3rd party lib
public int Size {
get { return 5; }
}
}
class RealPosition : IPosition { //use this as your real object instead of using Position directly
private Position position;
public RealPosition(Position position) {
this.position = position;
}
public int Size {
get { return position.Size; }
}
}
class MockPosition : IPosition { //use this for testing
public int Size{ get; set; }
}
public class Program {
static void Main(string[] args) {
var pos = new MockPosition { Size = 7 };
Console.WriteLine(Calc(pos)); //prints 14
Console.ReadLine();
}
static int Calc(IPosition pos) { //change your method signature to work with interface
return pos.Size * 2;
}
}
Old answer If the class is not sealed you don't need any mocking libraries. Just use the new modifier for the required properties like this:
class Position {
public int Size { get { return 5; } }
}
class MockPosition : Position {
public new int Size { get; set; }
}
....
var mock= new MockPosition();
mock.Size = 7;
To use these items in some sort of list you'll have to cast them like this:
var items = new List<Position>();
for (int i = 0; i < 5; i++) {
items.Add(new MockPosition { Size = i });
}
foreach (var item in items.Cast<MockPosition>()) {
Console.Write("{0}\t", item.Size); //prints 0 1 2 3 4
}
If it is sealed and the property is not virtual than you'll have to use some other techniques, Moq (which I guess you are using) does not allow that

C# is it possible to store like classes into a collection?

Tried to title my post as best I could, but here goes.
I have 5 classes for various "effect" animation stuff that can be done to an animation (alpha change, color change, position change, rotation change, scale change). They are all the same aside from variable types. They all use an abstract class for methods that could be shared between them all along with methods that are override in the derived classes.
I have a class that is for handling all the animations of a game object called AnimationHandler. What it does is store all the effect animations (along with the sprite animations) for my game's objects and handling them.
What I want to do is store all the effects into one dictionary that is then used to handle all changes to an animation for that object. I was wondering if it was possible to do or if it would be just easier to have 5 separate dictionaries to handle each effect separately?
The issue that I'm trying to figure out is how to access the variables that aren't in the abstract class.
Here is the sample code for my base class and a derived class:
abstract class EffectAnimation
{
protected EffectInfo Info;
public EffectInfo info
{
get
{ return Info; }
}
protected EffectType TypeOfEffect;
public EffectType typeofeffect
{
get
{ return TypeOfEffect; }
}
public abstract void NewAnimation();
public void Update(double time)
{
AnimationDone(time);
if (!info.Done)
{
if (UtilityAnimation.ReadyForNextFrame(time, Info.FrameLength))
{
Info.NextFrameTime = time + Info.FrameLength;
ChangeValue();
}
}
}
public void Start(double time)
{
Info.StartTime = time;
Info.NextFrameTime = time + Info.FrameLength;
}
public abstract void ChangeValue();
public abstract void Clamp();
protected abstract void AnimationDone(double time);
}
class AlphaAnimation : EffectAnimation
{
private float Change;
public float change
{
get
{ return Change; }
set
{ Change = value; }
}
private float End;
public float end
{
get
{ return End; }
set
{ End = value; }
}
private float Total;
public float total
{
get
{ return Total; }
set
{ Total = value; }
}
public void NewAnimation(EffectInfo stuff, float starting, float ending, float partialtotal)
{
Total = starting + partialtotal;
Info = stuff;
End = ending;
Info.Initialize();
Change = UtilityAnimation.MakeFadeAmount(stuff.AnimationLength, starting, ending, stuff.FPS);
}
public void ChangeValue()
{ Total += Change; }
private void Clamp()
{
if (Change > 0) // animation is positive
{
if (Total > End)
{
Total = End;
}
}
else // animation is negative
{
if (Total < End)
{
Total = End;
}
}
}
private void AnimationDone(double time)
{
Clamp();
if ((Total == End) && (time >= Info.DoneTime()))
{ Info.Done = true; }
}
}
What you ask for (accessing for instance change of AlphaAnimation via a reference of type EffectAnimation) is impossible without reflection or checking for the actual type. That being said, if possible, the design should be changed such that the desired effect of the animation can be triggered without knowing its type. This can be difficult depending on the case; in some cases it might make no sense altogether.
This is a possible solution;
List<EffectAnimation> animations = new List<EffectAnimation>();
animations.Add(new AlphaAnimation());
EffectAnimation item = animations[0];
if(item is AlphaAnimation)
{
AlphaAnimation alphaItem = item as AlphaAnimation;
float total = alphaItem.Total;
float change = alphaItem.Change;
}
This is basically just casting it to the right class and then you can easily access the properties you need. You can still add all your animations to the same list - just make sure to check if it is the right one when you take one out.

C# Stack not updating

For some reason the code that I modified doesn't seem to be functioning correctly. There were no exception error when debugging however it does not function the same as in the original code (list) - that is it doesn't seem to update. I've targeted it down to an area of code where I believe is causing the problem:
My original code (using List) that works:
private List<Gem> gems = new List<Gem>();
private List<Enemy> enemies = new List<Enemy>();
private void UpdateGems(GameTime gameTime)
{
for (int i = 0; i < gems.Count; ++i)
{
Gem gem = gems[i];
gem.Update(gameTime);
if (gem.BoundingCircle.Intersects(Player.BoundingRectangle))
{
gems.RemoveAt(i--);
OnGemCollected(gem, Player);
}
}
}
Here's my modified code replacing List to Stack which doesn't work correctly:
private Stack<Gem> gems = new Stack<Gem>();
private Stack<Enemy> enemies = new Stack<Enemy>();
private void UpdateGems(GameTime gameTime)
{
for (int i = 0; i < gems.Count; ++i)
{
Gem gem = gems.Peek();
gem.Update(gameTime);
if (gem.BoundingCircle.Equals(Player.BoundingRectangle))
{
gems.Pop();
OnGemCollected(gem, Player);
}
}
}
Any ideas?
I don't know exactly what you need, but the loop looks a little strange: if you don't pop() anything from the stack at the first turn, peek() will return the same element always.
Stack data structure is not indexed, it allow just to pop/peek the last pushed element. The code with the list behave of course different since you are actually checking all the elements in the list.
By definition, when you pop something off a stack you remove the last item added. Because of this you have reversed the order in which you are checking and removing Gem objects from the collection - when you do the Peek and Pop and BoundingCircle.Equals() check in the Stack<Gem> version you are not checking the first item in the collection like you are in the List<Gem> version.
A List can be iterated in either direction, just adjust your indexer in the appropriate way. A Stack is LIFO (Last In, First Out), so you can only access the last item added.
I think when called to peak method, it maybe keep a references to that item on the top of stack collection. So when you called to pop method. It gonna working not correctly.
I have copy your example and put to a console application as below
class Program
{
private static Stack<Gem> gems = new Stack<Gem>();
private Stack<Enemy> enemies = new Stack<Enemy>();
static void Main(string[] args)
{
gems.Push(new Gem
{
BoundingCircle = new BoundingCircle
{
Name = "abc"
}
});
gems.Push(new Gem
{
BoundingCircle = new BoundingCircle
{
Name = "def"
}
});
UpdateGems(new GameTime());
}
private static void UpdateGems(GameTime gameTime)
{
for (int i = 0; i < gems.Count; ++i)
{
Gem gem = gems.Peek();
gem.Update(gameTime);
if (gem.BoundingCircle.Equals(Player.BoundingRectangle))
{
gems.Pop();
OnGemCollected(gem, null);
}
}
}
private static void OnGemCollected(Gem gem, Player player)
{
}
}
public class Gem
{
public void Update(GameTime gameTime)
{
}
public BoundingCircle BoundingCircle { get; set; }
}
public class Enemy
{
}
public class GameTime
{
}
public class BoundingCircle : Bounding
{
public override bool Equals(object obj)
{
var temp = (Bounding) obj;
return Name.Equals(temp.Name, StringComparison.InvariantCulture);
}
}
public class Player
{
static Player()
{
BoundingRectangle = new BoundingRectangle
{
Name = "def"
};
}
public static BoundingRectangle BoundingRectangle { get; set; }
}
public class BoundingRectangle : Bounding
{
}
public abstract class Bounding
{
public string Name { get; set; }
}
It worked fine. Please notice that your Equals function have to be overridden by the BoundingCircle class.

Get an object out of a mixed type collection

Hi I'm new to OOP and I need help on a little problem.
I used a collection called Monsters to store 3 types of object. Spiders, Farmers, Gollum(irrelevant).
My collection as an indexer but when I use it to get an object out of the collection the object is typeless but I really need to TypeCast my next opperation.
private void Form1_Load(object sender, EventArgs e)
{
CurrentOpponent Opponent = new CurrentOpponent();
Gollum myGollum = new Gollum();
AngryFarmer myFarmer = new AngryFarmer();
Ugly_Spider mySpider = new Ugly_Spider();
myMonsters.AddGollum(myGollum);
myMonsters.AddFarmer(myFarmer);
myMonsters.AddUgly(mySpider);
progressBar1.Increment(100);
progressBar2.Increment(100);
Monster myCurrentOpponent = Opponent.randomEncounter();
//textBox1.Text = (this is where i need the type for a cast)myCurrentOpponent.name
}
Here is the randomEncounter where i extract the object
class CurrentOpponent
{
public Monster randomEncounter()
{
Random _random = new Random();
int opp = _random.Next(4);
return myMonsters[opp];
}
And finally the indexer wich returns a monster (parent of all 3 monster types)
public Monster this[int xxx]
{
get
{
return (Monster)List[xxx];
}
}
Help would be really appreciated..!!
Thanks in advance
Ideally, AngryFarmer, Ugly_Spider and Gollum should all inherit from Monster:
public class AngryFarmer : Monster
{
// ...
}
// etc.
You could then just use a List<Monster>:
myMonsters = new List<Monster>();
myMonsters.Add(new AngryFarmer()); // works because AngryFarmer is a kind of Monster
This will allow you to use polymorphism.
you need to use interfaces...... IMonster..... IMonster then has a name
then make all your monsters implement IMonster
and just have a List of IMonsters
you may wanna try it by using interfaces also! have a look...
public interface IMonster
{
String Name { get; }
Int32 Health { get; set; }
}
public class Spider : IMonster
{
public Spider()
{
_health = 100;
}
public string Name
{
get { return "Spider"; }
}
private int _health;
public int Health
{
get { return _health; }
set { _health = value; }
}
}
public class Gollum : IMonster
{
public Gollum()
{
_health = 250;
}
public string Name
{
get { return "Gollum"; }
}
private int _health;
public int Health
{
get { return _health; }
set { _health = value; }
}
}
class Program
{
static void Main(string[] args)
{
List<IMonster> monsters = new List<IMonster>()
{
new Gollum(),
new Spider()
};
IMonster randomMonster = GetRandomMonster(monsters);
Console.WriteLine(randomMonster.Name + "/" + randomMonster.Health);
}
private static IMonster GetRandomMonster(List<IMonster> monsters)
{
//Your code for getting a random monster goes here!
throw new NotImplementedException();
}
}
I like very much this approach... Imagine you have an element on your game that initially is not exactly a monster. Say it is a random element on your game that after a given event it becomes a monster that your Hero (say a game like heroes of mighty and magic) have to fight with. If you decided to add this feature long time after you created the game, it would become harmful/difficult/risky to change it, as this element might have already be inheriting from another class. If you were using interfaces you would simply implement it on this entity and it would promptly be capable of behaving like any other IMonster in your game. It means that this random entity would be able to be passed as a param to the method Fight(IHero hero, IMonster monster);
Ideally, AngryFarmer, Ugly_Spider and Gollum should all inherit
from Monster
I have learn your problem like the problem in the Tetris game:
1/ You have Monsters like I have Shapes.
2/ Each kind of Monster have it own properties (Health, Magic Point,...) and behaviours (attack, run, cast spell,..) like the Blocks have properties (color, position, state,..) and
behaviours (go down, rotate right, rotate left,...)
In the scene of the game you want to random a Monster that have the specific properties and behaviours, like I want to random a Shape. If it is your problem you can try my code:
public abstract class CMonster
{
int _HP;
int _MP;
//..and something like this
public int HP
{
get { return this._HP; }
set { this._HP=value;}
}
public int MP
{
get { return this._MP; }
set { this._MP = value; }
}
public abstract void Run();
public abstract void Attach();
public abstract void CastSpell();
}
public class CUgly_Spider : CMonster
{
public CUgly_Spider()
{
this.MP = 100;//your value here
this.HP = 100;//your value here
}
public override void Attach()
{
//your implemetation here
}
public override void Run()
{
//your implemetation here
}
public override void CastSpell()
{
//your implemetation here
}
}
public class CGollum : CMonster
{
public CGollum()
{
this.MP = 100;//your value here
this.HP = 100;//your value here
}
public override void Attach()
{
//your implemetation here
}
public override void Run()
{
//your implemetation here
}
public override void CastSpell()
{
//your implemetation here
}
}
class Test
{
private void InitTheGame()
{
CMonster curMonster=null;
Random rnd = new Random();
//sample random
if ((rnd.Next() % 2) == 0)
{
curMonster = new CGollum();
}
else
{
curMonster = new CUgly_Spider();
}
curMonster.Run();//when (rnd.Next() % 2) == 0 then the Gollum is doing else the Ugly_Spider
curMonster.Attach();//when (rnd.Next() % 2) == 0 then the Gollum is doing else the Ugly_Spider
curMonster.CastSpell();//when (rnd.Next() % 2) == 0 then the Gollum is doing else the Ugly_Spider
}
}
I hope that can help you.

Categories

Resources