This member has provided no bio about themself...

RSS My Blogs

LibGDX in Depth series – Entry 03

jaykalabs Blog

Before diving I request you to download LibGDX source code and view each of the class as i mention them. It is very difficult to follow otherwise.

The important variables in Mesh class are

static final Map> meshes = new HashMap>();
final VertexData vertices;
final IndexData indices;

The first variable meshes (Map) is for managed mesh. The second and third variable are the ones which store all the data related to the mesh. Mesh class contains many constructors. The most generic one is

public Mesh (VertexDataType type, boolean isStatic, int maxVertices, int maxIndices, VertexAttribute... attributes)
{
if (type == VertexDataType.VertexBufferObject)
{ vertices = new VertexBufferObject(isStatic, maxVertices, attributes);
indices = new IndexBufferObject(isStatic, maxIndices); isVertexArray = false;
}
else if (type == VertexDataType.VertexBufferObjectSubData)
{
vertices = new VertexBufferObjectSubData(isStatic, maxVertices, attributes);
indices = new IndexBufferObjectSubData(isStatic, maxIndices);
isVertexArray = false;
} else
{ vertices = new VertexArray(maxVertices, attributes);
indices = new IndexArray(maxIndices); isVertexArray = true;
}
addManagedMesh(Gdx.app, this);
}

We'll concentrate on VertexDataType.VertexBufferObject as the other two types are nearly similar and easier.
The constructor creates an instance of VertexBufferObject class and IndexBufferObject class, which are derived from VertexData class and IndexData class respectively.
The VertexBufferObject class is responsible for setting the vertices,binding the vertices with shader program and eventually unbind and disposing the vertex data.
The data for vertices consists of two parts mainly, one is the actual array of data and the second is the types of attributes included in the array.
Since the vertices data is an interleaved array, it is vital to tell OpenGL about the offset,number of components,etc of each attribute.
The important variables in VertexBufferObject class are

final VertexAttributes attributes;
final FloatBuffer buffer;

The entire vertex data is stored as a FloatBuffer.VertexAttribute helper class contains Constants and functions which will take care of informing OpenGL which type of data is present in which part of the array.

Before going further deep we'll analyze the code in first entry with what is learned so far

mesh = new Mesh(true, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked());
1) In this constructor I'm not setting any VertexDataType 2) I'm setting is static as true, so the LibGDX will use GL_STATIC_DRAW in glBufferData function call. 3) I'm telling i have 3 vertices with 3 index. 4) Next I'm passing that in the interleaved data per vertex first i've passed position data (i.e., VertexAttribute.Position() ), then i'm passing color data (VertexAttribute.ColorUnpacked()) To handle different type of vertex attributes, LibGDX uses a the Iterable class named VetexAttributes (note the's') which contains an array of VertexAttribute. Each vertex attribute class contains variable which uniquely defines a type of vertex attribute

/** the attribute {@link Usage} **/
public final int usage;
/** the number of components this attribute has **/
public final int numComponents;
/** the offset of this attribute in bytes, don't change this! **/
public int offset;
/** the alias for the attribute used in a {@link ShaderProgram} **/
public String alias;
/** optional unit/index specifier, used for texture coordinates and bone weights **/
public int unit;
private final int usageIndex;

For Example when I call VertexAtrribute.position()

public static VertexAttribute Position ()
{
return new VertexAttribute(Usage.Position, 3, ShaderProgram.POSITION_ATTRIBUTE);
}

it returns a new VertexAttribute class instance with usage as position, contains 3 components (X,Y,Z) and is to be passed on to the shader variable "a_position"(ShaderProgram.POSITION_ATTRIBUTE);
Similarly for VertexAttribute.ColorUnpacked()

public static VertexAttribute ColorUnpacked ()
{
return new VertexAttribute(Usage.Color, 4, ShaderProgram.COLOR_ATTRIBUTE);
}

it returns new VertexAttribute class instance with usage as Color containing 4 components (RGBA) and is passed on to shader variable "a_color" (ShaderProgram.COLOR_ATTRIBUTE);

Now that we have told how our data will look like to LibGDX, I can pass the data.

mesh.setVertices(new float[] {-0.5f, -0.5f, 0, 1, 0.4f, 1, 1, 0.5f, -0.5f, 0, 1, 0.2f, 0f, 1, 0.5f, 0.5f, 0, 1, 1, 1, 1});
setVertices function copies the above float array values to the FloatBuffer inside VertexBufferObject class.

Now the Mesh->VertexBufferObject instance contains details about the position of vertices and color of vertices in FloatBuffer and details of attributes passed as
an VertexAttribute array inside VertexAttributes instance.

Now the only thing remaining is to Bind the values to the location and render .
I'm sure you're confused as I am now. So I'll discuss bind and render in next entry.
I'm following

LibGDX in Depth series – Entry 02

jaykalabs Blog

In our Previous post LibGDX in Depth series – Entry 01, we created our first triangle in LibGDX. Now we'll see what happens behind the scene when we run that code . Source code for previous entry is here. Explaining meshes requires more than one entry. So in this entry i'll discuss how meshes are normally sent with Opengl and in the next entry i'll continue on how LibGDX hides these details from developer.

Messing with Meshes

In OpenGL in order to draw anything we create meshes and shade them with shaders. Simple right. Mesh can be as simple as a quad or as complex as an entire city environment. Mesh class is written in com.badlogic.gdx.graphics.Mesh.java

Mesh is made of vertices and each vertex has attributes such as position (non-optional), color, texcoord ,normal,etc. These vertex attributes can be stored as vertex array (in RAM) or as Vertex Buffer Objects (in GPU RAM) .For passing each of these attributes to vertex shader as vertex array in pure OpenGL we have to

1) Get the attribute reference location for the shader program using opengl funtion glGetAttribLocation

String attribute_name="a_position";
attribute_position = glGetAttribLocation (program, attribute_name);

a_position is attribute name you give in your vertex shader. LibGDX uses "a_" attributes for attribute,
"u_" for uniforms,"v_" for varying. We'll see what each of these are in shaders section

2) Then enable vertex attribute array and point the array to the location we got previously

glEnableVertexAttribArray(attribute_position );
/* Describe our vertices array to OpenGL (it can't guess its format automatically) */
 glVertexAttribPointer( attribute_position, // attribute
 2, // number of elements per vertex, here (x,y)
GL_FLOAT, // the type of each element
GL_FALSE, // take our values as-is
0, // no extra data between each position
triangle_vertices_position // pointer to the float array );

For vertex Buffer Objects

1) Get attribute location as before

String attribute_name="a_position";
attribute_position = glGetAttribLocation (program, attribute_name);

2) We create the VBO buffer first

glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle_vertices_position), triangle_vertices_position, GL_STATIC_DRAW); 

The above code uses GL_STATIC _DRAW as buffer usage hint

  • GL_STATIC_DRAW is for vertex buffers that are rendered many times, and whose contents are specified once and never change.
  • GL_DYNAMIC_DRAW is for vertex buffers that are rendered many times, and whose contents change during the rendering loop.
  • GL_STREAM_DRAW is for vertex buffers that are rendered a small number of times and then discarded.

3)Point the buffer to the location we got in step 1

glEnableVertexAttribArray(attribute_position);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(attribute_position, 2, GL_FLOAT, GL_FALSE,
0,triangle_vertices_position));

The above code is only for position of vertices. We have to send optional attributes such as color, normals ,etc. LibGDX makes sending all these data very simple. We used 0nly 3 lines of code for doing all the above.

mesh = new Mesh(true, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked());
mesh.setVertices(new float[] {-0.5f, -0.5f, 0, 1, 0.4f, 1, 1, 0.5f, -0.5f, 0, 1, 0.2f, 0f, 1, 0.5f, 0.5f, 0,
 1, 1, 1,1}); // Interleaved vertex attributes data
mesh.setIndices(new short[] {0, 1, 2});

The Constructor for a new mesh object in LibGDX is

public Mesh (boolean isStatic, int maxVertices, int maxIndices, VertexAttribute... attributes)

Setting isStatic to true creates a VertexBufferObject/VertexBufferObjectSubData and IndexBufferObject instead of Vertex and index array.
VertexAttribute class takes care of details of which type of attribute we are specifying.

There is also managed mesh concept. I'll dive into the Mesh class in next entry.

LibGDX in Depth series - Entry 01

jaykalabs Blog

Blog source jaykalabs.com
This is the first entry towards my exploration into the world of Computer Graphics and OpenGL through LibGDX. I will record my musings and ideas and what i understood about LibGDX in this series, which will serve as a reminder to me and a tutorial to you. Please note that this series will be slightly difficult for total beginners to OpenGL.

A New Beginning

I'm not going to discuss in detail about how to setup your first LibGDX project. You can find information regarding that here . Desktop and android project has to created as a minimal requirement. I have named my project "LibgdxTut01" and am using LibGDX 0.9.9.

Into the Depths

Our objective now is to get the below image as output. I'll be using the desktop project for that.

output

We'll not need any asset now, so delete the 'assets/data' folder inside android project. We'll be using OpenGLES 2.0. Hence we have to set the LibGDX configuration to use OpenGlES 2.0. Below is the snippet from my Main.java (desktop project).

java code:
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();

cfg.title = "LibgdxTut01";

<strong> cfg.useGL20 = true;<!-->

cfg.width = 480;

cfg.height = 320;


new LwjglApplication(new LibgdxTut01(), cfg);


In OpenGL everything we render is a series of triangles. Even the most complex scene from crysis is just a series of triangles with textures & etc. A group of these triangles is called mesh. The above triangle is a mesh with three vertices. Each of these vertices can have many attributes like color, texture coordinate , normal , tangent. For now i'll use only color. You can see that i have give pink,red and white color for the vertices. See how it has smoothly blended. We have to sent the position of the vertices and color of the vertices to graphics card, so that it can draw it. LibGDX provides a convenient class aptly named Mesh. Creating a new mesh now I add the below code inside Create function of libgdxtut01 class.

java code:
mesh = new Mesh(false, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked());

We are telling LibGDX that we need 3 vertices and we have 3 indices (number of triangle coords). You'll understand indices as we move on. For now I'll just tell that triangle has 3 vertices,3 indices. Square has 4 vertices, 6 indices(2 triangles). Pentagon has 5 vertices 9 indices (3 triangles).

Next in the constructor is VertexAttributes. position attribute requires 3 floats(XYZ) and color unpacked required 4 floats (RGBA). So in the constructor we are telling LibGDX that first 3 floats are position and next 4 are color of a vertex. so in the below code. (-0.5f, -0.5f, 0) are position of '0'th (zeroth) vertex and (1, 0.4f, 1, 1) is the color. The next (0.5f, -0.5f, 0) and (1, 0.2f, 0f, 1) corresponds to next vertex.

java code:
mesh.setVertices(new float[] {-0.5f, -0.5f, 0, 1, 0.4f, 1, 1, 0.5f, -0.5f, 0, 1, 0.2f, 0f, 1, 0.5f, 0.5f, 0, 1, 1, 1,

1});

mesh.setIndices(new short[] {0, 1, 2});

Next comes the shaders. OpenGLES 2.0 uses what is called as shaders for shading the meshes. There are many tutorials about what shaders are. You can refer here also. I've written my vertex and fragment shaders in files inside "assets/shaders" folder so that it need not be edited easily.

code:
shader=new ShaderProgram(Gdx.files.internal("shaders/vertex.vert"),Gdx.files.internal("shaders/fragment.frag"));

The ShaderProgram class will automatically compile,attach and link the shaders. Check shader.isCompiled() to check for errors. ShaderProgram class makes writing shaders and passing values very easy. Now to render the mesh add the following code to render loop.

java code:
Gdx.gl20.glClearColor(0.2f, 0.2f, 0.2f, 1);

Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);

shader.begin();

mesh.render(shader, GL20.GL_TRIANGLES);

shader.end();


We clear the framebuffer with gray color. shader.begin informs OpenGL to use the shader program for rendering all meshes upto shader.end. mesh.render creates the draw call for rendering. Run the desktop java project and you should see the above output. You can find the source code for this entry in github. If you have any doubts feel free to comment.

We'll look in detail into how Mesh class and Shader Class are implemented and how it interacts with GL context in next few entries.

Tank in Space (DEAD) - PostMortem

jaykalabs Blog

"Tank in Space" my first Indie Game died yesterday!!

Cause of death : Mercy Killing by the Creator

In this blog i discuss the reasons why the game was dying and why i had to kill it finally.

History

"Tank is Space",my first Unity game, is a Space Physics based game, in which you shoot the tank to move in space. Well if you have seen A-Team movie, where they fly a tank, then you know what my game is about :D. After experimenting with LibGDX, Rajawali and ANDengine , I finally decide to use Unity for my Game development venture. After three weeks of struggle with Unity, the game was launched on October 15 2013 for android. It received 1700 downloads in 'Slide me' and around 100+ in Google Play with zero reviews and It was FREE!!

Here's why it died

1) GUI should be good even if gameplay sucks

Unity's in-built GUI is neither flashy nor cool. It is just enough to get the job. So i wrote my own GUI Script. I used a Quad for the Entire Main Menu with created a Box Collider over the "play, exit,rate" texts of the quad. When user touched the screen you cast a ray from screen point to quad and see if it hits the Play or Rate Collider,etc and using the collider name do game stuff. There is no tween animation for each button (it's just one pic for entire menu), no cool stuff. It did have a 'Click' sound and got the job done. But was not professional and a major negative for the game.

2) Don't make the Game Difficult

You have to shoot Right to move left. Pretty complicated Right.. i mean Left. Play the Game you'll see how difficult it is. The required lot of thinking. You have to use Parallelogram law of vectors and Newtons First and third law of motion ot make the tank move wherever you want . Well some people found the game so difficult that they had headaches. So make games which are fun and doesn't use brain much.

3) Marketing is why games become hit, mostly

It was my first game, so didn't give any press release or Ads.I just posted in some random facebook groups i just joined at that time. Never release a game without making a big announcement. 'Make Sound or even Noise to make people notice you'. Try this on a plane. Same goes for apps too

4) Don't make Google Play you only appstore

Around 800 apps get published each day, your app is just one of them unless you tell everyone how cool it is. After faking death initially in Google Play it survived for 2 weeks or so in SlideMe. 1700 downloads for a free game is bad but is better than 100+. So publish everywhere.'If you don't make sound and don't move then you are considered dead'. By this law my app is dead. Anyone interested in reviving the game can contact me :)

The creator now moves to his next game "Thumbi".

Implementing Scoreoid In Unity with Advanced Encryption

jaykalabs Blog

Blog From Jaykalabs.wordpress.com

Scoreoid is a Truly cross platform Gaming Backed Service. But there is no Guide for integration with Unity, So i decided to share how and why i integrated Scoreoid for LeaderBoards in my Web Game (Unity ) "Thumbi" . You can find the game at Wooglie.com or Kongregate.com Thumbi mobile game is made with Unity and uses Google play Game Services for LeaderBoards. Though Google's Game Play services works well for Web Games also ,the Plugin i used required an additional JavaScript File to be embedded in the Game's HTML File, which Web Game Publishers like Kongregate or wooglie did not allow. After some searching for Leaderboard services i came across Scoreoid which is very flexible and supports all platform as it is just a bunch of HTTP requests.


Scoreoid Security: If you send scores without encryption anybody with Paros Proxy can manipulate the http post. Scoreoid provides and advanced security layer (beta) using encryption algorithm “DES”, block mode “ECB” and interchangeable padding “PKCS5″ or “PKCS7″. You have to enable it in settings. Also Scoreoid has both HTTP and HTTPS Api URL, but HTTPS provides better security than HTTP. Use the below helper class to encrypt and decrypt messages.

using UnityEngine;
using System.Collections;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class Crypto : MonoBehaviour {

public static string Decrypt(string encryptedString)
{
DESCryptoServiceProvider desProvider = new DESCryptoServiceProvider();
desProvider.Mode = CipherMode.ECB;
desProvider.Padding = PaddingMode.PKCS7;
desProvider.Key = Encoding.ASCII.GetBytes("97ed399c");
using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(encryptedString)))
{
using (CryptoStream cs = new CryptoStream(stream, desProvider.CreateDecryptor(), CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs, Encoding.ASCII))
{
return sr.ReadToEnd();
}
}
}
}

public static string Encrypt(string decryptedString)
{
DESCryptoServiceProvider desProvider = new DESCryptoServiceProvider();
desProvider.Mode = CipherMode.ECB;
desProvider.Padding = PaddingMode.PKCS7;
desProvider.Key = Encoding.ASCII.GetBytes("97ed399c");
using (MemoryStream stream = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(stream, desProvider.CreateEncryptor(), CryptoStreamMode.Write))
{
byte[] data = Encoding.Default.GetBytes(decryptedString);
cs.Write(data, 0, data.Length);
cs.FlushFinalBlock(); // <-- Add this
return Convert.ToBase64String(stream.ToArray());
}
}
}

}

SubmittingScores:

Submitting Scores or Creating User is very Simple.The following code shows you how. Note your GameID and Api key as these are required for every transaction.

public void SubmitScore(int Score)
{

/* API  method */
string url = "https://api.scoreoid.com/v1/createScore";

/* Unity WWW Class used for HTTP Request */
WWWForm form = new WWWForm();

form.AddField( "game_id", "YourGameID");
string encry= "api_key=YourAPIKEY&amp;"+"response=json&amp;"
+"username="+ProfileName +"&amp;score="+Score;
encry=Crypto.Encrypt(encry);
form.AddField( "s", encry);
WWW www = new WWW(url, form);
StartCoroutine(SubmitscoreCoRoutine(www));
}

IEnumerator SubmitscoreCoRoutine(WWW www)
{
yield return www;

var N=JSON.Parse (Crypto.Decrypt (www.text));

if(N!=null)
{
if(N["success"].Value!=null &amp;&amp; N["success"].Value!=string.Empty)
//Score Submitted

}
else
{
             //Score Not Submitted
}

}

You can receive response in JSON or XML. I choose JSON because it does not take much bandwidth for transferring data. Parsing XML requires System.XML which adds around 1.5 MB to your build. Web Games should be small to decrease loading time. Hence JSON is best choice as JSON parsers are just around 10KB.

There are several libraries for parsing JSON in unity like miniJSON, LiteJson,etc but most of them are full of bugs or did not support our purpose. The best Library is SimpleJSON.

Parsing

You can see from my above code that i'm checking whether the JSON .parse(decrypted string) is null before using it.This is because in case of error the message such as 'gameID doesnot exist', is sent as plain text and not encrytped by Scoreoid. All other success messages and game related error messages such as 'error playername exists' are all encrypted. Finally Just parse the information if it is not null and run in game actions.

Thus Scoreoid Is Implemented. Hope it helps.

Implementing Fake Shadows in Unity for Mobiles

jaykalabs Blog

Shadows are most important for any 3D game. Without shadows the scene looks unrealistic and not so 3D.. The following is my experiences in trying to implement a light weight shadow in unity and this article is in beginner level only.

unnamed

This is the screenshot of my mobile game "Thumbi" . The Blue and Red Cubes needed shadow to give a good 3d effect.

First I used the builtin hard and soft shadows. The total number of verts rendered without shadows was around 70,but the number of verts rendered with shadows was in thousands . This is a very simple casual game for mobile and rendering such a heavy shadow is unnecessary. Besides if i made the Floor Quad unlit/Transparent the shadows wont be drawn on it . This is as per design of unity3D. Hence came my next experiment projectors.

Second Projectors are available in Standard assets of unity. It is not available in standard assets for mobiles which should have made me think why? Many forums said projectors are cheaper than actual shadows but they are not at all cheap for mobile games. The number of verts when i used projectors was in hundreds and i got around only 15 fps for such a low poly game. For some reason projectors wont draw on transparent textures in unity. Playing this fast paced game at 15 FPS spoiled the gameplay. Hence i needed something else.

Third Using a simple Black&White Texture with of 16x16 like the below one

circle_gradient

Just use a quad with Multiply shader from mobile particles. Offset the quad opposite to direction of light to imitate a shadow and shift it below your object. The quad is made a child of the cube and moved along with the cube. Ok now we got a shadow with only 2 draw calls and few verts. This approach is useful only for flat surface and when the object is at same height from floor and direction of light is fixed.

For a more better shadow you can use Raycast in downward axis to check the distance to the ground and translate the shadow quad downward accordingly. For most mobile games only one light should be used in a scene for good performance. Hence you can find the direction between Cube and Light and move the shadow quad behind the cube in the opposite direction. Eg.,

Vector3 dir= DistanceFactor* (CubeTransform.position- LightTransform.position).normalized;

dir+=CubeTransform.position;

shadowquad.position= new vector3(dir.x,groundDistance,dir.z);

This code will make the shadow opposite to light direction, and fix it and a distance from cube determined by DistanceFactor. Use any texture you like with similar gradient.This shadow will look awkward on inclined floors.

Now you got a good looking Fake shadow for your mobile game. Do play my game "Thumbi". It's FREE.