Some Sketches

Yes I'm bored.. And me finding my soul.















Awful proportions, I know. Someday I'll be better.
Until then, to quote my minion - suck it!

Happy new year if anyone reads this..

PS: Thanks Santa for the Pen Drive!

First shot at Digital Matte

Got bored, so trying new things...


Btw, no more gaming as profession - not worth it in India. It'll remain hobby for now.
Me got a great job! Back to C++ and pointers. \m/

Alchemist - Alternative Ending!

Ubisoft keeps coming up with games that have alternative endings. So why not me?

A very long time ago, I was forced to read the Alchemist [ at gunpoint ]. This probably is the only non sci-fi, non programming book I've ever read in my life. And to be honest - it sucks, big time. What kinda idiot searches the world to find his destiny. Life is about destiny finding you. Google giving you THE search result is destiny - not you typing the url in the browser.

So here's the Alternative Ending:
Dumb Shepard gets tired of his stupid sheep and their constant "Blaaah Blaah"s.
He sells them.
He buys a dog. [even better - stray dog becomes his friend]
He takes it back to his place.
It digs up.
He finds the treasure.
Lives happily ever after. [Fatima who? We all know long distance relationships never work]

 NFS: Wind doesn't carry kisses. Its probably the smell of.. never mind.


XNA Button

This post is about creating a simple event-based button in XNA. I'll dump the code here. Future self is responsible for understanding it in case he/I don't remember it.


public class Button
{
Texture2D _upTexture, _mouseOverTexture, _mouseDownTexture, _disabledTexture;
int _width, _height, _x, _y;
string _name;
bool _enabled;
Rectangle _drawRectangle;
 
//States
ButtonStates _state;
KeyboardState _prevKeyState;
MouseState _prevMouseState;
 
public bool Enabled
{
get
{
return _enabled;
}
 
set
{
_enabled = value;
}
}
 
public string Name
{
get
{
return _name; 
}
set
{
_name = value;
}
}
 
public int Width
{
get
{
return _width;        
}
set
{
_width = value;
UpdateRectangle();
}
}
 
public int Height
{
get
{
return _height;
}
set
{
_height = value;
UpdateRectangle();
}
}
 
public int Left
{
get
{
return _x;
}
set
{
_x = value;
UpdateRectangle();
}
}
 
public int Top
{
get
{
return _y;
}
set
{
_y = value;
UpdateRectangle();
}
}
 
void UpdateRectangle()
{
_drawRectangle.X = _x;
_drawRectangle.Y = _y;
_drawRectangle.Width = _width;
_drawRectangle.Height = _height;
}
 
public Button(Texture2D up, Texture2D mouseOver, Texture2D mouseDown, Texture2D disabled)
{
_upTexture = up;
_mouseOverTexture = mouseOver;
_mouseDownTexture = mouseDown;
_disabledTexture = disabled;
 
_width = _height = 50;
_x = _y = 0;
_enabled = true;
_drawRectangle = new Rectangle();
_state = ButtonStates.Up;
}
 
public void Update()
{
if (_prevKeyState == null || _prevMouseState == null)
{
_prevMouseState = Mouse.GetState();
_prevKeyState = Keyboard.GetState();
return;
}
 
KeyboardState currentKeyState = Keyboard.GetState();
MouseState currentMouseState = Mouse.GetState();
 
if (_enabled)
{
switch (_state)
{
case ButtonStates.Up:
if (_drawRectangle.Contains(currentMouseState.X, currentMouseState.Y))
{
if (currentMouseState.LeftButton == ButtonState.Pressed && _prevMouseState.LeftButton != ButtonState.Pressed)
{
_state = ButtonStates.MouseDown;
}
else
{
_state = ButtonStates.MouseOver;
}
}
break;
 
case ButtonStates.MouseOver:
if (_drawRectangle.Contains(currentMouseState.X, currentMouseState.Y))
{
if (currentMouseState.LeftButton == ButtonState.Pressed && _prevMouseState.LeftButton != ButtonState.Pressed)
{
_state = ButtonStates.MouseDown;
}
}
else
{
_state = ButtonStates.Up;
}
 
break;
 
case ButtonStates.MouseDown:
if (_drawRectangle.Contains(currentMouseState.X, currentMouseState.Y))
{
if (currentMouseState.LeftButton != ButtonState.Pressed && _prevMouseState.LeftButton == ButtonState.Pressed)
{
_state = ButtonStates.Up;
 
//Fire Click event
if (OnClick != null)
{
OnClick(this);
}
}
}
else
{
if (currentMouseState.LeftButton != ButtonState.Pressed && _prevMouseState.LeftButton == ButtonState.Pressed)
{
//Release outside
_state = ButtonStates.Up;                                
}
}
break;
 
default:
break;
}
}           
 
_prevKeyState = currentKeyState;
_prevMouseState = currentMouseState;

}
 
public void Draw(SpriteBatch spriteBatch)
{
if (_enabled)
{
switch (_state)
{
case ButtonStates.Up:
if (_upTexture != null)
{
spriteBatch.Draw(_upTexture, _drawRectangle, Color.White);
}
break;
case ButtonStates.MouseOver:
if (_mouseOverTexture != null)
{
spriteBatch.Draw(_mouseOverTexture, _drawRectangle, Color.White);
}
break;
case ButtonStates.MouseDown:
if (_mouseDownTexture != null)
{
spriteBatch.Draw(_mouseDownTexture, _drawRectangle, Color.White);
}
break;
default:
break;
}
}
else
{
if (_disabledTexture != null)
{
spriteBatch.Draw(_disabledTexture, _drawRectangle, Color.White);                   
}
}            
}
 
//Events
public delegate void Click(Button sender);
public event Click OnClick;
 
public enum ButtonStates
{
Up,
MouseOver,
MouseDown
}
}

Thats it! Use OnClick event in the game to tap the click event, call button.Update() in the update logic of the game code.

Some Screenshots!






Risks

I recently read a poem about Risks. Its by Janet Rand. Sheer brilliance. Check it out -

To laugh is to risk appearing the fool,
To weep is to risk being called sentimental.
To reach out to another is to risk involvement.
To expose feelings is to risk showing your true self.
To place your ideas and your dreams before the crowd is to risk being called naive.
To love is to risk not being loved in return,
To live is to risk dying,
To hope is to risk despair,
To try is to risk failure

But risks must be taken, because the greatest risk in life is to risk nothing.
The person who risks nothing, does nothing, has nothing, is nothing, and becomes nothing.
He may avoid suffering and sorrow, but he simply cannot learn, feel, change, grow or love.
Chained by his certitude, he is a slave; he has forfeited his freedom.
Only the person who risks is truly free.

- JANET RAND

Destiny and the Irish Pot of Gold Syndrome

I always believe that nothing can be done to avoid one's destiny. It happens no matter what. There's no way to avoid events from happening in life - no matter how much you try, just like in final destination.

Theorem 1: When destiny wants to kick your ass - All you can do is bend over.

Conclusion 1: You never know whats in store for you. When you bend over - you may actually find a Pot-of-Gold. It's just destiny's way of showing you something good in life.

Corollary 1: When you find a Pot-of-Gold and bend over to pick it up - boy you MAYBE in trouble!

NFS: Stock markets may be a safer bet than investing in gold!

XNA Sphere

As mentioned in the previous post, this is bout creating a sphere in XNA.
I forgot to mention in my previous post, that these are useful for visualizing stuff in 3d world, this actually doesn't create surface - just lines.

I'll be using the Circle created in before to setup my sphere.

The funny thing about a sphere is that projection on any plane will always be a circle.Hence, when creating the circles we ensure that they lie on the circumference

Refer image below for clarity:




Here is the complete code:

//Generic Sphere for XNA Debugging / Visualizing.
//This is just a set of lines - no surface
//Author: Vikram N [ makubex ] 
//Blog: 8bitmemories.blogspot.com
public class Sphere
{        
//Color of the verttices
Color _VertexColor;
 
//List of Circles that make up the sphere
//Refer to post on Circles
List<Circle> _Verticals;
List<Circle> _Horizontals;
 
//Save original position
//Becomes easy to transform the sphere
Vector3[] _HBasePositions;
Vector3[] _VBasePositions;
 
//Main game reference
Game _Game;
BasicEffect _Effect;
 
//Not used
//NFS: May be useful someother day
Matrix _Transforms;
//Store pos, scale and rotation
//Only pos is useful. Others have not been implemented
//Rotation - no diff
//Scale - why dude..  create a new one with diff radius :P
Vector3 _Position, _Scale, _Rotation;
//Radius of the sphere
float _Radius;
 
public Vector3 Position
{
get
{
return _Position;
}
 
set
{
_Position = value;
Transform();
}
}
 
public Vector3 Rotation
{
get
{
return _Rotation;
}
 
set
{
_Rotation = value;
Transform();
}
}
 
public Vector3 Scale
{
get
{
return _Scale;
}
 
set
{
_Scale = value;
Transform();
}
}
 
public Matrix Transforms
{
get
{
return _Transforms;
}
 
set
{
_Transforms = value;
}
}
 
//No of circles to be used for creating the sphere
//Higher the number, better it looks
//10 seems to look nice :P
int LEVELS = 10;
//Constructor
public Sphere(Game game, Color color, float radius)
{
_Game = game;
_Effect = new BasicEffect(_Game.GraphicsDevice, null);
_Effect.VertexColorEnabled = true;
_VertexColor = color;
_Transforms = Matrix.Identity;
_Radius = radius;
 
_Verticals = new List<Circle>();
_Horizontals = new List<Circle>();
 
Setup();
}
 
//Function to create circles
void Setup()
{
float offset = _Radius / (float)LEVELS;
float rOffset = 90 / LEVELS;
//Add one on each side of the center
//For expln refer the blog - 8bitmemories.blogspot.com
for (int i = 0; i <= LEVELS; i++)
{        
Circle tmpPos = new Circle(_Game, _VertexColor, _Radius * (float) Math.Cos(MathHelper.ToRadians(i*rOffset)));
tmpPos.Position = new Vector3(0, _Radius * (float)Math.Sin(MathHelper.ToRadians(i * rOffset)), 0);
 
Circle tmpNeg = new Circle(_Game, _VertexColor, _Radius * (float)Math.Cos(MathHelper.ToRadians(i * rOffset)));
tmpNeg.Position = new Vector3(0, -_Radius * (float)Math.Sin(MathHelper.ToRadians(i * rOffset)), 0);
 
_Verticals.Add(tmpPos);
_Verticals.Add(tmpNeg);
}
 
//Same logic but set rotation of 90 degrees on z axis
for (int i = 0; i <= LEVELS; i++)
{
Circle tmpPos = new Circle(_Game, _VertexColor, _Radius * (float)Math.Cos(MathHelper.ToRadians(i * rOffset)));
tmpPos.Position = new Vector3(_Radius * (float)Math.Sin(MathHelper.ToRadians(i * rOffset)), 0, 0);
tmpPos.Rotation = new Vector3(0, 0, MathHelper.PiOver2);
 
Circle tmpNeg = new Circle(_Game, _VertexColor, _Radius * (float)Math.Cos(MathHelper.ToRadians(i * rOffset)));
tmpNeg.Position = new Vector3( -_Radius * (float)Math.Sin(MathHelper.ToRadians(i * rOffset)),0,  0);
tmpNeg .Rotation = new Vector3(0, 0, MathHelper.PiOver2);
 
_Horizontals.Add(tmpPos);
_Horizontals.Add(tmpNeg);
}
 
//Save original positions 
//Useful for translation        
_HBasePositions = _Horizontals.Select(x => x.Position).ToArray();
_VBasePositions = _Verticals.Select(x => x.Position).ToArray();
 
}
 
//Move the sphere
void Transform()
{
//Not used 
_Transforms = Matrix.CreateScale(_Scale) * Matrix.CreateFromYawPitchRoll(_Rotation.Y, _Rotation.X, _Rotation.Z) * Matrix.CreateTranslation(_Position);
 
//Use the base positions + translation value
for (int i = 0; i < _Verticals.Count; i++)
{
_Verticals[i].Position = _VBasePositions[i] + _Position;
}
 
for (int i = 0; i < _Horizontals.Count; i++)
{
_Horizontals[i].Position = _HBasePositions[i] + _Position;
}
}
 
//Draw spheres
public void Draw()
{
//Draw horizontal and vertical circles
for (int i = 0; i < _Verticals.Count; i++)
{
_Verticals[i].Draw();
}
 
for (int i = 0; i < _Horizontals.Count; i++)
{
_Horizontals[i].Draw();
}
}
}

Screen shots:


Pretty Ok for debugging I think.
NFS: I get confused with sin and cos!Hope you've learnt something in the future!

Simple Circle in XNA


This post is about creating a simple circle in XNA using VertexPositionColor elements and LineStrip primitive.
Lets call our class Circle.

Members:
//List of vertices
List<VertexPositionColor> _Vertices;
 
//Convert to array to avoid ToArray for every draw
VertexPositionColor[] _VertexArray;
 
//Color of the vertices
Color _VertexColor;
 
//Main game class
Game_Game;
BasicEffect _Effect;
 
//Transforms for the circle
Matrix _Transforms;
Vector3 _Position, _Scale, _Rotation;
 
//Radius of the circle
float _Radius;

Properties:
public Vector3 Position
{
get{ return_Position; }
set{_Position=value;Transform();}
}
 
public Vector3 Rotation
{
get{return_Rotation;}
set{_Rotation=value;Transform();}
}
 
public Vector3 Scale
{
get{return_Scale;}
set{_Scale=value;Transform();}
}
 
public MatrixTransforms
{
get{return_Transforms;}
set{_Transforms=value;}
}


Constants:
//This indicates that every 5 degree 
//a point on the cirumference will be added
//Ex: 360/5 = 72 points will be used
int DEGREE_INCREMENT = 5;

Constructor:
public Circle(Game game, Color color, float radius)
{
_Game = game;
_Effect = new BasicEffect(_Game.GraphicsDevice, null);
_Effect.VertexColorEnabled = true;
_VertexColor = color;
_Transforms = Matrix.Identity;
_Radius = radius;
_Scale = Vector3.One;
 
_Vertices = new List<VertexPositionColor>();
Setup();
 
_VertexArray = _Vertices.ToArray();
}

Setup Function:
void Setup()
{
//For each number of points : 360/ DEGREE_INCREMENT
for (int i = 0; i <= 360; i+= DEGREE_INCREMENT)
{
VertexPositionColor tmp = new VertexPositionColor();
 
// X => R * Cos(Angle), Y = 0, Z => R * Sin(Angle)
tmp.Position = new Vector3(_Radius * (float)Math.Cos(MathHelper.ToRadians(i)), 0, _Radius * (float)Math.Sin(MathHelper.ToRadians(i)));
tmp.Color = _VertexColor;
_Vertices.Add(tmp);                
} 
}

Transform Function:
//Update transform when pos, rot, scale is changed
void Transform()
{
_Transforms = Matrix.CreateScale(_Scale) * 
Matrix.CreateFromYawPitchRoll(_Rotation.Y, _Rotation.X, _Rotation.Z) * 
Matrix.CreateTranslation(_Position);
}

Draw Function:
public void Draw()
{
//Tell the device we are sending Vertexpositioncolor elements
_Game.GraphicsDevice.VertexDeclaration = new VertexDeclaration(_Game.GraphicsDevice, VertexPositionColor.VertexElements);
_Effect.Begin();
foreach (EffectPass pass in _Effect.CurrentTechnique.Passes)
{
pass.Begin();
 
//Set the world, view, projection matrices
_Effect.World = _Transforms;
_Effect.View = Camera.View;
_Effect.Projection = Camera.Projection;
 
//Draw primitive: n points => n-1 lines
_Game.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineStrip, _VertexArray, 0, _Vertices.Count - 1);
pass.End();
}
 
_Effect.End(); 
}

Screen shots with different Degree increments:


Next up - Sphere

Simple Grid in XNA

I created a simple Grid-Display system for debugging my games.
Pretty useful when I want to know the position of any object in the game.
It helps a lot in visualization.

Required class members:
public int Width;
public int Height;
public int Rows;
public int Columns;
public Vector3 Position;
List<VertexPositionColor> vertices;
BasicEffect effect;
Game game;

Constructor:
public Grid(Vector3 Position, int Width, int Height, int Rows, int Columns, Game game)

Constructor logic:
this.game = game;
effect = new BasicEffect(game.GraphicsDevice, null);
effect.VertexColorEnabled = true;  
this.Width = Width;
this.Height = Height;
this.Rows = Rows;
this.Columns = Columns;
this.Position = Position;
vertices = new List<VertexPositionColor>();
int xDiff = this.Width / this.Columns;
int zDiff = this.Height / this.Rows;
float xBase = this.Position.X - this.Width/ 2f;
float zBase = this.Position.Z - this.Height / 2f;
float yBase = this.Position.Y;
for (int i = 0; i <= this.Rows;i++)
{
   vertices.Add(new VertexPositionColor(new Vector3(xBase + i * xDiff, yBase, zBase), Color.Green));   vertices.Add(new VertexPositionColor(new Vector3(xBase + i * xDiff, yBase, zBase + this.Height), Color.Green));
}
for (int i = 0; i <= this.Columns;i++)
{
   vertices.Add(new VertexPositionColor(new Vector3(xBase, yBase, zBase + i* zDiff), Color.Green));
   vertices.Add(new VertexPositionColor(new Vector3(xBase + this.Width, yBase, zBase + i * zDiff), Color.Green));
}

The Draw method:
public void Draw()
{
     game.GraphicsDevice.VertexDeclaration = new VertexDeclaration(game.GraphicsDevice, VertexPositionColor.VertexElements);
     effect.Begin();
     foreach (EffectPass pass in effect.CurrentTechnique.Passes)
     {
        pass.Begin();
        effect.View = Camera.View;
        effect.Projection = Camera.Projection; 
        //Draw vertices as Primitive                 
       effect.End();
     }    
     effect.End();
}

To draw the lines:
game.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList,vertices.ToArray(),0,vertices.Count/2);

Logic explained:
Assume that the given position is the center of the Grid.
Grid extends on each side, i.e x and z axis by the amount width/2 and height/2.
The xDiff and xDiff are the distance between each column and row.
Start adding lines for each column and row.
Note the <= operator for the loop construct!

Game Completed!

Well, I completed my first game. Whew!!! Simple one.. but learnt a lot.
Based on the available tuts over net, I managed to add:
Ocean [ Shaders ]
Terrains
Collision detection [ Custom, no 3rd party engine ]
Cameras and lights
Skyboxes etc etc
UI Widgets 

Then I downloaded some XNA engines available over the web and discovered that in essence -
I had created my own mini - game engine!

I plan on posting some source-code and useful stuff when I find time. Right now I'm thinking of creating a Racing game.

NFS: The most painful thing in game-dev is debugging.