Nov 232013
 

We have seen in previous article 8 how to perform pixel collision.
Altough it worked perfectly, it only worked on non rotated shapes.

But in some cases, your shape will rotate (like a car in a racing game – see article « A racing car game »).

To perform pixel collision for a rotated shape, here below the steps :

-you first need to draw a rotated rectangle around your shape
-you then need to draw a bounding rectanle around that rotated rectangle (also called AABB : Axis Aligned Bounding Box)
-finally you can check whether 2 AABB intersects, and if so, if in the intersected region, we have 2 non transparent pixels (colliding) or not

The source code : XNA_DEMO_18
Note : the project contains a class named primitives2d which is used only to draw lines/rectangles around my objects.

Lets illustrate this with some screenshots.

Lets rotate our rectangle along with my rocket
pixel2

Lets define our bounding box
pixel3

Despite bounding boxes intersecting, we dont detect collision yet
pixel4

Here we go ! In the intersection region, there are 2 non transparent pixels
pixel5

 Posted by at 17 h 41 min
Nov 232013
 

One annoying fact around XNA is that it supports natively only xbox gamepads.

Well Nuclex fixes that for us : )
See here : http://nuclexframework.codeplex.com/ .
Download, unzip and add a reference in your project to nuclex.input.dll.

The source code : XNA_DEMO_21 .

Now lets see the code.

All the magic is in the object inputmanager.
Then, just like we would check the state of keyboard keys, we will do the same with the gamepad buttons.

If you want to check the state of the first DirectInput game pad in your system instead, just write:
If (input.GetGamePad(ExtendedPlayerIndex.Five).GetState().Buttons.X = ButtonState.Pressed) Then ...
Notice that DirectInput Gamepads (as opposed to xbox gamepads) starts at index 5. However, if you have an xbox pad plugged, index 5 will also work.


Imports Microsoft.Xna.Framework
Imports Microsoft.Xna.Framework.Graphics
Imports Microsoft.Xna.Framework.Audio
Imports Microsoft.Xna.Framework.Content
Imports Microsoft.Xna.Framework.Media
Imports Microsoft.Xna.Framework.Input
Imports Nuclex.Input

Public Class Game
Inherits Microsoft.Xna.Framework.Game
Dim graphics As GraphicsDeviceManager
Dim SpriteBatch As SpriteBatch
Dim input As InputManager
Dim myfont As SpriteFont
Dim msg As String = "."
Dim dummyTexture As Texture2D
Dim rc As Rectangle

Public Sub New()
graphics = New GraphicsDeviceManager(Me)
input = New InputManager(Services, Window.Handle)
Components.Add(input)
Window.Title = "Test"
End Sub

Protected Overrides Sub Initialize()
MyBase.Initialize()
End Sub
Protected Overrides Sub LoadContent()
SpriteBatch = New SpriteBatch(GraphicsDevice)
myfont = Content.Load(Of SpriteFont)("xnb\myfont")
dummyTexture = New Texture2D(GraphicsDevice, 1, 1)
'
Dim c(0) As Color
c(0) = Color.White
dummyTexture.SetData(Of Color)(c)
'
rc = New Rectangle(100, 100, 10, 10)
'
MyBase.LoadContent()

End Sub
Protected Overrides Sub UnloadContent()
MyBase.UnloadContent()
End Sub

Protected Overrides Sub Update(ByVal gameTime As Microsoft.Xna.Framework.GameTime)
'right
If (Keyboard.GetState.IsKeyDown(Keys.Right)) Or (input.GetGamePad(ExtendedPlayerIndex.Five).GetState().Buttons.X = ButtonState.Pressed) Then
msg = "right"
rc.X += 1
End If
'left
If (Keyboard.GetState.IsKeyDown(Keys.Left)) Or (input.GetGamePad(ExtendedPlayerIndex.Five).GetState().Buttons.A = ButtonState.Pressed) Then
msg = "left"
rc.X -= 1
End If
'up
If (Keyboard.GetState.IsKeyDown(Keys.Up)) Or (input.GetGamePad(ExtendedPlayerIndex.Five).GetState().Buttons.RightShoulder = ButtonState.Pressed) Then
msg = "up"
rc.Y -= 1
End If
'down
If (Keyboard.GetState.IsKeyDown(Keys.Down)) Or (input.GetGamePad(ExtendedPlayerIndex.Five).GetState().Buttons.LeftShoulder = ButtonState.Pressed) Then
msg = "down"
rc.Y += 1
End If
MyBase.Update(gameTime)
End Sub

Protected Overrides Sub Draw(ByVal gameTime As Microsoft.Xna.Framework.GameTime)
GraphicsDevice.Clear(Color.CornflowerBlue)
SpriteBatch.Begin()
SpriteBatch.DrawString(myfont, msg, New Vector2(10, 10), Color.White)
SpriteBatch.Draw(dummyTexture, rc, Color.White)
SpriteBatch.End()
MyBase.Draw(gameTime)
End Sub

End Class

 Posted by at 13 h 18 min
Nov 222013
 

Sometimes you need a simple progressbar in your XNA game to display game points, life, etc.

Lets do it quick and simple with rectangles only:
-One gray rectangle for the fix bar, and one red rectangle for the moving bar (use +/- keys).
-a very simple math formula to draw the current value against the width of the bar : progressbar_width * progressbar_value / progressbar_max

The sourcecode : Here


Imports Microsoft.Xna.Framework
Imports Microsoft.Xna.Framework.Graphics
Imports Microsoft.Xna.Framework.Audio
Imports Microsoft.Xna.Framework.Content
Imports Microsoft.Xna.Framework.Media
Imports Microsoft.Xna.Framework.Input

Public Class Game
Inherits Microsoft.Xna.Framework.Game
'Fields in our game graphic manager etc'
Dim graphics As GraphicsDeviceManager
Dim spritebatch As SpriteBatch
Dim dummyTexture As Texture2D
Dim progressbar_max = 100
Dim progressbar_value As Integer = progressbar_max
Dim progressbar_width As Integer = 250
Dim font As SpriteFont

Public Sub New()
graphics = New GraphicsDeviceManager(Me)
Window.Title = "Test"
graphics.PreferredBackBufferWidth = 400
graphics.PreferredBackBufferHeight = 200
End Sub

Protected Overrides Sub Initialize()
MyBase.Initialize()
End Sub
Protected Overrides Sub LoadContent()
spritebatch = New SpriteBatch(GraphicsDevice)
dummyTexture = New Texture2D(GraphicsDevice, 1, 1)
Dim c(0) As Color
c(0) = Color.White
dummyTexture.SetData(Of Color)(c)
'
font = Content.Load(Of SpriteFont)("xnb\myfont")
MyBase.LoadContent()
End Sub
Protected Overrides Sub UnloadContent()
MyBase.UnloadContent()
End Sub

Protected Overrides Sub Update(ByVal gameTime As Microsoft.Xna.Framework.GameTime)
If Keyboard.GetState.IsKeyDown(Keys.Add) Then progressbar_value += 1
If Keyboard.GetState.IsKeyDown(Keys.Subtract) Then progressbar_value -= 1
If progressbar_value >= progressbar_max Then progressbar_value = progressbar_max
If progressbar_value <= 0 Then progressbar_value = 0 MyBase.Update(gameTime) End Sub Protected Overrides Sub Draw(ByVal gameTime As Microsoft.Xna.Framework.GameTime) GraphicsDevice.Clear(Color.Blue) spritebatch.Begin() spritebatch.DrawString(font, progressbar_value, New Vector2(10, 10), Color.White) spritebatch.Draw(dummyTexture, New Rectangle(100, 10, progressbar_width, 10), Color.Gray) spritebatch.Draw(dummyTexture, New Rectangle(100, 10, progressbar_width * progressbar_value / progressbar_max, 10), Color.Red) spritebatch.End() MyBase.Draw(gameTime) End Sub End Class

 Posted by at 23 h 40 min
Nov 172013
 

So now you have made this sweet little XNA game of yours and you want to distribute it to friends.

Sure you could give them the content of your debug/release folder but thats a lot of files in there may be not needed for simple execution.
Not to mention you would like to distribute the XNA run time with it.
Why not package all this in a friendly setup that allow one to install/deinstall?

Well lets use Inno Setup.

Bere below a script that will allow you to make one standalone package handling it all.

Adapt paths and filenames to your project.


[Files]
Source: XNA_BASE1.exe; DestDir: {app}
Source: *.dll; DestDir: {app}
Source: xnb\*; DestDir: {app}\xnb
Source: xnafx40_redist.msi; DestDir: {tmp}; Flags: deleteafterinstall
[Icons]
Name: "{group}\Shooting"; Filename: "{app}\XNA_BASE1.exe"; WorkingDir: "{app}"
Name: "{group}\Uninstall Shooting"; Filename: "{uninstallexe}"
[Run]
Filename: {tmp}\xnafx40_redist.msi; Check: ask_; Flags: shellexec waituntilterminated; StatusMsg: "running"
[Code]
function Ask_():Boolean;
begin
result:=false;
if MsgBox('Install XNA Runtime? Needed to run the game', mbConfirmation, MB_YESNO) = IDYES then result:=true
end;
[Dirs]
Name: {app}\xnb
[Setup]
AppName=Shooting
AppVersion=1.0
DefaultDirName={pf}\shooting
DefaultGroupName=Shooting
UninstallDisplayIcon={app}\uninstall.exe
Compression=lzma2
SolidCompression=yes
SourceDir=C:\Projects\XNA_DEMO_12_shooting\XNA_BASE1\bin\Debug
OutputDir=C:\Projects\XNA_DEMO_12_shooting\installer

inno1

inno2

inno3

 Posted by at 18 h 34 min
Nov 172013
 

A short recap of recent articles around VB.Net and XNA :

VB.Net and XNA : Article 9 – A Pong Game
VB.Net and XNA : Vroom V1
VB.Net and XNA : Article 8 (pixel collision)
VB.Net and XNA : Article 7 (Scrolling)
VB.Net and XNA : Article 6 (move a texture, add a background, play some sound)
VB.Net and XNA : Article 5 (mouse input)
VB.NET and XNA : Article 4 (keyboard input)
VB.NET and XNA : Article 3 (draw text)
VB.Net and XNA : Article 2 (moving texture)
VB.Net and XNA : Article 1 (skeleton class)
VB.Net and XNA : Article 0 (introduction)

 Posted by at 12 h 57 min
Nov 162013
 

This time lets see how, without any external texture, we will animate forms and use collision detection.

To illustrate this, lets make a Pong game.

We will need to draw 3 rectangles : 2 bars and one ball.
The update method will manage check the keyboard, move the positions of each rectangle and check collision thru the intersect rectangle method.

The code : XNA_DEMO_17
up/down for player2, z/s for player1 : as simple as that.

See below a short video.

Enjoy

 Posted by at 18 h 58 min
Nov 162013
 

Using all previous articles, lets make a (almost complete) car racing game which we will call Vroom V1.

This is a mono screen game (v2 will be multiple screens).
This is a one player game (v2 will multi players).
Gamepad is not yet supported (v2 will).
A score.txt file is generated at the end of each track.

V1 and V2 have 8 tracks (v2 may have more).

A v3 in the future may support network games, extra items on the track, choose controls, choose car colors, choose difficulty, etc.

Controls are easy :
-F1 to start the track.
-up/down to speed up/speed down.
-left/right to turn left/right.
-hitting the side tracks will slow down the speed.

Working but not satisfied : could not use the pixel detection (since car is rotating) and therefore went to color detection.

A next article will review pixel collision with rotation shapes.

Any feedback, suggestions, ideas, remarks welcome 🙂

Binary here : vrooom
If you want the source code, please contact me and I’ll be happy to share.
Remember that you have to install xna runtime.

EDIT : code source here :vroom_v1_src

EDIT : Look at which is an improved version.

Thanks to my son Ewen who was my beta tester (and graphist) on this one 🙂

 Posted by at 15 h 18 min
Nov 162013
 

Today, lets see how to detect two sprites (i.e moving textures) colliding.
Pixel collision is the basic of any game.

The principle is the following :
first we need to define the region the two image rectangles intersect,
then we will iterate through each pixel in that region, and compare the alpha value of each image of each pixel.
If neither has an alpha value of 0 (transparent), they are both considered colliding.
See original discussion here.

A picture illustrating this priniciple :
xna_pixel_collision

In the attached code, we will
-setup a background and 2 balls
-update the balls position and make a sound when we touch the screen boundaries
-detect if the balls are colliding and if yes, make a sound

Note : this does not cover rotating shapes as this will be covered in a future article.

Enjoy.

xna_demo_6

 Posted by at 12 h 39 min
Nov 082013
 

This time lets scree how to make a scrolling in VB.Net and XNA.

Rather simple : the idea is to load a texture and to draw it into 2 rectangles, next to each other, and to update the rectangles position.

The project files : XNA_DEMO_8


Imports Microsoft.Xna.Framework
Imports Microsoft.Xna.Framework.Graphics
Imports Microsoft.Xna.Framework.Audio
Imports Microsoft.Xna.Framework.Content
Imports Microsoft.Xna.Framework.Media
Imports Microsoft.Xna.Framework.Input

Public Class Game
Inherits Microsoft.Xna.Framework.Game
'Fields in our game graphic manager etc'
Dim graphics As GraphicsDeviceManager
' // 1. Load a Texture2D and SpriteBatch as normal.
Dim texture1 As Texture2D
Dim spriteBatch As SpriteBatch
' // 2. Create two rectangles for the texture.
Dim rectangle1 As Rectangle
Dim rectangle2 As Rectangle
'// 3. step for the scrolling
Dim istep As Integer = 5
'// some text we will display on screen
Dim font1 As SpriteFont
Dim msg As String

Public Sub New()
graphics = New GraphicsDeviceManager(Me)
Window.Title = "lets Scroll!"
graphics.PreferredBackBufferWidth = 800
graphics.PreferredBackBufferHeight = 410
End Sub

Protected Overrides Sub Initialize()
'// 3a. rectangle1 and 2 should be equal to the
'// dimension of the texture.
rectangle1 = New Rectangle(0, 0, 2048, 410)
'// 3b. Position rectangle2 to the immediate right of rectangle1.
rectangle2 = New Rectangle(2048, 0, 2048, 410)
MyBase.Initialize()
End Sub

Protected Overrides Sub LoadContent()
MyBase.LoadContent()
spriteBatch = New SpriteBatch(GraphicsDevice)
texture1 = Content.Load(Of Texture2D)("back1")
'lets create a font
font1 = Content.Load(Of SpriteFont)("myfont")
End Sub

Protected Overrides Sub UnloadContent()
MyBase.UnloadContent()
End Sub

Protected Overrides Sub Update(ByVal gameTime As Microsoft.Xna.Framework.GameTime)
'// 5a. This is where the quote unquote "magic" happens.
'// This is a simple bounds check. If the right edge of
'// rectangle1 is offscreen to the left, you move it to
'// the right side of rectangle2.
If (rectangle1.X + texture1.Width <= 0) Then rectangle1.X = rectangle2.X + texture1.Width ' // You repeat this check for rectangle2. If (rectangle2.X + texture1.Width <= 0) Then rectangle2.X = rectangle1.X + texture1.Width '// 6. Otherwise we incrementally move it to the left. '// You can swap out X for Y if you instead want incremental '// vertical scrolling. Dim key As KeyboardState key = Keyboard.GetState If key.IsKeyDown(Keys.Add) Then istep = istep + 1 If key.IsKeyDown(Keys.Subtract) Then istep = istep - 1 rectangle1.X -= istep rectangle2.X -= istep msg = "step= " & istep.ToString ' MyBase.Update(gameTime) End Sub Protected Overrides Sub Draw(ByVal gameTime As Microsoft.Xna.Framework.GameTime) '// 4. Load the SpriteBatch as normal. '// load the same texture into two different rectangles. spriteBatch.Begin() spriteBatch.Draw(texture1, rectangle1, Color.White) spriteBatch.Draw(texture1, rectangle2, Color.White) spriteBatch.DrawString(font1, msg, New Vector2(20.0F, 20.0F), Color.White) spriteBatch.End() MyBase.Draw(gameTime) End Sub End Class

 Posted by at 19 h 24 min
Nov 052013
 

One article for today : lets build on what have seen so far and lets have a bouncing ball with a background and some sound when the ball hit the walls.

As always we load contents (textures and sound), we update our variables (position and direction), and we finally draw.
By now, you probably got the idea 🙂

The project files : xna_demo_4


Imports Microsoft.Xna.Framework
Imports Microsoft.Xna.Framework.Graphics
Imports Microsoft.Xna.Framework.Audio
Imports Microsoft.Xna.Framework.Content
Imports Microsoft.Xna.Framework.Media
Imports Microsoft.Xna.Framework.Input

Public Class Game
Inherits Microsoft.Xna.Framework.Game
'Fields in our game graphic manager etc'
Dim graphics As GraphicsDeviceManager
Dim spriteBatch As SpriteBatch
'Texture that we will render'
Private mTexture As Texture2D
'Set the coordinates to draw the sprite at'
Private spritePos As Vector2 = Vector2.Zero
'X and Y speed of the sprite'
Private XSpeed As Single = 80
Private YSpeed As Single = 120
'Vector2 used for the speed of the sprite'
Private spriteSpeed As New Vector2(XSpeed, YSpeed)
'sound
Private mysound As SoundEffect
'background
Private backgroundTexture As Texture2D

Public Sub New()
graphics = New GraphicsDeviceManager(Me)
'graphics.ToggleFullScreen()
End Sub

Protected Overrides Sub Initialize()
'TODO: Add your initialization logic here'
MyBase.Initialize()
End Sub

Protected Overrides Sub LoadContent()
' TODO: use this.Content to load your game content here'
MyBase.LoadContent()
' Create a new SpriteBatch, which can be used to draw textures.'
spriteBatch = New SpriteBatch(GraphicsDevice)
'Load the texture'
mTexture = Content.Load(Of Texture2D)("bille")
'load sound
mysound = Content.Load(Of SoundEffect)("sleep")
'load background
backgroundTexture = Content.Load(Of Texture2D)("background2")
End Sub

Protected Overrides Sub UnloadContent()
MyBase.UnloadContent()
'TODO: Unload any non ContentManager content here'
End Sub

Protected Overrides Sub Update(ByVal gameTime As Microsoft.Xna.Framework.GameTime)
'TODO: Add your update logic here'
'The method that will update our sprite position'
UpdateSprite(gameTime)
'
MyBase.Update(gameTime)
End Sub

Protected Overrides Sub Draw(ByVal gameTime As Microsoft.Xna.Framework.GameTime)
'GraphicsDevice.Clear(Color.CornflowerBlue)
'TODO: Add your drawing code here'
Dim mainFrame As New Rectangle(0, 0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height)
'Draw the sprite'
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend)
spriteBatch.Draw(backgroundTexture, mainFrame, Color.White)
spriteBatch.Draw(mTexture, spritePos, Color.White)
spriteBatch.End()
'TODO: Add your drawing code here'
MyBase.Draw(gameTime)
End Sub

Private Sub UpdateSprite(ByVal gameTime As GameTime)
'The function move the sprite and check if its on the limits of the screen so it can bounce back'
Dim intMaxX As Integer
Dim intMinX As Integer = 0
Dim intMaxY As Integer
Dim intMinY As Integer = 0
'move the sprite by speed scaled by elapsed time'
spritePos += spriteSpeed * CSng(gameTime.ElapsedGameTime.TotalSeconds)
'Get the max. X and Y coordinates'
intMaxX = graphics.GraphicsDevice.Viewport.Width - mTexture.Width
intMaxY = graphics.GraphicsDevice.Viewport.Height - mTexture.Height
'Check the sprite if its at some of the edges of the screen and then reverce the speed of the sprite'
If spritePos.X > intMaxX Then
'Check if the sprite is at the maximum X coordinates of the screen if so reverse the speed'
spriteSpeed.X *= -1
spritePos.X = intMaxX
mysound.Play()
ElseIf spritePos.X < intMinX Then 'Check if the sprite is at the minimum X coordinates of the scree and reverse the speed' spriteSpeed.X *= -1 spritePos.X = intMinX mysound.Play() End If If spritePos.Y > intMaxY Then
'Check if the sprite is at the maximum Y coordinates of the screen if so reverse the speed'
spriteSpeed.Y *= -1
spritePos.Y = intMaxY
mysound.Play()

ElseIf spritePos.Y < intMinY Then 'Check if the sprite is at the minimum Y coordinates of the scree and reverse the speed' spriteSpeed.Y *= -1 spritePos.Y = intMinY mysound.Play() End If End Sub End Class

 Posted by at 22 h 24 min