How to display a bitmap in SharpDX? - c#

I am trying to make a very simple game for learning purposes, but i am struggling with SharpDX.
Basically what i'm trying to achieve is: Take several bitmap images and display them in a window on certain x y coordinates. After that, i will clear the window a display those images again, but on different x y coordinates (a very basic game loop basically, which means the images will be re-displayed many times per second).
I have this code:
using SharpDX;
using SharpDX.Toolkit;
internal sealed class MyGame : Game
{
private readonly GraphicsDeviceManager _graphicsDeviceManager;
public MyGame()
{
_graphicsDeviceManager = new GraphicsDeviceManager(this);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
base.Draw(gameTime);
}
}
-------
public partial class MainWindow : Window
{
public MainWindow()
{
using (var game = new MyGame())
game.Run();
}
}
When compiled, it simply opens a window with a blue background.
Then, I have two images:
var img = new BitmapImage(new Uri("C:/img/pic1.png"));
var img1 = new BitmapImage(new Uri("C:/img/pic2.png"));
And this is where the problem lies, i am unable to figure out, how to take these two images and actually display them in the window. img should be displayed at x10 y50 coordinates (or in other words, 10 pixels from the left side of the window, and 50 pixels from the top) and img1 at x200 y150 coordinates.
I'm sure the solution is something easy, but I just can't figure it out.

Inside MyGame.
Firstly, in LoadContent method load the texture:
private Texture2D myTexture;
protected override void LoadContent()
{
this.myTexture = this.Content.Load<Texture2D>("Path to img");
}
then in Draw;
protected override void Draw(GameTime gameTime)
{
var sprite = new SpriteBatch(this.GraphicsDevice);
sprite.Begin();
sprite.Draw(this.myTexture,
new Rectangle(10, 50, // position: x and y coordiantes in pixels
/* width and height below
- do not remeber order: */
25, 25),
Color.White);
sprite.End();
base.Draw(gameTime);
}
This is the basic way to draw anything with SharpDX.

Related

adding a background in monogame isn't working

I just want to add a background image in my c# monogame main menu. I already have a main menu with buttons and a working game. Just the background is missing.
This is a part of my code:
public void LoadAssets()
{
background = ScreenManager.Texture("background");
[...] //unimportant stuff for this problem
}
public void Draw(GameTime gameTime)
{
SpriteBatch spriteBatch= new SpriteBatch();
spriteBatch.Begin();
spriteBatch.Draw(background, new Rectangle(0, 0, 800, 480), Color.White);
spriteBatch.End();
foreach (var button in mButtons)
{
button.Draw(ScreenManager.mSprites);
}
}
I get the following error CS7036 C# There is no argument given that corresponds to the required formal parameter of "graphicsDevice" from "SpriteBatch.SpriteBatch(GraphicsDevice).
I included the image in content. I don't know where is my error.
Thanks, for help!
First, you do NOT create a new SpriteBatch instance each draw call. That would be like 60 new instances per second (at 60fps)
Instead, you create it in your LoadContent() method and use it all the way in your Draw()
method:
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
[...]
}
Second, GraphicsDevice is definetly available in your Draw-Call as long as you have not messed something up really bad ;)

c# draw a straight line

How do i get a REAL straight line with c#? the code below draws a line, great, but this line is not perfect, it's not pixel by pixel straight, is there better code out there that produces a better, accurate straight line?
namespace Dimension3D
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void canvas_Paint(object sender, PaintEventArgs e)
{
Graphics gObject = canvas.CreateGraphics();
Brush red = new SolidBrush(Color.Red);
Pen redPen = new Pen(red, 8);
gObject.DrawLine(redPen, 10, 10, 35, 500);
}
}
}
What you see as a straight line is actually a trick. It is "smoothed" out so the jagged parts are surrounded by shaded pixels (See Below). This explains how to do it better than I can.
https://msdn.microsoft.com/en-us/library/system.drawing.graphics.smoothingmode.aspx
The images below are the same. The top is just zoomed in.
You have to turn off AntiAlias for drawing pixel perfect lines.
gObject.SmothingMode = SmoothingMode.None;
Don't forget to put it back to Default after so you don't change image rendering or other stuff that needs anitialias to look nice

What is the prefered way or spot using Artemis in monogame or xna to add a mouse click rectangle

Using Artemis, Visual Studio, C# and Monogame.
Just starting to get a grasp on Artemis, but looking fo the proper place to add a clickable rectangle/area to an entity, there will be multiple entities on the screen.
Basic simple idea, i have small square sprites randomly showing and moving in the 2D play area.
I need to be able to click on them and keeping it simple, delete the square.
In Artemis you have Components, Entities, Systems.
I know i'll be adding this rectangle area to the Texture2D square, guessing it should be its own component.
Trying to figure out
Get the rectangle the size of the square, and stay with the square when it moves.
How in some system, detect that this square was clicked or touched.
UPDATE
In my DrawableGameComponent entity.
DrawPosition is a vector2 and set in the Main Game routine.
It is the location of my square.
I use that and texture size to calculate the size and location of my rectangle.
AreItemsIntersecting function will take the Mouse position when the screen is clicked, then i used that to create a little rect, and then checked if the 2 intersect. If they do, then the object was clicked.
public override void Update(GameTime gameTime)
{
var bx = DrawPosition.X;
var by = DrawPosition.Y;
var w = _texture.Bounds.Width;
var h = _texture.Bounds.Height;
_bounds = new Rectangle((int)bx, (int)by, w+1, h+1);
base.Update(gameTime);
}
public override void Draw(GameTime gameTime)
{
if (_texture != null)
{
_spriteBatch.Begin();
_spriteBatch.Draw(_texture, DrawPosition, Color.White);
_spriteBatch.Draw(_texture, _bounds, Color.Transparent);
_spriteBatch.End();
base.Draw(gameTime);
}
public bool AreItemsIntersecting(int x, int y)
{
var vect = new Rectangle(x, y, 1, 1);
if (vect.Intersects(_bounds))
{
return true;
}
return false;
}
I would create a BoundingBox component. It will expose a Bounds property of type Rectangle.
With this component in place you can create a KillEntityOnClickSystem to handle the removal of clicked entities. You'll just need to check whether the mouse is inside the Bounds of the entity BoundingBox when the mouse button is clicked.
Hope this helps!

Fast 2D graphics in WPF

I need to draw a large amount of 2D elements in WPF, such as lines and polygons. Their position also needs to be updated constantly.
I have looked at many of the answers here which mostly suggested using DrawingVisual or overriding the OnRender function. To test these methods I've implemented a simple particle system rendering 10000 ellipses and I find that the drawing performance is still really terrible using both of these approaches. On my PC I can't get much above 5-10 frames a second. which is totally unacceptable when you consider that I easily draw 1/2 million particles smoothly using other technologies.
So my question is, am I running against a technical limitation here of WPF or am I missing something? Is there something else I can use? any suggestions welcome.
Here the code I tried
content of MainWindow.xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="500" Width="500" Loaded="Window_Loaded">
<Grid Name="xamlGrid">
</Grid>
</Window>
content of MainWindow.xaml.cs:
using System.Windows.Threading;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
EllipseBounce[] _particles;
DispatcherTimer _timer = new DispatcherTimer();
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//particles with Ellipse Geometry
_particles = new EllipseBounce[10000];
//define area particles can bounce around in
Rect stage = new Rect(0, 0, 500, 500);
//seed particles with random velocity and position
Random rand = new Random();
//populate
for (int i = 0; i < _particles.Length; i++)
{
Point pos = new Point((float)(rand.NextDouble() * stage.Width + stage.X), (float)(rand.NextDouble() * stage.Height + stage.Y));
Point vel = new Point((float)(rand.NextDouble() * 5 - 2.5), (float)(rand.NextDouble() * 5 - 2.5));
_particles[i] = new EllipseBounce(stage, pos, vel, 2);
}
//add to particle system - this will draw particles via onrender method
ParticleSystem ps = new ParticleSystem(_particles);
//at this element to the grid (assumes we have a Grid in xaml named 'xmalGrid'
xamlGrid.Children.Add(ps);
//set up and update function for the particle position
_timer.Tick += _timer_Tick;
_timer.Interval = new TimeSpan(0, 0, 0, 0, 1000 / 60); //update at 60 fps
_timer.Start();
}
void _timer_Tick(object sender, EventArgs e)
{
for (int i = 0; i < _particles.Length; i++)
{
_particles[i].Update();
}
}
}
/// <summary>
/// Framework elements that draws particles
/// </summary>
public class ParticleSystem : FrameworkElement
{
private DrawingGroup _drawingGroup;
public ParticleSystem(EllipseBounce[] particles)
{
_drawingGroup = new DrawingGroup();
for (int i = 0; i < particles.Length; i++)
{
EllipseGeometry eg = particles[i].EllipseGeometry;
Brush col = Brushes.Black;
col.Freeze();
GeometryDrawing gd = new GeometryDrawing(col, null, eg);
_drawingGroup.Children.Add(gd);
}
}
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
drawingContext.DrawDrawing(_drawingGroup);
}
}
/// <summary>
/// simple class that implements 2d particle movements that bounce from walls
/// </summary>
public class SimpleBounce2D
{
protected Point _position;
protected Point _velocity;
protected Rect _stage;
public SimpleBounce2D(Rect stage, Point pos,Point vel)
{
_stage = stage;
_position = pos;
_velocity = vel;
}
public double X
{
get
{
return _position.X;
}
}
public double Y
{
get
{
return _position.Y;
}
}
public virtual void Update()
{
UpdatePosition();
BoundaryCheck();
}
private void UpdatePosition()
{
_position.X += _velocity.X;
_position.Y += _velocity.Y;
}
private void BoundaryCheck()
{
if (_position.X > _stage.Width + _stage.X)
{
_velocity.X = -_velocity.X;
_position.X = _stage.Width + _stage.X;
}
if (_position.X < _stage.X)
{
_velocity.X = -_velocity.X;
_position.X = _stage.X;
}
if (_position.Y > _stage.Height + _stage.Y)
{
_velocity.Y = -_velocity.Y;
_position.Y = _stage.Height + _stage.Y;
}
if (_position.Y < _stage.Y)
{
_velocity.Y = -_velocity.Y;
_position.Y = _stage.Y;
}
}
}
/// <summary>
/// extend simplebounce2d to add ellipse geometry and update position in the WPF construct
/// </summary>
public class EllipseBounce : SimpleBounce2D
{
protected EllipseGeometry _ellipse;
public EllipseBounce(Rect stage,Point pos, Point vel, float radius)
: base(stage, pos, vel)
{
_ellipse = new EllipseGeometry(pos, radius, radius);
}
public EllipseGeometry EllipseGeometry
{
get
{
return _ellipse;
}
}
public override void Update()
{
base.Update();
_ellipse.Center = _position;
}
}
}
I believe the sample code provided is pretty much as good as it gets, and is showcasing the limits of the framework. In my measurements I profiled an average cost of 15-25ms is attributed to render-overhead. In essence we speak here about just the modification of the centre (dependency-) property, which is quite expensive. I presume it is expensive because it propagates the changes to mil-core directly.
One important note is that the overhead cost is proportional to the amount of objects whose position are changed in the simulation. Rendering a large quantity of objects on itself is not an issue when a majority of objects are temporal coherent i.e. don't change positions.
The best alternative approach for this situation is to resort to D3DImage, which is an element for the Windows Presentation Foundation to present information rendered with DirectX. Generally spoken that approach should be effective, performance wise.
You could try a WriteableBitmap, and produce the image using faster code on a background thread. However, the only thing you can do with it is copy bitmap data, so you either have to code your own primitive drawing routines, or (which might even work in your case) create a "stamp" image which you copy to everywhere your particles go...
The fastest WPF drawing method I have found is to:
create a DrawingGroup "backingStore".
during OnRender(), draw my drawing group to the drawing context
anytime I want, backingStore.Open() and draw new graphics objects into it
The surprising thing about this for me, coming from Windows.Forms.. is that I can update my DrawingGroup after I've added it to the DrawingContext during OnRender(). This is updating the existing retained drawing commands in the WPF drawing tree and triggering an efficient repaint.
In a simple app I've coded in both Windows.Forms and WPF (SoundLevelMonitor), this method empirically feels pretty similar in performance to immediate OnPaint() GDI drawing.
I think WPF did a dis-service by calling the method OnRender(), it might be better termed AccumulateDrawingObjects()
This basically looks like:
DrawingGroup backingStore = new DrawingGroup();
protected override void OnRender(DrawingContext drawingContext) {
base.OnRender(drawingContext);
Render(); // put content into our backingStore
drawingContext.DrawDrawing(backingStore);
}
// I can call this anytime, and it'll update my visual drawing
// without ever triggering layout or OnRender()
private void Render() {
var drawingContext = backingStore.Open();
Render(drawingContext);
drawingContext.Close();
}
I've also tried using RenderTargetBitmap and WriteableBitmap, both to an Image.Source, and written directly to a DrawingContext. The above method is faster.
In windows forms these kind of things made me fall back to;
Set Visible=False for the highest level container (e.g. canvas of the form itself)
Draw a lot
Set Visible=True
Not sure if WPF supports this.
Here are some of the things you may try: (I tried them with your sample and it seems to look faster (at least on my system)).
Use Canvas instead of Grid (unless you have other reasons). Play BitmapScalingMode and CachingHint:
<Canvas Name="xamlGrid" RenderOptions.BitmapScalingMode="LowQuality" RenderOptions.CachingHint="Cache" IsHitTestVisible = "False">
</Canvas>
Add a StaticResource for Brush used in GeometryDrawing:
<SolidColorBrush x:Key="MyBrush" Color="DarkBlue"/>
in code use as:
GeometryDrawing gd = new GeometryDrawing((SolidColorBrush)this.FindResource("MyBrush"), null, eg);
I hope this helps.

XNA weird 3D painting when painting text

I'm working on a 3D Spaceship game with XNA 3.1
I tried to separate my painting code from the game logic (altought XNA makes this almost).
I'm using a special static class that paints my models on screen... the main Game class uses this code at painting:
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.Black);
// Draws the stage (the skybox and objects like rocks)
stageManager.Draw(gameTime, GraphicsDevice, camera);
// Draws each player and each Enemy on stage given the camera
foreach (Player p in players)
p.Draw(camera);
foreach(Enemy e in enemies)
e.Draw(camera);
if(Configuration.Debug)
col.renderColBoundings(GraphicsDevice, camera);
GraphicHelper.drawOverlayText("50", "10"); // "Error" line...
base.Draw(gameTime);
}
But when I paint text, something weird occurs... Here's an image (original):
As you can see, everything looks overlapped (but in place)... Like the spaceship turbines.
The code inside GraphicHelper.drawOverlayText is this:
public static void drawOverlayText(String p1Hp, String currEnemies)
{
string text1 = "Player1: " + p1Hp;
string text2 = "Enemies: " + currEnemies + "/10";
string text3 = "Space Hogs Beta";
spriteBatch.Begin();
// Draw the string twice to create a drop shadow, first colored black
// and offset one pixel to the bottom right, then again in white at the
// intended position. This makes text easier to read over the background.
spriteBatch.DrawString(font, text1, new Vector2(651, 11), Color.Gray);
spriteBatch.DrawString(font, text1, new Vector2(650, 10), Color.White);
spriteBatch.DrawString(font, text2, new Vector2(851, 11), Color.Gray);
spriteBatch.DrawString(font, text2, new Vector2(850, 10), Color.White);
spriteBatch.DrawString(font, text3, new Vector2(741, 611), Color.Gray);
spriteBatch.DrawString(font, text3, new Vector2(740, 610), Color.White);
spriteBatch.End();
}
And this static class has this attributes:
static ContentManager content;
static GraphicsDevice graphics;
static Camera camera;
static Dictionary<String, Model> models = new Dictionary<string, Model>();
static SpriteBatch spriteBatch;
static SpriteFont font;
public static void initHelper(ContentManager c, GraphicsDevice g, Camera cam)
{
content = c;
graphics = g;
camera = cam;
spriteBatch = new SpriteBatch(g);
font = c.Load<SpriteFont>("Fonts/main");
}
Hope you can help me :)
The odd rendering you are seeing is because the depth buffer is turned off. It gets turned off when you use SpriteBatch. This is a known oddity of the XNA 3.1 API. XNA 4.0 at least makes it a bit more obvious that this is happening.
Here is an explanation of what render states are changed by SpriteBatch in XNA 3.1. And here is the same thing for XNA 4.0.
The solution is to basically set your render states back to what you want them to be, after using SpriteBatch. In this case, at least, set:
GraphicsDevice.RenderState.DepthBufferEnable = true;
(There may also be some other states in there you want to change back.)

Categories