У меня есть 2 текстуры 800x480 (передний план / фон), которые являются файлами .png в приложении XNA Windows Phone 7.
Я хочу, чтобы передний план исчезал / переходный, чтобы показать фон. У меня огромные проблемы с производительностью. Моя идея состоит только в maipulate Alpha
канал в одном Texture2D
, поэтому я создал такой код:
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
private Texture2D _background, _foreground;
private BlendState _blendState;
private uint[] _pixelsForeground;
private uint[] _pixelsBackground;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
TargetElapsedTime = TimeSpan.FromTicks(333333);
graphics.IsFullScreen = true;
graphics.SupportedOrientations = DisplayOrientation.Portrait;
graphics.PreferredBackBufferHeight = 840;
graphics.PreferredBackBufferWidth = 480;
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
_background = this.Content.Load<Texture2D>(@"background");
_foreground = this.Content.Load<Texture2D>(@"foreground");
_pixelsForeground = new uint[_foreground.Width * _foreground.Height];
_pixelsBackground = new uint[_foreground.Width * _foreground.Height];
_background.GetData(_pixelsBackground);
_foreground.GetData(_pixelsForeground);
_blendState = new BlendState
{
AlphaBlendFunction = BlendFunction.Add,
ColorBlendFunction = BlendFunction.Add,
AlphaSourceBlend = Blend.SourceAlpha,
ColorSourceBlend = Blend.SourceAlpha,
AlphaDestinationBlend = Blend.InverseSourceAlpha,
ColorDestinationBlend = Blend.InverseSourceAlpha
};
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
this.GraphicsDevice.Textures[0] = null;
for (int x = 0; x < _foreground.Width; x++)
{
for (int y = 0; y < _foreground.Height; y++)
{
uint pixelCanvas = _pixelsForeground[y * _foreground.Width + x];
uint newPixelCanvas = pixelCanvas - 0x05000000;
_pixelsForeground[y*_foreground.Width + x] = newPixelCanvas;
_pixelsForeground[y * _foreground.Width + x] = (newPixelCanvas & 0xFF000000) > (pixelCanvas & 0xFF000000)
? pixelCanvas & 0x00FFFFFF
: newPixelCanvas;
}
}
Rectangle rect = new Rectangle(0, 0, _foreground.Width, _foreground.Height);
_foreground.SetData<uint>(0, rect, _pixelsForeground, 0, _foreground.Height * _foreground.Width);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.FrontToBack, _blendState);
spriteBatch.Draw(_foreground, Vector2.One, null, Color.White);
spriteBatch.Draw(_background, Vector2.One, null, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
Проблема в том, что он генерирует низкую производительность из-за:
_foreground.SetData<uint>(...)
Какую технику я могу использовать, чтобы справиться с этим лучше?
Я бы предпочел эту манипуляцию альфа-каналом для других целей.
Имейте в виду, что у пикселей переднего плана уже может быть другой альфа-канал при запуске, например, прозрачные пятна.