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.
Related
im beginner and still learning please don't hate.
So my script is located in Canvas, (Canvas -> inv -> invslot) but I need to get currentSlot int from a script in invslot gameobj., how would I do that the right way? I've tried this so far but doesn't seem to work at all.
void UpdateUI () {
for (int i = 0; i < slots.Length; i++)
{
if (i < inventory.items.Count) {
currentSlot = GetComponentsInChildren<InventoryScroll>();
slots[i] = currentSlot;
currentSlot.AddItem(inventory.items[i]);
Debug.Log ("Updating UI");
} else
{
slots[i].ClearSlot();
}
}
}
EDIT!
Here is the top of my InventoryUI, where I want to bring the int currentSlot
public Transform itemsParent;
Inventory inventory;
InventorySlot[] slots;
// Start is called before the first frame update
void Start()
{
inventory = Inventory.instance;
inventory.onItemChangedCallback += UpdateUI;
slots = itemsParent.GetComponentsInChildren<InventorySlot>();
}
But the Inventoryscroll goes this way
List<GameObject> slots = new List<GameObject>();
public int currentSlot=0;
int slotsToScroll=3;
void Start() {
foreach(Transform child in this.transform) {
slots.Add(child.gameObject);
}
}
void Update () {
if (Input.GetKeyDown(KeyCode.Alpha1)) {
currentSlot=0;
UpdateDisplay();
}
if (Input.GetAxis("Mouse ScrollWheel") >0){
if (currentSlot<slotsToScroll) {
currentSlot++;
} else {
currentSlot=0;
}
UpdateDisplay();
}
}
void UpdateDisplay() {
for (int i = 0; i < slots.Count; i++)
{
if (i==currentSlot) {
slots[i].transform.GetChild(0).gameObject.SetActive(true);
} else {
slots[i].transform.GetChild(0).gameObject.SetActive(false);
}
}
}
Inventory script
#region Singleton
public static Inventory instance;
void Awake () {
if (instance != null) {
Debug.LogWarning("More than one instance of inventory found!");
return;
}
instance = this;
}
#endregion
public delegate void OnItemChanged();
public OnItemChanged onItemChangedCallback;
public int space = 6;
public List items = new List();
public bool Add (Item item) {
if (!item.isDefaultItem) {
if(items.Count >= space) {
Debug.Log("Not enough inventory space.");
return false;
}
items.Add(item);
if (onItemChangedCallback != null)
onItemChangedCallback.Invoke();
}
return true;
public void Remove (Item item) {
items.Remove(item);
if (onItemChangedCallback != null)
onItemChangedCallback.Invoke();
Careful, Unity has two methods:
GetComponentsInChildren
Returns all components of Type type in the GameObject or any of its children.
this returns a InventoryScroll []!
and GetComponentInChildren
Returns the component of Type type in the GameObject or any of its children using depth first search.
This returns one single InventoryScroll reference, the first one found!
Note the s!
From your description and how you use it in your code it seems like you wanted to use the latter but have an s too much.
The second mistake: From the variable name it sounds like you rather wanted to get an InventorySlot not an InventoryScroll!
So you should use
currentSlot = GetComponentInChildren<InventorySlot>();
Though it is hard to tell what your actual goal is with this code without seeing the types of slots and currentSlot.
It also appears really strange to me that you already get all slots in Start but here you overwrite
slots[i] = currentSlot;
for each i that is i < inventory.items.Coun. Also you iterate through slots.Length but you pass in inventory.izems[i] .. I don't understand what is supposed to happen here exactly.
hello i'm trying to make a dialogue box using an array but i seem to be having a bit of an issue. instead of showing the different strings that's in DialogHolder class, it keeps on showing the DialogueManager instead.
From my understanding, I wanted to make it that the DialogHolder holds that dialogue and i got the idea of making it something like this -->
[DialogHolder = DialogueManager]
but the only thing that is showing is the DailogueManager with the test strings i placed to see if the dialogue changes
DailogHolder
public string dialogue;
private DialogueManager sentence;
public string[] NPC_name;
[TextArea(3, 10)]
public string[] dialogueLines;
void Start()
{
}
public void TriggerDialogue()
{
FindObjectOfType<DialogueManager>().ShowDialogue(dialogueLines);
FindObjectOfType<DialogueManager>().ShowName(NPC_name);
}
DialogueManager
//holds the text GameObject
public Text NPC_nameText;
public Text NPC_DialogueText;
public string[] names;
[TextArea(3, 10)]
public string[] dialogueLines;
public int currentlines;
void Start () {
//lets the box types the char individual
StopAllCoroutines();
}
void Update()
{
StartDialog();
}
public void StartDialog()
{
if (currentlines >= dialogueLines.Length)
{
currentlines = 0;
EndDialogue();
return;
}
NPC_DialogueText.text = "";
StartCoroutine(TypeSentence());
}
public void ShowDialogue(string[] dialogueLines)
{
NPC_DialogueText.text = dialogueLines[currentlines];
}
public void ShowName(string[] NPC_name)
{
//selected a name
NPC_nameText.text = NPC_name[0];
//this part works for some reason since it's taken from the DialogHolder class
}
//pressed by a button
public void NextLine()
{
currentlines++;
StopAllCoroutines();
}
void EndDialogue()
{
Debug.Log("End of Conversation");
}
IEnumerator TypeSentence()
{
//types the characters for each sentence
foreach (char letter in dialogueLines[currentlines].ToCharArray())
{
NPC_DialogueText.text += letter;
yield return null;
}
}
if i remove the [size] of the array in the DailogHolder class, i get an error that says [Array index is out of range] but if i just remove the strings that was saved inside that array, it wouldn't matter anyway since it just keeps on using the array in the DialogueManager class.
Please help, it works if i'm using only a single string and not an array but i need to learn how to print multiple lines
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.
I'm creating a Media player application with Unity3D and C#.
(My question is not related to Unity, it's a pure design problem)
Here is what I currently have:
an IApp interface, with implementers:
TextViewer
ImageViewer
MediaPlayer
an IFile interface, with implementers:
TextFile
ImageFile
MediaFile - with children:
VideoFile
AudioFile
Here's the interface:
public interface IApp
{
void Open(IFile file);
Type SupportedType { get; }
}
Each app has a specific supported file type it could open.
A word about my MediaPlayer, is that it opens/plays both Audio and Video files. But the way I open videos, is different from the way I open audios, so there's a unique logic for each.
Now here's the code - very simple (but not fully implemented yet):
public class MediaPlayer : IApp
{
public Type SupportedType { get { return typeof(MediaFile); } }
public void Open(IFile file)
{
if (file is MediaFile)
Console.WriteLine("MediaPlayer opening media file...");
}
List<MediaFile> Medias = new List<MediaFile>();
public MediaFile Current { private set; get; }
public PlaybackControls Controls { private set; get; }
public PlaybackSettings Settings { private set; get; }
public MediaPlayer()
{
Controls = new PlaybackControls(this);
Settings = new PlaybackSettings(this);
}
public class PlaybackControls
{
private MediaPlayer player;
private int index;
public PlaybackControls(MediaPlayer player)
{
this.player = player;
}
public void Seek(float pos) { }
public void Next()
{
index = (index + 1) % player.Medias.Count;
player.Current = player.Medias[index];
}
public void Previous()
{
index--;
if (index < 0)
index = player.Medias.Count - 1;
player.Current = player.Medias[index];
}
private void PlayVideo(VideoFile video)
{
// video logic
}
private void PlayAudio(AudioFile audio)
{
// audio logic
}
public void Play(MediaFile media)
{
IsPlaying = true;
if (media is AudioFile)
PlayAudio(media as AudioFile);
else if (media is VideoFile)
PlayVideo(media as VideoFile);
}
public void Play()
{
Play(player.Current);
}
public void Pause()
{
IsPlaying = false;
}
public void Stop()
{
IsPlaying = false;
Seek(0);
}
public bool IsPlaying { get; private set; }
}
public class PlaybackSettings
{
// Volume, shuffling, looping, etc
}
}
The thing that I don't quite like, is the Play(Media) method. Inside, I'm doing a check upon the media type, and depending on whether the media is a video or audio, I'm calling the right method. I don't like that, I don't feel it's quite right. What if I had other types of media, like picture? what if I wanted to move ImageFile under MediaFile?
I would then have to add another else-if statement, which isn't polymorphic at all.
What I could do instead, is let the media files choose what method to call, like:
public abstract class MediaFile : IFile
{
//...
public abstract void Open(MediaPlayer from);
//...
}
public class AudioFile : MediaFile
{
public override void Open(MediaPlayer from)
{
from.PlayAudio(this);
}
}
public class VideoFile : MediaFile
{
public override void Open(MediaPlayer from)
{
from.PlayVideo(this);
}
}
Now in the MediaPlayer:
public void Open(MediaFile media)
{
media.Open(this); // polymorphically open it
}
No more else-if, nice! But this introduces other inconveniences I don't like:
VideoFile & MediaPlayer and AudioFile & MediaPlayer are now more tightly coupled.
There's now a circular dependency (MediaPlayer has to know about Audio/VideoFile and vise versa)
I don't think it makes sense for the Audio/VideoFiles to be able to open themselves, by themselves (although they're not really doing so, they're just telling the MediaPlayer how to open them. The MediaPlayer should know how to, he doesn't need anyone telling him how to do his work.)
It feels very redundant, it's like asking somebody to point at his ear, so he wraps his right hand around his head, and points to his left ear instead of right! - What's happening is that we're going:
either
MediaPlayer.Open(Media) -> AudioFile.Open(AudioFile) -> MediaPlayer.OpenAudio(AudioFile)
or
MediaPlayer.Open(Media) -> VideoFile.Open(VideoFile) -> MediaPlayer.OpenVideo(VideoFile)
We're circling around ourselves, in the name of polymorphism where we could have just gone directly to the right methods.
I think both the two above approaches are not best, but if I were to choose one, I would go for the first.
What do you think? Is there a better way? - A nice, elegant, robust polymorphic way that shoots all birds with one stone? How should I have gone about this? Maybe there's a design pattern I could use here?
And please correct me if I was wrong in my judgement.
Thanks a lot for any help in advance.
You have couple options.
1) Use dictionary of delegates and select based on file type, which delegate to run:
public class PlaybackControls
{
private MediaPlayer player;
private int index;
Dictionary<string, Action<MediaFile>> _fileActionMethods;
public PlaybackControls(MediaPlayer player)
{
this.player = player;
_fileActionMethods = new Dictionary<string, Action<MediaFile>>();
_fileActionMethods.Add(typeof(VideoFile).Name, x => PlayVideoFile(x));
_fileActionMethods.Add(typeof(AudioFile).Name, x => PlayAudioFile(x));
}
public void Seek(float pos) { }
public void Next()
{
index = (index + 1) % player.Medias.Count;
player.Current = player.Medias[index];
}
public void Previous()
{
index--;
if (index < 0)
index = player.Medias.Count - 1;
player.Current = player.Medias[index];
}
public void Play(MediaFile media)
{
IsPlaying = true;
_fileActionMethods[media.GetType().Name](media);
}
public void Play()
{
Play(player.Current);
}
public void Pause()
{
IsPlaying = false;
}
public void Stop()
{
IsPlaying = false;
Seek(0);
}
public bool IsPlaying { get; private set; }
private void PlayVideoFile(MediaFile file) { }
private void PlayAudioFile(MediaFile file) { }
}
2) Second option is based on similar concept of dynamic selection, but uses another layer of abstraction that enables you to handle each file using separate class. For lack of imagination I am naming it IFileActionHandler. It has only one method now but you can add more, if you need to. The sample below shows how to dynamically select the correct implementation based on the file type. I created a dictionary of these implementations in the constructor. Depending on how large the memory footprint of the implementations is, you may want to think about another approach - define the key value pairs in a static file (XML, config, txt, whatever) and create the correct instance using one of System.Acticator.CreateInstance overloads.
interface IFileActionHandler
{
void PlayFile(IFile file);
}
class FileActionHandlerBase : IFileActionHandler
{
IApp _app;
public FileActionHandlerBase(IApp app) // It may not be needed depending on what you want to do.
{
_app = app;
}
public abstract void PlayFile(IFile file);
}
class AudioFileActionHandler : FileActionHandlerBase
{
public AudioFileActionHandler(IApp app)
: base(app) { }
public override void PlayFile(IFile file)
{
// Your implementation...
}
}
class VideoFileActionHandler : FileActionHandlerBase
{
public VideoFileActionHandler(IApp app)
: base(app) { }
public override void PlayFile(IFile file)
{
// Your implementation...
}
}
public class PlaybackControls
{
private MediaPlayer player;
private int index;
Dictionary<string, IFileActionHandler> _fileActionHandlers;
public PlaybackControls(MediaPlayer player)
{
this.player = player;
_fileActionHandlers = new Dictionary<string, IFileActionHandler>();
_fileActionHandlers.Add(typeof(VideoFile).Name, new VideoFileActionHandler(player));
_fileActionHandlers.Add(typeof(AudioFile).Name, new AudioFileActionHandler(player));
}
public void Seek(float pos) { }
public void Next()
{
index = (index + 1) % player.Medias.Count;
player.Current = player.Medias[index];
}
public void Previous()
{
index--;
if (index < 0)
index = player.Medias.Count - 1;
player.Current = player.Medias[index];
}
public void Play(MediaFile media)
{
IsPlaying = true;
_fileActionHandlers[media.GetType().Name].PlayFile(media);
}
public void Play()
{
Play(player.Current);
}
public void Pause()
{
IsPlaying = false;
}
public void Stop()
{
IsPlaying = false;
Seek(0);
}
public bool IsPlaying { get; private set; }
}
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.