I’ve been wanting to do this for a long time.
You know, warping/transforming sprites, wave effects, stuff like that. I just don’t know if it’s possible to do this through MonoGame.
I’ve been wanting to do this for a long time.
You know, warping/transforming sprites, wave effects, stuff like that. I just don’t know if it’s possible to do this through MonoGame.
These are absolutely possible!
I don’t have a computer right now to set up examples, but google for monogame or XNA distortion shader
I have done things like heat-waves, wavy flags, skewing and such with simple things like stencil-rects. Its not as cool as the stuff in the video, but it is crisp and smooth.
You have anything you want on a render-target.
You have a wave generator (something that spins) that spits out, say 16 different x or y values per frame…
In your draw cycle, draw each line or row of your rendertarget (using a pixel-thin stencil rect) either to a draw pos + alternating wave values, or have the stencil rect move with the wave values.
For a full screen heat wave, this is 1080 draw-calls in a for loop, but I have done it in a game with all sorts of other action happening, and it was fine.
With a seperate class set up to handle this, you can throw any image through, and have it stretch to fit any banner or area of the screen…
Umm… I have no idea what any of this means or how to do it… @monopalle
Okay, well I can understand the concept, but I don’t know how to implement/code it
I can post an example if you want? Pretty sure I have a project that only does that one thing.
Yes please! I’d appreciate it
ok, here is first a custom class… Its basically just a basic sprite that can update its position…
public class Line
{
public Rectangle my_from;
public Rectangle my_destination;
public Vector2 x_finder;
public Line(Rectangle start)
{
my_destination = start;
}
public void Update()
{
x_finder = Game1.RotateVector2(x_finder,0.04f,Vector2.Zero);
my_destination.X = (int)x_finder.X;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Game1.sand, my_destination, my_from, /*new Color(my_destination.X*20,100,my_destination.Y/4)*/Color.White *1.0f, 0, Vector2.Zero, SpriteEffects.None, 0);
}
}
Here is a texture you can use:
and here is the main class, game1
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferHeight = 1080;
graphics.PreferredBackBufferWidth = 1920;
}
protected override void Initialize()
{
base.Initialize();
}
public static Texture2D sand;
Vector2 x_finder;
List<Line> lines;
protected override void LoadContent()
{
sand = Content.Load<Texture2D>(".\\sand");
spriteBatch = new SpriteBatch(GraphicsDevice);
lines = new List<Line>();
//this vector is rotated around vector.zero, so we get an x value that waves up and down...
// CHANGE this value to determine how far and fast the waves move
x_finder = new Vector2(-50,0);
//here we add a rectangle for each line of image we want wobbled.
//the rectangle will be modified dynamically by the x_finder above.
for (int i = 0; i < 1080; i++)
{
lines.Add(new Line(new Rectangle(0, i, 1920, 1)));
x_finder = (RotateVector2(x_finder, 0.02f, Vector2.Zero));
lines[i].my_destination = new Rectangle( (int)x_finder.X , lines[i].my_destination.Y, lines[i].my_destination.Width, lines[i].my_destination.Height);
lines[i].x_finder += x_finder;
lines[i].my_from = (new Rectangle(0,i,1920,1));
}
}
//THIS method just orbits a vector around another vector, here we are using it to generate wave patterns.
public static Vector2 RotateVector2(Vector2 point, float radians, Vector2 pivot)
{
float cosRadians = (float)Math.Cos(radians);
float sinRadians = (float)Math.Sin(radians);
Vector2 translatedPoint = new Vector2();
translatedPoint.X = point.X - pivot.X;
translatedPoint.Y = point.Y - pivot.Y;
Vector2 rotatedPoint = new Vector2();
rotatedPoint.X = translatedPoint.X * cosRadians - translatedPoint.Y * sinRadians + pivot.X;
rotatedPoint.Y = translatedPoint.X * sinRadians + translatedPoint.Y * cosRadians + pivot.Y;
return rotatedPoint;
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
foreach (Line line in lines)
{
line.Update();
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
// spriteBatch.Draw(sand,Vector2.Zero,Color.White);
foreach (Line line in lines)
{
line.Draw(spriteBatch);
}
spriteBatch.End();
// TODO: Add your drawing code here
base.Draw(gameTime);
}
}
Thats all there is to it…
For best results with heat waves, I think draw the image first, then draw the wave effect with a lowered alpha on top… looks more distorted.
For something like a flag, turn the alpha to 1, and dont draw the original image underneath…
Oh my god, it works. I gotta start playing around with this. Thank you so much. How can I thank you?
I’m just glad to help… I get a lot of help here myself
So yeah, that effect does the whole screen, you can of-coarse do smaller areas, and other effects…