fixed values for property c# - c#

I have an Movement class as a property for my objects.
What I want to do is only be able to set determined values for this property, ex:
class Movement
{
public Direction Moving;
public Direction Facing;
}
Movement movement = new Movement():
movement.Moving = Direction.Up;
movement.Facing = Direction.Down;
I could make Direction.Up/Down/Left/Right constant strings, but i dont want to be able to set anything that's not Direction.Up/Down/Left/Right' to the property.
but i don't know how to make the Direction class.

One way is to use an Enum
public enum Direction
{
Up,
Down,
Left,
Right
}
Then if you need to make sure the stored int value is a valid value for your enum: Is there a way to check if int is legal enum in C#?

You can use an enum and use it like this:
public enum Direction {
1 = Up,
2 = Right,
3 = Down,
4 = Left
}
public class UseDirection {
public Direction Dir { public get; private set; }
public void SetDirection(Direction dir) {
Dir = dir;
}
}
However, now if you want to do some manipulations on Directions, or do some calculation, you cannot implement it in Direction since it is an enum.
You could also make an abstract class Direction, and make the actual directions derive from Direction, like this:
public abstract class Direction {
private class DirectionUp : Direction { }
private class DirectionDown : Direction { }
private class DirectionLeft : Direction { }
private class DirectionRight : Direction { }
public static Direction Up => new DirectionUp();
public static Direction Down => new DirectionDown();
public static Direction Left => new DirectionLeft();
public static Direction Right => new DirectionRight();
}
Now you can use Direction like this:
public class AggregatesDirection {
public Direction Dir { public get; private set; }
public AggregatesDirection() {
Dir = Direction.Up; //uses the static property in Direction that will use the private constructor of the private class in Direction.
}
}
This pattern is nice, because you can now just use the Direction interface to do all the stuff relevant to direction, and still have different implementations for when you would, say, relocate something for a given direction in the different direction classes.
You could also just make the classes public and outside of the abstract Direction class, but you would expose the types to the namespace then, which is probably not necessary.

i figured it out, here's what did the trick for me:
public class Direction
{
private string value;
private Direction(string value)
{
switch (value)
{
case "left":
{
this.value = value;
break;
}
case "right":
{
this.value = value;
break;
}
case "up":
{
this.value = value;
break;
}
case "down":
{
this.value = value;
break;
}
default:
throw new Exception("Valor invalido");
}
}
public static class Directions
{
public static Direction Up = new Direction("up");
public static Direction Down = new Direction("down");
public static Direction Left = new Direction("left");
public static Direction Right = new Direction("right");
}
}
i put the class 'Direction' as public, but it constructor as private, so it can only be instantiated inside itself and its child's, and then made the static class 'Directions' inside it.
so i can easily:
this.directionMoving = Direction.Directions.Down;
this.directionLooking = Direction.Directions.Down;
anywhere in my code, but can't:
Direction move = new Direction();
because it's constructor is only accessible inside itself.

Related

Why isn't the value of class member changing?

Im fairly new to programming and am making a rpg battle simulator for practice. My problem is that I can't seem to make my attack method work. Heres the classes I have:
class Person
{
protected int attack;
protected int health;
public Person(int _attack, int _health)
{
attack = _attack;
health = _health;
}
public int GetAttack()
{
return attack;
}
public int GetHealth()
{
return health;
}
public int Attack(int _health)
{
_health -= attack;
return _health;
}
}
class Hero : Person
{
public Hero(int _attack, int _health)
:base (_attack , _health)
{
}
}
class Enemy : Person
{
public Enemy(int _attack, int _health)
:base (_attack , _health)
{
}
}
and heres the main:
class Program
{
static void Main(string[] args)
{
Hero Joe = new Hero(4, 10);
Enemy Tim = new Enemy(5, 20);
Joe.Attack(Tim.GetHealth());
Console.WriteLine(Tim.GetHealth());
Console.WriteLine(Tim.GetAttack());
Console.ReadLine();
}
}
My guess is that the attack method is doing the math, but is never changing the health that is passed into it. Or maybe it has something to do with the fact that their protected. Another thought of mine is that it doesn't need to return anything.
How would I go about making my attack method work? I just want it to take in somethings health value, subtract the attacking things attack value, and save the calculated value as the health? Thank you for reading this !
When you pass around an int, you are making copies of the number, not passing references to the same number in memory.
When you pass around an instance of a class, you are passing around references to the same object in memory.
Therefore, I suggest changing your design to something like this:
public void Attack(Person target)
{
target.health -= this.attack;
}
...
Joe.Attack(Jim);
You got a couple things you can improve here. First thing is naming conventions, I recommend reading the design guidelines.
First, If you change your Attack and Health to properties instead of protected fields, you expose getter and setter methods for it. Obviously you only want to set form the controller so make the set a private set:
public class Person
{
public int Attack { get; private set; }
public int Health { get; private set; }
public Person(int attack, int health)
{
Attack = attack;
Health = health;
}
// Rest of code
}
When you do it like this you eliminate the need for your individual GetAttack() and GetHealth() methods.
Next, the names of your parameter in Attack() is misleading. I assume you want the parameter to be "attack" and not "health" right? Since our setter is private this method allows us to only access health modifications inside the class. Since we already changed Health to be a property, we don't need to return it anymore so this method can now be void:
//Our property is named Attack so this has to be AttackAction or something different
public void AttackAction(int attack)
{
Health -= attack;
}
And if we put it all together:
public class Person
{
public int Attack { get; private set; }
public int Health { get; private set; }
public Person(int attack, int health)
{
Attack = attack;
Health = health;
}
public void AttackAction(int attack)
{
Health -= attack;
}
}
public class Hero : Person
{
public Hero(int attack, int health)
:base (attack , health)
{
}
}
public class Enemy : Person
{
public Enemy(int attack, int health)
:base (attack , health)
{
}
}
I made a fiddle here that shows this new code in action.
You are calling Attack() but are never saving the value returned by that method. You need to add a Setter for the health field, then set that value to the method's returned value. Something like
Health Property
public int Health
{
get { return health; }
set { health = value; }
}
Setting the Value
Tim.Health = Joe.Attack(Tim.Health);
If you want to keep the design pattern the same (you don't, see Blorgbeard's answer) you could add a SetHealth() method to Person and do something like this:
Tim.SetHealth(Joe.Attack(Tim.GetHealth());
This gets Tim's health total, passes that to Joe's attack method, which returns a value (what Tim's new health total should be) and then Tim's health is set to this value.

How to use an enum to choose between multiple script option using c#

Here is the code I am using:
public enum TargetingOptions
{
NoTarget,
AllCreatures,
EnemyCreatures,
YourCreatures,
AllCharacters,
EnemyCharacters,
YourCharacters
}
public enum Faction
{
Fog,
Imperial,
Monster,
Pirate
}
public class CardAsset : ScriptableObject
{
public CharacterAsset characterAsset;
[TextArea(2, 3)]
public string Description;
public Sprite CardImage;
public int ManaCost;
[Header("Faction")]
public Faction faction;
[Header("Creature Info")]
public int MaxHealth;
public int Attack;
public int AttacksForOneTurn = 1;
public bool Charge;
public string CreatureScriptName;
public int specialCreatureAmount;
[Header("SpellInfo")]
public string SpellScriptName;
public int specialSpellAmount;
public TargetingOptions Targets;
}
what I am trying to do is create a different "hand" of cards depending on faction. to do this I have created a separate "hand" script for each of the factions, but I want to create a "handmultiple" script that will choose which "hand faction" script to head to.
So if in unity "pirate" is chosen, then all that will appear would be the associated scripts (ignoring fog, imperial and pirate scripts)
Does that make sense?
thank you!
enter code here using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
public class HandVisualImperial : MonoBehaviour
{
public AreaPosition owner;
public bool TakeCardsOpenly = true;
public SameDistanceChildren slots;
[Header("Transform References")]
public Transform DrawPreviewSpot;
public Transform DeckTransform;
public Transform OtherCardDrawSourceTransform;
public Transform PlayPreviewSpot;
private List<GameObject> CardsInHand = new List<GameObject>();
public void AddCard(GameObject card)
{
CardsInHand.Insert(0, card);
card.transform.SetParent(slots.transform);
PlaceCardsOnNewSlots();
UpdatePlacementOfSlots();
}
public void RemoveCard(GameObject card)
{
CardsInHand.Remove(card);
PlaceCardsOnNewSlots();
UpdatePlacementOfSlots();
}
So I think I have it figured out:
Have a whole bunch more work to do before testing it unfortunately.. but I believe I have it done now... Thank you all for the help!!!
public class HandVisualMultiple : MonoBehaviour
{
Faction factiontype;
public HandVisualFog fog;
public HandVisualImperial imperial;
public HandVisualMonster monster;
public HandVisualPirate pirate;
void Start()
{
fog = GetComponent<HandVisualFog>();
imperial = GetComponent<HandVisualImperial>();
monster = GetComponent<HandVisualMonster>();
pirate = GetComponent<HandVisualPirate>();
if (factiontype == Faction.Fog)
{
fog.enabled = true;
imperial.enabled = false;
monster.enabled = false;
pirate.enabled = false;
}
else if (factiontype == Faction.Imperial)
{
fog.enabled = false;
imperial.enabled = true;
monster.enabled = false;
pirate.enabled = false;
}
else if (factiontype == Faction.Monster)
{
fog.enabled = false;
imperial.enabled = false;
monster.enabled = true;
pirate.enabled = false;
}
else if (factiontype == Faction.Pirate)
{
fog.enabled = false;
imperial.enabled = false;
monster.enabled = false;
pirate.enabled = true;
}
}
}
It's not the answer for your question, but an experienced game developer advice.
Try to use Polimorfism. A single main class. "class Creature" and then a lot of child classes class ImperialCreature:Creature, class PirateCreature:Creature and then set the parameters to each of them.
And later you can set another sub classes. for instance: class JackSparrow:PirateCreature ... and on...
The enum is similar to an array, so if you do (int)Faction.Fog it will return 0 since it's the first item. You could have an array or list with your scripts in the same order as your enum and call them by casting the enum to an int

how to get an enum from another script in unity

I am trying to create a win condition script pulling the status of an enum from a different script and then do stuff with it.
crowd.cs
public enum crowdOptions {None, TeamA, TeamB};
public crowdOptions Crowd;
Crowd = crowdOption.None;
I have the crowd doing a bunch of stuff, but lets say it is set to none.
winning.cs
if (Crowd = crowdOption.None){
do something
} else if (Crowd = crowdOption.TeamA){
do something
} else {
do something
}
I tried a GetComponent and set the result of of Crowd to a newvariable, but I don't think I did that right
public CrowdSway = GameObject.Find("crowdManager").GetComponent<CrowdManager>();
I also tried
if (CrowdManager.Crowd = crowdOptions.None) {
print("none");
} else {
print("hmmmmmm");
}
that didn't work either.
In order to access the Crowd enum variable in your crowd.cs class from another script, that script needs to have an instance of a Crowd object. For example:
public class Crowd : MonoBehaviour
{
public enum crowdOptions {None, TeamA, TeamB};
public crowdOptions crowdOpts;
}
public class Winning : MonoBehaviour
{
void Start()
{
Crowd myCrowd = new Crowd();
if(myCrowd.crowdOpts == crowdOptions.None)
{
//do something
}
}
}
Alternatively, you could also make your crowdOptions enum variable static. Then you can access it from any script by name.
public class Crowd : MonoBehaviour
{
public enum crowdOptions {None, TeamA, TeamB};
public static crowdOptions CrowdOptions;
}
public class Winning : MonoBehaviour
{
void Start()
{
if(CrowdOptions == Crowd.crowdOptions.None)
{
//do something
}
}
}

C# Access Struct using String

I am a bit stuck with my game. I have a class called Upgradebuttons. From this class I want to access some variables stored in a struct from another class. I can easily access the variables by typing classname.structname.preferedvar but the structname depends on which upgrade as been clicked. So I want to call the struct using a string. I have tried:
MethodInfo method = typeof(Classname).GetMethod(structname);
But this only works if it is a void and not a struct. What do I need to do in order to get this working?
public class UpgradeButtons : MonoBehaviour {
public void somefunction{
// here i want to have access
}
}
This is an example of the class I want to have access to:
public class Upgrades: MonoBehaviour {
public struct Upgrade1{
public const int Cost = 10;
public const float Value = 0.1f;
public static string Naam = "Autoclicker";
}
}
While this is possible, it sounds like poorly thought out design. Perhaps you could use one common struct Upgrade and use the Name property to find it at runtime?
Example:
public struct Upgrade
{
public string Name;
public int Cost;
public float Value;
public Upgrade(string name, int cost, float value)
{
this.Name = name;
this.Cost = cost;
this.Value = value;
}
}
public class UpgradeButtons : MonoBehavior
{
List<Upgrade> Upgrades = new List<Upgrade>();
public void CreateButtons()
{
Upgrades.Add(new Upgrade("Autoclicker", 10, 0.1f));
//etc...
}
public void somefunction()
{
Upgrade autoclickUpgrade = Upgrades.Where(p => p.Name == "Autoclicker").FirstOrDefault();
if(autoclickUpgrade == null)
throw new Exception("Could not find Autoclicker upgrade.");
//do something with autoclickUpgrade
}
}
just remove static from string Naam:
public class Upgrades: MonoBehaviour {
public struct Upgrade1{
public const int Cost = 10;
public const float Value = 0.1f;
public string Naam = "Autoclicker";
}
}
When an object ( class, variable, method) is defined as static it can not be referenced through an instance.
If I understand your question, you are on the right track, probably. Since the struct (type) that your add-on depends on may or may not exist, Reflection is the best way to go here.
Try Assembly.GetType(), or a related method, to attempt to load the type, check its existence, and iterate its members.
http://msdn.microsoft.com/en-us/library/y0cd10tb(v=vs.110).aspx

Utilising interfaces for polymorphism in C#

By way of an intro, I'm creating a basic Quadtree engine for personal learning purposes. I'm wanting this engine to have the capability of working with many different types of shapes (at the moment I'm going with circles and squares) that will all move around in a window and perform some sort of action when collision occurs.
After asking a question on the topic of generic lists earlier, I have decided on using an interface for polymorphism. The best interface for this would be an interface utilising Vector2 due to the fact that every object that appears in my Quadtree will have an x,y position and Vector2 covers that nicely. Here is my code as it currently stands:
public interface ISpatialNode {
Vector2 position { get; set; }
}
public class QShape {
public string colour { get; set; }
}
public class QCircle : QShape, ISpatialNode {
public int radius;
public Vector2 position {
get { return position; }
set { position = value; }
}
public QCircle(int theRadius, float theX, float theY, string theColour) {
this.radius = theRadius;
this.position = new Vector2(theX, theY);
this.colour = theColour;
}
}
public class QSquare : QShape, ISpatialNode {
public int sideLength;
public Vector2 position {
get { return position; }
set { position = value; }
}
public QSquare(int theSideLength, float theX, float theY, string theColour) {
this.sideLength = theSideLength;
this.position = new Vector2(theX, theY);
this.colour = theColour;
}
}
So I'll be eventually wanting to have an interface that works to the point that I can use the generic list List<ISpatialNode> QObjectList = new List<ISpatialNode>(); and I can add shapes to it using the code QObjectList.Add(new QCircle(50, 400, 300, "Red")); or QObjectList.Add(new QSquare(100, 400, 300, "Blue")); or something along those lines (keep in mind that I'll be wanting to add different shapes later along the line).
Problem is, this code doesn't seem to work when I call it from here (Initialize() is the XNA method):
protected override void Initialize() {
QObjectList.Add(new QCircle(5, 10, 10, "Red"));
base.Initialize();
}
So my question has two parts:
1. Why does this code give me a stackoverflow error at the set {
position = value; } part of my QCircle and QSquare classes?
2. Would this be an efficient/effective way of utilising interfaces for
polymorphism?
The problem is in your property it is setting itself in circular loop
public Vector2 position { get ; set ; }
Or declare a private field
private Vector2 _position;
public Vector2 position {
get { return _position; }
set { _position = value; }
}
Stack overflow is because:
public Vector2 position {
get { return position; }
set { position = value; }
}
the set actually sets the same again. You may want this:
private Vector2 _position;
public Vector2 position {
get { return _position; }
set { _position = value; }
}
or its short version:
public Vector2 position { get; set; } //BTW, the c# standard is to use upper camel case property names
Regarding the use of polymorphism, it seems right in this scenario.

Categories

Resources