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

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.

Related

Unity: Using multiple timers C#

I have multiple classes that use a countdown timer, but when I use more than one timer, the output returns the same value, not two separate values specific to their own class.
If I use one timer, everything works perfectly with no issues, it is literally just splitting those timers into separate timers.
I'm sure I have missed something simple here, but can't figure out why they are returning the same output.
Edit: clarity - mfCurrentTime and mfTimeTravelling return the same value, and they should return different values from each timer, but they are merging together as if there is only one timer.
They aren't acting like two separate timers, they are acting as if it is one timer
Edit 2: When used individually, both timers return different values, the correct values that they should be returning. It's only when both timers are running at the same time that the issue occurs.
for example:
mfCurrentTime will always return the current time elapsed as it is continually calling Countdown Update
mfTimeTravelling returns the time elapsed when the bool _mbIsTravelling is true.
When both classes are active, mfCurrentTime is correct, and when the bool is true for mbIsTravelling in the other class, it takes the time of mfCurrentTime. The issue is that they should be two completely separate timers, not one timer.
Edit 3: #Abion47's help lead to the discovery that everything is working as it should, I had just not included a flag for the update in the Update method. I was so fixed on the way I was calling Countdown being the issue, when the real error was a massive oversight on my behalf. I added a condition to the update, and everything is fine.
if(_mbIsTravelling)
{
mIsTravellinTimer.Update();
}
-
This class is using a Countdown timer.
public class Level_TimeTaken : MonoBehaviour
{
public EndOfLevelElement UIElement;
[HideInInspector]
public float mfCurrentTime;
[HideInInspector]
public string msTimeTaken;
private bool _mbLevelIsActive;
private Countdown mLevelTime = new Countdown(9999.0f);
void Start()
{
mLevelTime.Reset();
_mbLevelIsActive = true;
}
void Update()
{
mLevelTime.Update();
TimerRunning();
UIElement.GetTimeTaken(msTimeTaken);
}
private void TimerRunning()
{
if (_mbLevelIsActive)
{
mfCurrentTime = mLevelTime.GetTimeElapsed();
msTimeTaken = mfCurrentTime.ToString("#.00");
}
}
}
This class is also using a Countdown timer.
public class Level_DistanceTravelled : MonoBehaviour
{
public EndOfLevelElement UIElement;
[HideInInspector]
public float mfTimeTravelling;
[HideInInspector]
public string msDistanceTravelled;
private bool _mbIsTravelling;
private Countdown mIsTravellinTimer = new Countdown(6000.0f);
void Start()
{
mIsTravellinTimer.Reset();
}
void Update()
{
mIsTravellinTimer.Update();
DistanceTravelling();
UIElement.GetDistanceTravelled(msDistanceTravelled);
}
private void DistanceTravelling()
{
if (GMM.Instance.Input.ShouldLHorizontalKeyLeft() || GMM.Instance.Input.ShouldLHorizontalKeyRight() || GMM.Instance.Input.ShouldLHorizontalAxis() != 0.0f)
{
_mbIsTravelling = true;
}
else
{
_mbIsTravelling = false;
}
if (_mbIsTravelling)
{
// add math for working out distance so the string displays meters spooled
mfTimeTravelling = mIsTravellinTimer.GetTimeElapsed();
msDistanceTravelled = mfTimeTravelling.ToString("#.00");
}
}
}
and Countdown class, (a generic class for handling timers etc) is here
public class Countdown
{
private float _mfCountdownTime;
private float _mfCurrentTime;
public Countdown(float lfCountdownTime)
{
_mfCountdownTime = lfCountdownTime;
_mfCurrentTime = 0f;
}
public void Update()
{
Update(Time.deltaTime);
}
public void Update(float lfTimeStep)
{
_mfCurrentTime += lfTimeStep;
if (_mfCurrentTime > _mfCountdownTime)
{
_mfCurrentTime = _mfCountdownTime;
}
}
public bool IsComplete()
{
return _mfCurrentTime >= _mfCountdownTime;
}
public void SetComplete()
{
_mfCurrentTime = _mfCountdownTime;
}
public void Reset()
{
_mfCurrentTime = 0f;
}
public float GetTimeElapsed()
{
return _mfCurrentTime;
}
public float GetTimeRemaining()
{
return _mfCountdownTime - _mfCurrentTime;
}
public float GetProgress()
{
return Mathf.Clamp01(_mfCurrentTime / _mfCountdownTime);
}
}
Thanks
In both of your scripts, you are getting the value from GetTimeElapsed. This value is the amount of time that has passed since the Countdown had started, which if both Countdowns were started at the same time would give you the same number.
Perhaps you meant to call GetTimeRemaining, which returns a value that takes the total time given into account? Or maybe GetProgress?

With Statement in C# like that of AS3/GML

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.

Assign multiple values to one object(?)

Note: I am somewhat of a beginner to C#.
I'm working on a little game that will have a bunch of different levels. Each level has its own class that contains variables (and other irrelevant code). Since I need to pass these values to the main class (my form) I have made them all into methods that returns the value I want (since I can't come up with a better solution). example:
class Level01
{
public int Boxes() { return 3; }
public int MaxPoints() { return 46; }
public int Health() { return 63; }
public int[,] SolidBoxes()
{
int[,] position = new int[Boxes(), Boxes()];
position[1, 1] = 1;
return position;
}
}
When I access these values from my form class I do
int boxes;
int maxPoints;
int health;
int[,] solidBoxes;
void readLevelData() //Starts each new level
{
//Reads the correct level
switch (levelNo)
{
case 1:
setValues(Lvl01.Boxes(), Lvl01.MaxPoints(), Lvl01.Health(), Lvl01.SolidBoxes());
break;
//The same case 2:, 3: for Level02,03..
}
}
void setValues(int getBoxes, int getMaxPoints, int getHealth, int[,] getSolidBoxes)
{
boxes = getBoxes;
maxPoints = getMaxPoints;
health = getHealth;
solidBoxes = getSolidBoxes;
}
I am aware that there's probably a million things in my code here that can be done better and I gladly listen if you have any suggestions, but the thing I wish to ask is:
How can I get all the values from each class using maybe just one name? Ex. Instead doing as I do now, is there a way so I can do something similar to this:
case 1:
setValues(Lvl01.Values);
break;
The problem here is in the setValues method, some of the levels has quite a lot of settings that I wish to use, but I doubt the method would want to take like 15 parameters, and I'm not sure what to do when some levels are not using settings that other levels use.
How should I change my code so I do not have to use every single value as a parameter?
You could use a Dictionary<int, Level> to lookup the object representing each level. Instead of the switch/case, you would do something like
Level level = myLevelDictionary[currentLevel];
That requires you change your classes from having one class per level, to one class that represents any level, e.g.:
class Level
{
public int Boxes { get; set; }
public int MaxPoints { get; set; }
public int Health { get; set; }
public int[,] SolidBoxes()
{
int[,] position = new int[boardSize, boardSize];
position[1, 1] = 1;
return position;
}
}
You would then populate your dictionary like
Dictionary<int, Level> myLevelDictionary = new Dictionary<int, Level>()
{
{ 1, new Level() { Boxes = 3, MaxPoints = 46, Health = 63 } },
// etc.
};
UPDATE
A note about abstract classes
You mention abstract classes in your comments. They are useful if all of your levels have some behavior in common, but some have specialized behavior too. They will often be used in games for things that can move in the game, e.g. something like
abstract class Character
{
// Something everyone has
public int HitPoints { get; set; }
// Something everyone does, but does differently
public abstract void Attack(Character target);
}
public class Fighter : Character
{
public int SwordDamage { get; set; }
public void Attack(Character target)
{
target.Damage(this.SwordDamage - target.PhysicalDamageResistance);
}
}
public class Mage : Character
{
public int MagicFireDamage { get; set; }
public int MagicColdDamage { get; set; }
public void Attack(Character target)
{
if (UseFireDamage()) // e.g. roll random chance that the mage uses a fire spell
{
target.Damage(this.SwordDamage - target.FireDamageResistance);
}
else
{
target.Damage(this.SwordDamage - target.ColdDamageResistance);
}
}
}
one way maybe to use a dictionary.
class Level01
{
Dictionary<string,int> values;
public level01()
{
values.Add("Boxes",3);
values.Add("MaxPoints",3);
values.Add("Health",3);
}
//indexer
public int this[string s] {get{return values[s];} set {values[s] = value;}}
}
and use like:
Level01 lv = new Level01();
somemethod(lv["Boxes"]); //passes 3 to some method
although really you would want to use Dictionary<string,object> and add some type checking and other things to make it work smoothly but hopefully you can get started with that

OOP C# - Design pattern for MMO mechanics simulator

I've been working on a simulator for FFXIV;
I keep getting really close to finishing, then I get walled into an object access issue that doesn't let me access the stats of the main player. My project can be found at: https://github.com/eein/chocobro
There's plenty of things i can optimize, I know. :P
Basically i'm kind of brute-force winging it to have objects gain access to the objects they need, but i'm looking for the right way to do things.
I'm going to start rewriting it so don't clutch too hard to the example code but its there to see the issue i'm having. :(
Ideally in the next attempt, this is what i'd like to do:
Start with a player class that contains all of the informatin about the player object (in the future, i'd like to create multiples for full group simulation).
Something like:
int main(){
Player p = new Player();
public void setJob()
{
if (job == "bard"){ Player p = new Bard(); }
if (job == "warrior"){ Player p = new Warrior(); }
}
public class Player
{
private string name {get;set;}
private string job {get;set;}
private string STR;
private string DEX;
private string VIT;
//etc..
public virtual void rotation()
{
}
}
//I want to make the program a bit modular for jobs (roles/classes)
//So..
public class Bard : Player
{
public override void rotation()
{
heavyshot.execute();
//etc.
}
Ability heavyshot = new Heavyshot();
public class Heavyshot : Ability
{
public Heavyshot()
{
name = "Heavy Shot";
potency = 150;
dotPotency = 0;
recastTime = 2.5;
TPcost = 60;
animationDelay = 0.8;
abilityType = "Weaponskill";
castTime = 0.0;
duration = 0.0;
}
public override void impact()
{
//add heavier shot buff activation here
base.impact();
}
}
}
public class Ability{
public int cooldown;
public int cost;
public virtual void impact()
{
public virtual void impact()
{
//Deal some damage.
// !! - the key problem is here, i want to initiate a roll to compare to the players CRIT rating versus the roll to determine the bonus damage. But I can't access the initiated players crit from here. The rating may change depending on abilities used so I can't create a new object. I know i need an object reference but I can't figure it out...
log(time.ToString("F2") + " - " + name +
" Deals " + potency +
" Potency Damage. Next ability at: " + nextability);
}
}
I'm probably not being too clear, but basically I want to be able to access the player's crit from ability, and i'm assuming ability can't be set up this way in order for it to work. Does anyone have a good idea what kind of design pattern I should be using so that the virtual functions in ability can access the parent classes players stats?
Ideally, I want the bard class to contain all of the abilities and stat updates pertaining to the bard job, once bard inherits player and the object is changed to reference the Bard object, how do I make it so abilities created by the Ability class dont need an object reference to the parent at the time of creation when accessing that function.
I'm confusing myself, but many thanks to whoever understands my gibberish and can help!
One option is to pass the crit to the Abillity's constructor.
Another option, if an Ability is always connected to the player.
Have the crit property public with private set:
public class Player
{
private double crit { get; private set;}
...
}
Then pass the Player to the Ability's constructor and hold it there.
Note however that this will increase the coupling.
This could be done like this:
public class Ability
{
protected Player _player;
public Ability(Player player)
{
_player = player;
}
}
you would want to change the Headshot class deriving from Ability as well
public class Headshot : Ability
{
public Headshot(Player player) : base(player)
{
...
}
}
Instead of executing abilities rotation directly, save the abilities in a list. This way, you can have setup method in Player, that injects the player into all abilities in rotation. Adding conditions and some kind of "abilityused", that negates next ability is actually one more reason to express the rotation in some kind of list. So you don't have to duplicate the "abilityused" check everywhere, but have it in one place. Something like this:
public class Player
{
private string name {get;set;}
private string job {get;set;}
private string STR;
private string DEX;
private string VIT;
//etc..
public struct RotationAbility
{
public RotationAbility(Func<bool> cond, Ability ability)
{
this.cond = cond;
this.ability = ability;
}
public Func<bool> cond;
public Ability ability;
}
private List<RotationAbility> rotation = new List<RotationAbility>();
public void execute()
{
foreach (var ab in rotation)
{
if (ab.cond())
ab.ability.execute();
}
}
public void setUpRotation()
{
setUpRotation(rotation);
foreach (var ab in rotation)
{
ab.ability.Player = this;
}
}
protected virtual void setUpRotation(List<RotationAbility> rotation) { }
}
//I want to make the program a bit modular for jobs (roles/classes)
//So..
public class Bard : Player
{
protected override void setUpRotation(List<RotationAbility> rotation)
{
rotation.Add(new RotationAbility(()=>buff>0, new Heavyshot());
//etc.
}
public class Heavyshot : Ability
{
public Heavyshot()
{
name = "Heavy Shot";
potency = 150;
dotPotency = 0;
recastTime = 2.5;
TPcost = 60;
animationDelay = 0.8;
abilityType = "Weaponskill";
castTime = 0.0;
duration = 0.0;
}
public override void impact()
{
//add heavier shot buff activation here
base.impact();
}
}
}
public class Ability{
public Player Player { get; set; }
public int cooldown;
public int cost;
public virtual void impact()
{
//Deal some damage.
// !! - the key problem is here, i want to initiate a roll to compare to the players CRIT rating versus the roll to determine the bonus damage. But I can't access the initiated players crit from here. The rating may change depending on abilities used so I can't create a new object. I know i need an object reference but I can't figure it out...
log(time.ToString("F2") + " - " + name +
" Deals " + potency +
" Potency Damage. Next ability at: " + nextability);
}
}
}

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