Diskuze: XNA - komponentka nereaguje na přepsání update
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.


David Hartinger:24.10.2012 9:17
Máš to v tutoriálech
Ještě existuje DrawableGameComponent.
matesax:24.10.2012 11:05
Z něj právě dědím...
(Změnil jsem to...) Rovnou se zeptám - je to dobrý návrh?:
Komponentka GameMenu. Třída MenuItemCollection. Komponentka MenuItem. MenuItem se nezávisle na ničem rovnou vykresluje - potřebuje k tomu pochopitelně parametr Game. A zároveň vytváří známé eventy - click, hover... Má border, text, name,... A teď - odkud bych měl čerpat MenuItemCollection? (Aktuálně CollectionBase) Zatím tedy GameMenu nemá valné využití - ale asi nakonec potřeba bude. Na jednu stranu jsem se vyhnul cyklům - ale zase si hodně předávám parametr Game...
matesax:24.10.2012 17:03
Jo a tak přemýšlím:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
namespace GameMenu
{
public struct MouseEventArgs
{
public MouseState MouseState { get; set; }
}
public class MenuItem : DrawableGameComponent
{
private Texture2D itemTexture;
private SpriteBatch spriteBatch;
private SpriteFont spriteFont;
public string Name { get; set; }
public string Text { get; set; }
public Rectangle Bounds { get; set; }
public Color BackgroundColor { get; set; }
public Color BorderColor { get; set; }
public Color ForeColor { get; set; }
public int BorderWidth { get; set; }
public delegate void ClickHandler(object sender, MouseEventArgs me);
public event ClickHandler Click;
public delegate void MouseHoverHandler(object sender, MouseEventArgs me);
public event MouseHoverHandler MouseHover;
public MenuItem(Game game, SpriteFont spriteFont) : base(game)
{
game.Components.Add(this);
BorderWidth = 2;
BorderColor = Color.RoyalBlue;
BackgroundColor = Color.CornflowerBlue;
this.spriteFont = spriteFont;
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
itemTexture = new Texture2D(GraphicsDevice, Bounds.Width, Bounds.Height);
SetTexture();
}
public override void Update(GameTime gameTime)
{
if (Bounds.Intersects(new Rectangle(Mouse.GetState().X, Mouse.GetState().Y, 5, 5)))
{
MouseHover(this, new MouseEventArgs() { MouseState = Mouse.GetState() });
if (Mouse.GetState().LeftButton == ButtonState.Pressed)
Click(this, new MouseEventArgs() { MouseState = Mouse.GetState() });
}
base.Update(gameTime);
}
private void SetTexture()
{
Color[] colors = new Color[Bounds.Width * Bounds.Height];
for (int x = 0; x < Bounds.Width; x++)
for (int y = 0; y < Bounds.Height; y++)
colors[x + (Bounds.Width * y)] = x < BorderWidth || y < BorderWidth || x > Bounds.Width - 1 - BorderWidth || y > Bounds.Height - 1 - BorderWidth ? BorderColor : BackgroundColor;
itemTexture.SetData<Color>(colors);
}
public override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(itemTexture, Bounds, BackgroundColor);
spriteBatch.DrawString(spriteFont, Text, new Vector2(Bounds.X, Bounds.Y), ForeColor);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Neměly by být ty eventy někde mimo? Přijde mi blbost je pokaždé vytvářet...
Nešlo by to zkrátit?
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
namespace GameMenu
{
public struct MouseEventArgs
{
public MouseState MouseState { get; set; }
}
public class MenuItem : DrawableGameComponent
{
private Game mum;
private Texture2D itemTexture;
private SpriteBatch spriteBatch;
private SpriteFont spriteFont;
private string spriteFontFile;
public string Name { get; set; }
public string Text { get; set; }
public Rectangle Bounds { get; set; }
public Color BackgroundColor { get; set; }
public Color BorderColor { get; set; }
public Color ForeColor { get; set; }
public int BorderWidth { get; set; }
public Texture2D Image { get; set; }
public delegate void ClickHandler(object sender, MouseEventArgs me);
public event ClickHandler Click;
public delegate void MouseHoverHandler(object sender, MouseEventArgs me);
public event MouseHoverHandler MouseHover;
public MenuItem(Game game, string spriteFontFile) : base(game)
{
Text = "Konec";
BorderWidth = 2;
game.Components.Add(this);
ForeColor = Color.AliceBlue;
BorderColor = Color.RoyalBlue;
BackgroundColor = Color.CornflowerBlue;
this.spriteFontFile = spriteFontFile;
mum = game;
}
private struct HSV
{
public decimal Hue { get; set; }
public decimal Saturation { get; set; }
public decimal Value { get; set; }
}
private HSV ToHSV(Color rgb)
{
decimal
r = (decimal)rgb.R / 255m,
g = (decimal)rgb.G / 255m,
b = (decimal)rgb.B / 255m,
minRGB = Math.Min(r, Math.Min(g, b)),
maxRGB = Math.Max(r, Math.Max(g, b));
if (minRGB == maxRGB)
return new HSV() { Hue = 0, Saturation = 0, Value = minRGB };
return new HSV() { Hue = 60 * ((r == minRGB ? 3 : b == minRGB ? 1 : 5) - (r == minRGB ? g - b : b == minRGB ? r - g : b - r) / (maxRGB - minRGB)), Saturation = (maxRGB - minRGB) / maxRGB, Value = maxRGB };
}
private Color ToRGB(HSV hsv)
{
decimal
hi = Math.Floor(hsv.Hue / 60) % 6,
f = hsv.Hue / 60 - Math.Floor(hsv.Hue / 60),
p = hsv.Value * (1 - hsv.Saturation),
q = hsv.Value * (1 - (f * hsv.Saturation)),
t = hsv.Value * (1 - ((1 - f) * hsv.Saturation));
decimal[] ret;
switch ((int)hi)
{
case 0:
ret = new decimal[] { hsv.Value, t, p };
break;
case 1:
ret = new decimal[] { q, hsv.Value, p };
break;
case 2:
ret = new decimal[] { p, hsv.Value, t };
break;
case 3:
ret = new decimal[] { p, q, hsv.Value };
break;
case 4:
ret = new decimal[] { t, p, hsv.Value };
break;
case 5:
ret = new decimal[] { hsv.Value, p, q };
break;
default:
ret = new decimal[] { 0xFF, 0x00, 0x00, 0x00 };
break;
}
return new Color((int)(ret[0] * 255m), (int)(ret[1] * 255m), (int)(ret[2] * 255m));
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
spriteFont = mum.Content.Load<SpriteFont>(spriteFontFile);
itemTexture = new Texture2D(GraphicsDevice, Bounds.Width, Bounds.Height);
SetTexture();
}
public override void Update(GameTime gameTime)
{
if (Bounds.Intersects(new Rectangle(Mouse.GetState().X, Mouse.GetState().Y, 5, 5)))
{
if (MouseHover != null)
MouseHover(this, new MouseEventArgs() { MouseState = Mouse.GetState() });
if (Mouse.GetState().LeftButton == ButtonState.Pressed && Click != null)
Click(this, new MouseEventArgs() { MouseState = Mouse.GetState() });
}
base.Update(gameTime);
}
private void SetTexture()
{
Color[] colors = new Color[Bounds.Width * Bounds.Height];
for (int x = 0; x < Bounds.Width; x++)
for (int y = 0; y < Bounds.Height; y++)
colors[x + (Bounds.Width * y)] = x < BorderWidth || y < BorderWidth || x > Bounds.Width - 1 - BorderWidth || y > Bounds.Height - 1 - BorderWidth ? BorderColor : BackgroundColor;
itemTexture.SetData<Color>(colors);
}
public override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(itemTexture, Bounds, BackgroundColor);
spriteBatch.DrawString(spriteFont, Text, new Vector2(Bounds.X, Bounds.Y) + ((new Vector2(Bounds.Width, Bounds.Height) - spriteFont.MeasureString(Text)) / 2), ForeColor);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Převod barev tam je kvůli tomu, že tlačítka budou přechody - a snadno měnit světlost mohu právě v HSV... Hodně mě štvě, že jsem byl donucen si parametr Game dokonce ukládat - ale jak jinak na to jít?
David Hartinger:25.10.2012 12:22
Ukládání Game je v pořádku, tak jsou komponenty navržené.
matesax:25.10.2012 12:24
Jo jasně - prostě mi jde o to mít to nejkratší a hlavně co nejméně náročné...
matesax:25.10.2012 15:03
Nevíš, co je na tom špatně? :
int
index = 0,
notch = 100 / Bounds.Height;
decimal difference = 1 / ((decimal)notch / Bounds.Height);
for (decimal saturation = 0; saturation <= 1; saturation += difference)
{
currentColor.Saturation = Math.Min(1, saturation);
usedColor.Add(ToRGB(currentColor));
}
for (int y = 0; y < Bounds.Height; y++)
{
for (int x = 0; x < Bounds.Width; x++)
colors[x + (Bounds.Width * y)] = x < BorderWidth || y < BorderWidth || x > Bounds.Width - 1 - BorderWidth || y > Bounds.Height - 1 - BorderWidth ? BorderColor : usedColor[index];
if (y % notch == 0)
index++;
}
Nejprve si spočítám differenci - aby mi barva vystačila, ale ona mi nestačí - zkusil jsem si i dát rezervu...
matesax:25.10.2012 15:52
Jé - já to prohodil...
decimal difference = 1 / (Bounds.Height / (decimal)notch);
matesax:25.10.2012 20:54
Game není třeba ukládat - je to vlastnost komponentky...
Zobrazeno 11 zpráv z 11.