Complexity of Dictionary - C#

Started by
15 comments, last by jameszhao00 12 years, 5 months ago
Hey, I am creating a game using XNA 4.0 and C#.

I am currently trying to create a HUD. I ended up going with 2 classes to create the HUD. It will be easier to show you than explain:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CGPLibrary.Sprites;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace CGPLibrary
{
public class HUDElement
{
protected Sprite element;
protected Texture2D texture;
protected int width, height;
protected Vector2 m_position;
protected int offsetX, offsetY;
protected GameWindow Window;
protected Color color;


public enum Position
{
TOP_LEFT, TOP_RIGHT, TOP_MIDDLE, MIDDLE_LEFT, MIDDLE_RIGHT, MIDDLE, BOTTOM_LEFT, BOTTOM_RIGHT, BOTTOM_MIDDLE

}

public enum ELEM_TYPE { Health, Armour, H_ABackground, Life }ELEM_TYPE elementType;

public HUDElement(Sprite sprite, GameWindow window)
{
color = sprite.sprColor;
Window = window;
offsetX = 0;
offsetY = 0;
element = sprite;
texture = sprite.spTexture;
width = sprite.Width;
height = sprite.Height;
}

public Sprite spr { get { return element; } }
public int Width { get { return width; } }
public int Height { get { return height; } }
public Color elemColor { get { return color; } set { color = value; } }
public Texture2D elemText { get { return texture; } }
public ELEM_TYPE type { get { return elementType; } set { elementType = value; } }
public Vector2 position { get { return m_position; } }
public int xOffset { get { return offsetX; } set { offsetX = value; } }
public int yOffset { get { return offsetY; } set { offsetY = value; } }

public void setPosition(Position pos)
{
switch (pos)
{
case Position.TOP_LEFT:
m_position = new Vector2(offsetX, offsetY);
break;
case Position.TOP_MIDDLE:
m_position = new Vector2((Window.ClientBounds.Width / 2 - texture.Width / 2) + offsetX, offsetY);
break;
case Position.TOP_RIGHT:
m_position = new Vector2((Window.ClientBounds.Width - texture.Width) + offsetX, offsetY);
break;

case Position.MIDDLE_LEFT:
m_position = new Vector2(offsetX, (Window.ClientBounds.Height / 2 - texture.Height / 2) + offsetY);
break;
case Position.MIDDLE:
m_position = new Vector2((Window.ClientBounds.Width / 2 - texture.Width / 2) + offsetX, (Window.ClientBounds.Height / 2 - texture.Height / 2) + offsetY);
break;
case Position.MIDDLE_RIGHT:
m_position = new Vector2((Window.ClientBounds.Width - texture.Width) + offsetX, (Window.ClientBounds.Height / 2 - texture.Height / 2) + offsetY);
break;

case Position.BOTTOM_LEFT:
m_position = new Vector2(offsetX, (Window.ClientBounds.Height - texture.Height) + offsetY);
break;
case Position.BOTTOM_MIDDLE:
m_position = new Vector2((Window.ClientBounds.Width / 2 - texture.Width / 2) + offsetX, (Window.ClientBounds.Height - texture.Height) + offsetY);
break;
case Position.BOTTOM_RIGHT:
m_position = new Vector2((Window.ClientBounds.Width - texture.Width) + offsetX, (Window.ClientBounds.Height - texture.Height) + offsetY);
break;

}

}
}
}



using Microsoft.Xna.Framework;
using System.Collections.Generic;
using HeadStacker;
using CGPLibrary.Sprites;
using Microsoft.Xna.Framework.Graphics;
using CGPLibrary.Entities;


namespace CGPLibrary
{
/// <summary>
/// This is a game component that implements IUpdateable.
/// </summary>
public class HUD : DrawableGameComponent
{
protected Dictionary<HUDElement.ELEM_TYPE, HUDElement> hudElements;
HumanPlayer player;
protected SpriteBatch batch;
public Main game;

public HUD(Main game)
: base(game)
{
hudElements = new Dictionary<HUDElement.ELEM_TYPE, HUDElement>();
this.game = game;
player =game.human;
this.batch = game.spriteBatch;

}


public void addHudElement(HUDElement elem)
{
hudElements.Add(elem.type, elem);


}
public override void Draw(GameTime gameTime)
{
batch.Begin();
batch.Draw(hudElements[HUDElement.ELEM_TYPE.Life].elemText, hudElements[HUDElement.ELEM_TYPE.Life].position, hudElements[HUDElement.ELEM_TYPE.Life].spr.sourceRect,
hudElements[HUDElement.ELEM_TYPE.Life].elemColor, 0f, Vector2.Zero, hudElements[HUDElement.ELEM_TYPE.Life].spr.Scale,SpriteEffects.None,0f);


batch.Draw(hudElements[HUDElement.ELEM_TYPE.H_ABackground].elemText, hudElements[HUDElement.ELEM_TYPE.H_ABackground].position,null,
hudElements[HUDElement.ELEM_TYPE.H_ABackground].elemColor,0f,Vector2.Zero,hudElements[HUDElement.ELEM_TYPE.H_ABackground].spr.Scale,SpriteEffects.None,0f);



batch.Draw(hudElements[HUDElement.ELEM_TYPE.Health].elemText, hudElements[HUDElement.ELEM_TYPE.Health].position,
new Rectangle(0,0,(int)(hudElements[HUDElement.ELEM_TYPE.Health].Width * ((double)player.health/100)),hudElements[HUDElement.ELEM_TYPE.Health].Height)
,hudElements[HUDElement.ELEM_TYPE.Health].elemColor,0f,Vector2.Zero,hudElements[HUDElement.ELEM_TYPE.Health].spr.Scale,SpriteEffects.None,0f);



batch.Draw(hudElements[HUDElement.ELEM_TYPE.Armour].elemText, hudElements[HUDElement.ELEM_TYPE.Armour].position,
new Rectangle(0, 0, (int)(hudElements[HUDElement.ELEM_TYPE.Armour].Width * ((double)player.armour / 100)), hudElements[HUDElement.ELEM_TYPE.Armour].Height)
, hudElements[HUDElement.ELEM_TYPE.Armour].elemColor,0f, Vector2.Zero, hudElements[HUDElement.ELEM_TYPE.Armour].spr.Scale, SpriteEffects.None, 0f);
batch.End();

base.Draw(gameTime);
}
public override void Update(GameTime gameTime)
{
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
hudElements[HUDElement.ELEM_TYPE.Life].spr.animate(elapsed);
// hudElements[HUDElement.ELEM_TYPE.Health].elemText = player.currentWeapon.texture;

base.Update(gameTime);
}
}
}




You can see in the draw method, I find each element inside the Dictionary and draw it. My question is, will this cause any kind of overhead? I think I read that the Dictionary is normally O( c )but that was using the .containsKey() method. Will using the [] notation cause any slowdowns(or increased performance)?
Advertisement
It's fine.

It's fine.


Thanks ,I guess that answer just about sums it up then :D
I can't speak to the efficiency of your system, but your code makes my eyes bleed. Why don't you try something like this?



HudElement element = hudElements[HUDElement.ELEM_TYPE.Life];
batch.Draw(element.elemText, element.position, element.spr.sourceRect, element.elemColor, 0f, Vector2.Zero, element.spr.Scale,SpriteEffects.None,0f);


I can't speak to the efficiency of your system, but your code makes my eyes bleed. Why don't you try something like this?



HudElement element = hudElements[HUDElement.ELEM_TYPE.Life];
batch.Draw(element.elemText, element.position, element.spr.sourceRect, element.elemColor, 0f, Vector2.Zero, element.spr.Scale,SpriteEffects.None,0f);




Haha, It makes mine bleed , also, I have no idea why I didn't do that in the first place. Thanks for that

HudElement life = hudElements[HUDElement.ELEM_TYPE.Life];
batch.Draw(life.elemText, life.position, life.spr.sourceRect, life.elemColor, 0f, Vector2.Zero, life.spr.Scale,SpriteEffects.None,0f);
//or
HudElement HUDLife = hudElements[HUDElement.ELEM_TYPE.Life];
batch.Draw(HUDLife.elemText, HUDLife.position, HUDLife.spr.sourceRect, HUDLife.elemColor, 0f, Vector2.Zero, HUDLife.spr.Scale,SpriteEffects.None,0f);


I don't know. Suspense's code definitely does the job. But I guess, if it were me, I'd like a little more description.

Beginner in Game Development?  Read here. And read here.

 

All of the above would work better if it were turned the other way round:
class HudElement {
...
public void RenderToSpriteBatch(SpriteBatch s) {
s.draw(elemText, position, spr.sourceRect, elemColor, 0f, Vector2.Zero, spr.Scale,SpriteEffects.None, 0f);
}
...
};


Then:
...
public override void Draw(GameTime gameTime)
{
batch.Begin();
foreach(KeyValuePair<HUDElement.ELEM_TYPE, HUDElement> e in hudElements) {
e.Value.RenderToSpriteBatch(batch);
}
batch.End();
...


HudElement life = hudElements[HUDElement.ELEM_TYPE.Life];
batch.Draw(life.elemText, life.position, life.spr.sourceRect, life.elemColor, 0f, Vector2.Zero, life.spr.Scale,SpriteEffects.None,0f);
//or
HudElement HUDLife = hudElements[HUDElement.ELEM_TYPE.Life];
batch.Draw(HUDLife.elemText, HUDLife.position, HUDLife.spr.sourceRect, HUDLife.elemColor, 0f, Vector2.Zero, HUDLife.spr.Scale,SpriteEffects.None,0f);


I don't know. Suspense's code definitely does the job. But I guess, if it were me, I'd like a little more description.


Ye thanks, I did it the way you did aswell after I read Suspense's reply. I also like some description :D.. He was probably just generalising anyway.
Speaking to your question, I'd be surprised --extremely surprised-- if: aDictionary.containsKey("blah") was faster or improved in any way than aDictionary["blah"]. If anything, aDictionary.containsKey("blah") would have to do a scan of all keys until it reached the key it was looking for. aDictionary["blah"], IIRC, is the better choice of the two. And definitely should be still O(c).

Beginner in Game Development?  Read here. And read here.

 


All of the above would work better if it were turned the other way round:
class HudElement {
...
public void RenderToSpriteBatch(SpriteBatch s) {
s.draw(elemText, position, spr.sourceRect, elemColor, 0f, Vector2.Zero, spr.Scale,SpriteEffects.None, 0f);
}
...
};


Then:
...
public override void Draw(GameTime gameTime)
{
batch.Begin();
foreach(KeyValuePair<HUDElement.ELEM_TYPE, HUDElement> e in hudElements) {
e.Value.RenderToSpriteBatch(batch);
}
batch.End();
...




Ahhh cool, I was looking for a way to do it all at once after I got it working. Thanks!

This topic is closed to new replies.

Advertisement