Drawing on an image before drawing on screen in XNA using VB.NET - vb.net

I'm programming a game in XNA, using VB.NET. I want to create an intro to the game that zooms in/out the whole screen and scaling each image to accomplish this is cumbersome at best. I like to be able to draw a lot of .PNG's (or parts of them) onto a whole image, to then be able to manipulate (scale, turn etc) that whole image, before drawing it with the spriteBatch. The examples I can find use something like:
dim bitmap as New Bitmap
or
dim image as New Image
but these codes highlights the "Bitmap" or "Image" as red, and I cannot use them. I'd be thankful for any help on this issue!

SpriteBatch works with XNA Texture2D objects, whereas Bitmap and Image are System.Drawing types. They do not work together.
You can create a new RenderTarget2D, set it as active using GraphicsDevice.SetRenderTarget() and draw there using a SpriteBatch. You can then draw the stored render target to screen using a SpriteBatch, since render targets are a type of Texture2D.

So I've experimented with Petri Laarne's answer and finally come up with a workable code (most examples online are using C#, and doesn't explain the entire process). Trying to explain it here:
In Public Class Game1:
Private WithEvents graphics As GraphicsDeviceManager
Private WithEvents spriteBatch, spriteBatch2 As SpriteBatch
In Loadcontent:
Public render2 As RenderTarget2D
spriteBatch2 = New SpriteBatch(GraphicsDevice)
spriteBatch = New SpriteBatch(GraphicsDevice)
render2 = New RenderTarget2D(GraphicsDevice, 1024, 768)
In Draw:
spriteBatch2.GraphicsDevice.SetRenderTarget(render2)
GraphicsDevice.Clear(Color.Black)
srcRect = New Rectangle(440, 0, 440, 440) : destRect = New Rectangle(100, 335, 440, 440)
spriteBatch2.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend) : spriteBatch2.Draw(introNEWMirrorDecos, destRect, srcRect, Color.White) : spriteBatch2.End()
destRect = New Rectangle(300, 335, 440, 440)
spriteBatch2.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend) : spriteBatch2.Draw(introNEWMirrorDecos, destRect, srcRect, Color.White) : spriteBatch2.End()
spriteBatch2.GraphicsDevice.SetRenderTarget(Nothing)
GraphicsDevice.Clear(Color.Black)
destRect = New Rectangle(512, 384, 1024, 768) : srcRect = New Rectangle(0, 0, 1024, 768)
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend) : spriteBatch.Draw(render2, destRect, srcRect, Color.White, PI / 12, New Vector2(512, 384), SpriteEffects.None, 0) : spriteBatch.End()
This is an example code from the actual game that worked like it was intended: drawing 2 things on the alternate rendering image and then drawing them as one single image (in this case being able to rotate it by pi/12).
Any comments on how to do this differently or more efficient is appreciated, and thank's for the initial answer #Petri Laarne

Related

Can not we initialize a Font for second time in VB.NET?

I am making a 2D game in VB.NET. I use only one font object to draw strings on the form. This font is only needed in Game Menu. Therefore I dispose the font when it is not necessary and initialize it again when needed.
font_1 = New Font("Autobus Bold", 15.0)
When I use this font (font_1) to draw a string on the form, I get this error.
An unhandled exception of type 'System.ArgumentException' occurred in
System.Drawing.dll
Additional information: Parameter is not valid.
When I view the the font, it shows,
{Name = Reference to a non-shared member requires an object reference.
Size=15.0}
This error doesn't happen when the game menu is loaded for the first time (when font_1 is initialized for the first time). When the user plays the game, font is disposed. When user enters to Game Menu again, font is initialized again before it is used for drawing. When font is used for drawing a string on the window, this error happens.
It looks like error is only within the Font Family. I saw this question in few forums, but no one had given a solution. (This is my first question in a forum)
Edited : I removed the Font(font_1). But still I get the same error. Here is the code that draws the string.
Private Sub mcFramesHandler_TIMER_Tick(sender As Object, e As EventArgs) Handles mcFramesHandler_TIMER.Tick
gB.Clear(Color.Black)
gB.DrawImage(Background_IMG, 0, 0, 640, 480)
Select Case currentMode
Case GameMode.OnGame
If mcShoot_TIMER.Enabled Then gB.DrawImage(Bullet_IMG, Bullet_X, Bullet_Y, 20, 50)
If mcEneShoot_TIMER.Enabled Then gB.DrawImage(EneBullet_IMG, EneBullet_X, EneBullet_Y, 20, 50)
If Shooter_Lives Then gB.DrawImage(Shooter_IMG, Shooter_X, Bullet_Y_Def, 100, 105)
If mcMoveEnemy_TIMER.Enabled Then gB.DrawImage(Enemy_IMG, Enemy_X, 10, 100, 80)
If mcExplode_TMER.Enabled Then gB.DrawImage(Explotion_IMG, Explotion_X, Explotion_Y, 100, 80)
Case GameMode.Begining
gB.DrawString("Start", New Font("Autobus Bold", 15.0), textBrush(0), 110, 98) 'Error is generated in this line
gB.DrawString("Credits", New Font("Autobus Bold", 15.0), textBrush(1), 102, 158)
gB.DrawString("Exit", New Font("Autobus Bold", 15.0), textBrush(2), 114, 218)
End Select
Me.CreateGraphics.DrawImage(backbuffer, 0, 0, 640, 480)
End Sub
Here textBrudh(0) is a brush. gB is the Graphic object. gB successfully draws the background image before it draws the string. This happens only when Game Menu is displayed
Your support is really appreciated.
After you have finished to draw your things you need to dispose all objects around Graphics, not only the font but all (better with closure techniques like code below)
If you need a new instace of Graphics you can create this at the moment this is needed without using a Global object (when you work with Graphics).
Using gB As Graphics = Me.CreateGraphics
Using textBrush As Brush = Brushes.Black
Using font_1 As Font = New Font("Courier New", 15)
gB.DrawString("Start", font_1, textBrush, 400, 98)
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
'gB.DrawOtherthings()
End Using
End Using
End Using
Problem was with the brush (textBrush : an array of brush). When I dsipose each item in the array and re initialize, looks like something has happened to them (like they are not brushes anymore. See the error again. It says "Parameter is not valid"). So I just redim the array to 0.
Redim textBrush (0)
This clears previous items. Then I redim the array again initilizes each of them when needed.
Redim textBrush (2)
textBrush (0) = Brushes.Yellow
textBrush (1) = Brushes.Red
textBrush (2) = Brushes.Red
This array is used to change text color when up and down key is pressed.
I saw lot of people had mentioned this error in forums
{Name = Reference to a non-shared member requires an object reference. Size=15.0}
I don't what this name is, but it doesn't effect the programme. It is always like that in any Font.

Place Text in Image on Edges

This tool I wrote in Visual Basic 2010 should add an author text to images. The user is able to set the font opacity and position. To make things easier I wanted some position presets as one can see in the bottom right corner. The calculation I am using is (bottom right in this case:
Dim textSize As Size = TextRenderer.MeasureText(tagString + curText, curFont)
tmpPos = New Point(srcImg.Width - textSize.Width - 10, srcImg.Height - textSize.Height - 10)
As you can see this works perfectly for this example picture. Where as on some the text just clips out.
First One: 1024x768 | Detected Font Size: 680x72
Second One: 1688x1125 | Detected Font Size: 680x72
I suspect this has something to do with the aspect ratio of the images but I do not know how to fix it.
The text is drawn like that:
brush = New SolidBrush(color.FromArgb(alpha, color))
gr = Graphics.FromImage(editImg)
gr.DrawString(tagString + text, font, brush, pos)
HauptBild.Image = editImg
I found this http://www.codeproject.com/Articles/20923/Mouse-Position-over-Image-in-a-PictureBox and it answered my questions.
is this problem only occuring in your preview or also in the converted File? Please post the Code how you save the New Image. I think you have Set a sizemode in your picturebox which is the Problem. Try it without the sizemode.
Will be better to see more your code, but, as i understand by TextRenderer class it is System.Windows.Forms. Just do not use Graphics, created from control (i suppose it is pictureBox with sizemode:Zoom), use Graphics, created from your image instead.
Here is code (sorry, C#), which loads image from file, draws text starting from the same coordinate and places on puctureBox1. Text always starts from Point(100,100).
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Filter = "Image files|*.jpeg;*.png;*.jpg;*.gif;*.bmp";
if(openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
Bitmap orig=(Bitmap)Bitmap.FromFile(openFileDialog1.FileName);
//workaround for images with color table, see remarks here https://msdn.microsoft.com/en-us/library/system.drawing.graphics.fromimage(v=vs.110).aspx
Bitmap bmp=orig.Clone(new Rectangle(0, 0, orig.Width, orig.Height), System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
Graphics g = Graphics.FromImage(bmp);
g.DrawString("hello", new Font(this.Font.FontFamily,30,FontStyle.Bold ) , new System.Drawing.SolidBrush(System.Drawing.Color.Yellow ), new Point(100, 100));
this.pictureBox1.Image = bmp;
orig.Dispose();
}
catch (Exception ex)
{
MessageBox.Show("Something goes wrong: " + ex.Message+ "\\n"+ ex.StackTrace );
}
}

libgdx generate texture at runtime

Hi i need to create a texture that is made up of other textures overlayed. I've tried using pixmap however it is noticably slow. The idea is to create a "snapshot" of a dialog so that it can be animated as it shows up and when it is dismissed. Please help
This is the code that I am using:
texture_dialog.getTextureData().prepare();
Pixmap pm1 = texture_dialog.getTextureData().consumePixmap();
btn_ok.getTexture().getTextureData().prepare();
Pixmap pm = btn_ok.getTexture().getTextureData().consumePixmap();
pm1.drawPixmap(pm, pm1.getWidth()/2 - pm.getWidth()/2, pm1.getHeight() - pm.getHeight() - 52);
textureSnapShot = new Texture(pm1, true);
pm1.dispose();
pm.dispose();
textureSnapShot.setFilter(TextureFilter.MipMapLinearLinear, TextureFilter.MipMapLinearLinear);
spriteSnapShot = new Sprite(textureSnapShot);
I've tried using a FrameBuffer as follows:
SpriteBatch sb = new SpriteBatch();
sb.setProjectionMatrix(camera.combined);
FrameBuffer fbo = new FrameBuffer(Format.RGBA8888, texture_dialog.getWidth(), texture_dialog.getHeight(), false);
fbo.begin();
sb.begin();
sb.draw(texture_dialog, 0, 0);
sb.draw(btn_ok.getTexture(), texture_dialog.getWidth()/2 - btn_ok.getWidth()/2, 52);
sb.end();
fbo.end();
sb.dispose();
textureSnapShot = fbo.getColorBufferTexture();
//textureSnapShot.setFilter(TextureFilter.MipMapLinearLinear, TextureFilter.MipMapLinearLinear);
spriteSnapShot = new Sprite(textureSnapShot);
The results are as follows:
http://medialinestudio.co.za/screens.png
Left: Pixmap Right: FrameBuffer
Pixmap has the correct result but too slow. FrameBuffer is faster but incorrect result
FBO is definitely what you should use for your need.
read this post : libgdx SpriteBatch render to texture
what you missing is :
create a camera with correct width/height and position to fit your drawing inside the FBO viewport (0,0,Width,Height)
flip the output texture (m_fboRegion.flip(false, true))

Changing text color in PdfSharp

I'm currently creating a PDF with PdfSharp which mostly consists of text and some images.
The text elements have different colors. My problem is that as soon as I use a different color than the color I started with, the text is not visible in the resulting PDF (e.g. I start with black text, switch to a red text, the red text is not visible). All text elements are in the resulting PDF (I can select them), but the red elements are invisible.
So here is the code:
// Create a new PDF document with one page
var document = new PdfDocument();
var page = document.AddPage();
page.Width = 800;
page.Height = 600;
var defaultFont = new XFont("Arial", 12, XFontStyle.Regular, new XPdfFontOptions(PdfFontEmbedding.Always));
var gfx = XGraphics.FromPdfPage(page);
// black text
gfx.DrawString("black", defaultFont, XBrushes.Black, new XRect(x, y, width, height), XStringFormats.Center);
// red text
gfx.DrawString("red", defaultFont, XBrushes.Red, new XRect(x2, y2, width2, height2), XStringFormats.Center);
I've already found a solution (re-creating the XGraphics object) but it's quiete messy because it needs to be called after each color change:
// ...
// black text
gfx.DrawString("black", defaultFont, XBrushes.Black, new XRect(x, y, width, height), XStringFormats.Center);
// disposing the old graphics context and creating a new one seems to help
gfx.Dispose();
gfx = XGraphics.FromPdfPage(page);
// red text
gfx.DrawString("red", defaultFont, XBrushes.Red, new XRect(x2, y2, width2, height2), XStringFormats.Center);
I guess there is a better solution, but I couldn't find one yet.
Edit
As suggested in this answer, I wanted to create a SSCCE. During the creation I found the actual bug. Instead of XBrushes.Red I used an own defined XBrush, but didn't mention it in the above code snippet, because I thought it was unnecessary.
As already mentioned in the last section of the question, I used an own defined brush instead of XBrushes.Red.
I defined it the following way:
XBrush redBrush = new XSolidBrush(new XColor {R = 207, G = 0, B = 44});
This way the brush only worked after I disposed the graphics object and created a new one. But after some googling I found the correct way to define a brush:
XBrush redBrush = new XSolidBrush(XColor.FromArgb(207, 0, 44));
I tried to replicate your problem using your code snippet and PDFsharp version 1.32. I used VS Express 2013 which automatically converted all projects to .NET 4.5.
I tried both builds (GDI+ and WPF) and all colours worked fine for me.
So instead of just a code snippet you should provide an SSCCE.
See also:
http://forum.pdfsharp.net/viewtopic.php?p=2094#p2094

vb.net code to make a image transparent

I wish to make a bitmap image (.bmp) transparent using VB.NET code. Kindly help me.
I found the key was using the imageAttributes class. Basically set the color key to the color you are using to represent the transparent area, and use one of the drawImage calls that accepts an imageAttribute parameter...
Imports System.Drawing.Imaging
' and in a sub somewhere:
Private mImageAttributes As New ImageAttributes
mImageAttributes.SetColorKey(Color.FromArgb(0, 220, 20, 255),
Color.FromArgb(0, 220, 20, 255))
Dim imageRectangle As New Rectangle(pX, pY, pBitmap.Width, pBitmap.Height)
e.Graphics.DrawImage(pBitmap, imageRectangle, 0, 0, pBitmap.Width, pBitmap.Height,
GraphicsUnit.Pixel, mImageAttributes)
VS 2012
Dim watermark_bm2 As Bitmap = 'someimage(from file or global resource)
watermark_bm2.MakeTransparent()
This msdn article gives full details on how to do this
Here is another article, but code sample is in c#