Tuesday, April 23, 2013

jQuery: Dynamically add/delete rows in a table [Extended]

0 comments
Sl No.Item NameAmount
1
Total Amount
 
 
 
  
 
 
  
Sl No.Item NameAmount
1
Total Amount

jQuery: Dynamically add/delete rows in a table

0 comments

Item NameAmount

 

 
 
  
 
 
  
Item NameAmount

jQuery: The Write Less, Do More, JavaScript Library

0 comments

Tuesday, December 20, 2011

2D C++ Game: Pacman - Pre-Alpha

1 comments
Snapshot:
Pending:
▪ Game states
▪ Score, lives calculation
▪ Monster AI
▪ Sound effects & background music
▪ More levels

Source Code:
 /**************************************************************
 *    Pacman C++                                              *
 *    Written by Sunit Maharana (c) 2011 - 2012               *
 *    http://sunitdevdiary.blogspot.com                       *
 **************************************************************
 *    This source code is released under the The GNU          *
 *    General Public License (GPL). It is free and is         *
 *    distributed in the hope that it will be useful,         *
 *    you can redistribute it and/or modify it under the      *
 *    terms of the GNU General Public License.                *
 **************************************************************/
// Allegro library
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>

//Screen resolution
#define SCREEN_W 800
#define SCREEN_H 600
#define TILE_SIZE 32

// Game fps
#define FPS 60

// Direction
#define STAND 0
#define LEFT -1
#define RIGHT 1
#define UP -2
#define DOWN 2

// Game input keys
enum Keyboard {KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ESCAPE};
bool keyboard[5] = {false,false,false,false,false};

// Types of objects in the game
enum ObjectType {FOOD, BLOCK};


// Character Object Class
class CharacterObject
{
    public:
    float posX; // X coordinate of the Character Object
    float posY; // Y coordinate of the Character Object
    float speed; // Speed of the Character Object
    float angle; // Angle of rotation of Character Object
    int direction; // Direction [0 -> STAND, -1 -> LEFT, 1 -> RIGHT, -2 -> UP, 2 -> DOWN]

    int spritesheetWidth; // Width of the sprite sheet
    int spritesheetHeight; // Height of the sprite sheet
    int totalFrame; // Total number of frames
    int currentFrame; // Current frame counter
    int frameWidth; // Width of the selected region from the sprite sheet
    int frameHeight; // Height of the selected region from the sprite sheet
    int frameDelay; // Frame delay in between animation sequence
    int frameDelayCounter; // Frame delay counter
    ALLEGRO_BITMAP *image; // ALLEGRO_BITMAP to hold the sprite sheet

    // Class constructor
    CharacterObject()
    {
        posX = 0;
        posY = 0;
        speed = 0;
        direction = 0;
        angle = 0;
        spritesheetWidth = 0;
        spritesheetHeight = 0;
        totalFrame= 0;
        currentFrame = 0;
        frameWidth = 0;
        frameHeight = 0;
        frameDelay = 0;
        frameDelayCounter = 0;
        image = NULL;
    }

    // Method To Initialize The CharacterObject
    void InitObject()
    {
        // Returns the width of the sprite sheet
        spritesheetWidth = al_get_bitmap_width(image);
        // Returns the height of the sprite sheet
        spritesheetHeight = al_get_bitmap_height(image);
        // Calculation to find out individual frame width
        frameWidth = spritesheetWidth / totalFrame;
        // Calculation to find out individual frame height
        frameHeight = spritesheetHeight;
        // Makes the background of the sprite sheet transparent
        al_convert_mask_to_alpha(image,al_map_rgb(255, 0, 255));
    }

    // Method to handle drawing logic of the Character Object
    void DrawObject(ALLEGRO_DISPLAY *screen)
    {
        // X coordinate calculation of selected frame/region
        int currentFrameX = currentFrame * frameWidth;
        // Y coordinate of selected frame/region
        int currentFrameY = 0;
        // Empty bitmap to store rotated image
        ALLEGRO_BITMAP *rotated = NULL;
        // Creating the new bitmap with width and height same as the selected frame/region
        rotated = al_create_bitmap(frameWidth, frameHeight);
        // New bitmap selected for drawing instead of backbuffer
        al_set_target_bitmap(rotated);
        // Particular region/frame is selected and drawn on to the new bitmap
        al_draw_bitmap_region(image, currentFrameX, currentFrameY, frameWidth, frameHeight, 0, 0, 0);
        // Drawing target changed back to backbuffer of the screen
        al_set_target_bitmap(al_get_backbuffer(screen));


        /* Logic to handle the rotation of the sprite as per direction
        0 degree is 0 radian
        90 degree is pi / 2
        180 degree is pi
        270 degree is 1.5 * pi
        360 degree is 2 * pi
        Check radian and degree conversion chart
        */
        switch(direction)
        {
            case STAND:
            angle = angle; // No rotation
            break;
            case LEFT:
            angle = ALLEGRO_PI; // 180 degree rotation
            break;
            case RIGHT:
            angle = 0 ; // 0 degree rotation
            break;
            case UP:
            angle = ALLEGRO_PI * 1.5; // 270 degree rotation
            break;
            case DOWN:
            angle = ALLEGRO_PI / 2; // 90 degree rotation
            break;
        }
        // Rotate the new bitmap 'rotated' holding our selected region of the sprite sheet
        // Draw it on to the backbuffer
        al_draw_rotated_bitmap(rotated, frameWidth / 2, frameHeight / 2, posX, posY, angle, 0);
        // Free resoruce after using ALLEGRO_BITMAP 'rotated'
        al_destroy_bitmap(rotated);
        // Logic to handle frame delay in animation sequence
        if(++frameDelayCounter >= frameDelay)
        {
            // Frame animation sequence logic
            // Increment frame & reset frame counter to 0 after traversing through all frames
            if(++currentFrame >= totalFrame)currentFrame = 0;
            // If Character Object is standing, only draw the first frame of the sprite sheet
            if(direction == STAND){currentFrame = 0;frameDelayCounter = frameDelay;}
            // Reset frame delay counter to 0, after it has completed its delay cycle
            frameDelayCounter = 0;
        }
    }

    // Method to handle movement, direction and collision logic of Character Object
    void UpdateLogic()
    {
        //Update object direction as per keyPress
        if(keyboard[KEY_UP])direction = -2;
        if(keyboard[KEY_DOWN])direction = 2;
        if(keyboard[KEY_LEFT])direction = -1;
        if(keyboard[KEY_RIGHT])direction = 1;

        //Update object speed as per direction
        switch(direction)
        {
            case LEFT:
            posX = posX - speed; // Move negative to x-axis
            break;
            case RIGHT:
            posX = posX + speed; // Move along the x-axis
            break;
            case UP:
            posY = posY - speed; // Move negative to y-axis
            break;
            case DOWN:
            posY = posY + speed; // Move along the y-axis
            break;
            case STAND: // No update in position
            break;
        }

        //Check for collision [Object moving out of the screen]
        if(posX>=SCREEN_W)posX=10; // If Character Object position outside right of the screen
        if(posY>=SCREEN_H)posY=10; // If Character Object position outside bottom of the screen
        if(posX<=0)posX=SCREEN_W;  // If Character Object position outside the left of screen
        if(posY<=0)posY=SCREEN_H;  // If Character Object position outsided the top of the
    }

    //Method to handle collision
    template <class T>
    void CollisionLogic(T &object)
    {
        if(this->posX + 10 > (object.posX - object.boundedBoxWidth/2) &&
        this->posX - 10 < (object.posX + object.boundedBoxWidth + object.boundedBoxWidth/2) &&
        this->posY + 10 > (object.posY - object.boundedBoxHeight/2) &&
        this->posY - 10 < (object.posY + object.boundedBoxHeight + object.boundedBoxHeight/2 ))
        {
            switch(object.type)
            {
                 case BLOCK:
                 {
                    switch(direction)
                    {
                        case LEFT:
                        posX = posX + 2;
                        break;
                        case RIGHT:
                        posX = posX - 2;
                        break;
                        case UP:
                        posY = posY + 2;
                        break;
                        case DOWN:
                        posY= posY - 2;
                        break;
                    }
                    direction = STAND; // Collision occurs, change direction to stand
                    break;
                 }
                 case FOOD:
                 {
                    object.alive = false;
                     break;
                 }

            }

        }

    }

};

class GameObject
{
    public:
    float posX; // X coordinate of the Game Object
    float posY; // Y coordinate of the Game Object
    int type; // Type of Game Object
    bool alive; // Boolean flag to check if Game Object is alive
    int boundedBoxWidth; // Bounded box width for collision
    int boundedBoxHeight; // Bounded box height for collision
    ALLEGRO_BITMAP *image; // ALLEGRO_BITMAP to hold the image

    GameObject()
    {
        posX = 0;
        posY = 0;
        alive = true;
        boundedBoxWidth = 0;
        boundedBoxHeight = 0;
        image = NULL;
    }

    // Method To Initialize The GameObject
    void InitObject(ALLEGRO_BITMAP *image, float posX, float posY, int type)
    {
        this->image = image;
        this->posX = posX;
        this->posY = posY;
        this->type = type;
        al_convert_mask_to_alpha(this->image, al_map_rgb(255, 0, 255));
        boundedBoxWidth = al_get_bitmap_width(image);
        boundedBoxHeight = al_get_bitmap_height(image);
    }

    // Method to draw the GameObject
    void DrawObject()
    {
        if(alive)
        al_draw_bitmap(image, posX, posY, 0);
    }


};

// GameManager class
class GameManager
{
    public:
    ALLEGRO_FILE *levelData; // ALLEGRO_FILE to operate external file
    ALLEGRO_BITMAP *foodSprite, *blockSprite; // ALLEGRO_BITMAP to hold food sprite, level block sprite
    CharacterObject Pacman; // Pacman object creation of class CharacteObject
    GameObject *gameObject; // Pointer to GameObject

    int gameObjectCount; // Variable to hold total count of Game Object's in a level
    int levelGrid[SCREEN_H / TILE_SIZE][SCREEN_W / TILE_SIZE]; // 2 dimensional array to hold level data from a external file

    // Method to Initialize Level
    void InitLevel()
    {
        Pacman.image = al_load_bitmap("Pacman_Sprite_Sheet.PNG"); // Loading pacman sprite sheet
        Pacman.posX = SCREEN_W / 2; // Starting x-coordinate of pacman on the screen
        Pacman.posY = SCREEN_H / 2; // Starting y-coordinate of pacman on the screen
        Pacman.speed = 2.0; // Movement speed of pacman
        Pacman.totalFrame = 2; // Total number of pacman animation frames in the sprite sheet
        Pacman.frameDelay = 7; // Speed of pacman animation
        Pacman.InitObject(); // Initialize pacman

        gameObject = new GameObject[(SCREEN_W / TILE_SIZE) * (SCREEN_H / TILE_SIZE)];
        gameObjectCount = 0;

        foodSprite = al_load_bitmap("food.png");
        blockSprite = al_load_bitmap("block.png");

        levelData = al_fopen("level_1.data","r");

        // Loading and initializing Level & Game Objects
        for(int row=0;row < SCREEN_H / TILE_SIZE;row++)
        {
            for(int column=0;column < SCREEN_W / TILE_SIZE;column++)
            {
                levelGrid[row][column] = al_fgetc(levelData);
                switch(levelGrid[row][column])
                {
                    case 10:
                    column--;
                    break;
                    case 49:
                    gameObject[gameObjectCount].InitObject(blockSprite, column * TILE_SIZE, row * TILE_SIZE, BLOCK);
                    gameObjectCount++;
                    break;
                    case 48:
                    gameObject[gameObjectCount].InitObject(foodSprite, column * TILE_SIZE, row * TILE_SIZE, FOOD);
                    gameObjectCount++;
                    break;
                }
            }
        }

    }

    void DrawLevel(ALLEGRO_DISPLAY *screen)
    {
        // Draw level objects
        for(int loopCounter = 0; loopCounter < gameObjectCount; loopCounter++)
        {
            gameObject[loopCounter].DrawObject();
        }

        // Draw pacman Character Object
        Pacman.DrawObject(screen);

    }

    void UpdateLogic()
    {
        // Update pacman Character Object logic
        Pacman.UpdateLogic();
        // Update pacman collision check
        for(int loopCounter = 0; loopCounter < gameObjectCount; loopCounter++)
        {
            Pacman.CollisionLogic(gameObject[loopCounter]);
        }
    }

    // Method to update keypress events
    void KeyboardEventUpdate(ALLEGRO_EVENT &event, bool flag)
    {
        switch(event.keyboard.keycode)
        {
            case ALLEGRO_KEY_UP:
            keyboard[KEY_UP] = flag;
            break;
            case ALLEGRO_KEY_DOWN:
            keyboard[KEY_DOWN] = flag;
            break;
            case ALLEGRO_KEY_LEFT:
            keyboard[KEY_LEFT] = flag;
            break;
            case ALLEGRO_KEY_RIGHT:
            keyboard[KEY_RIGHT] = flag;
            break;
            case ALLEGRO_KEY_ESCAPE:
            keyboard[KEY_ESCAPE] = flag;
            break;
        }
    }

};

int main()
{
    al_init(); // Start Allegro
    ALLEGRO_DISPLAY *screen = NULL; // Main display
    ALLEGRO_EVENT_QUEUE *event_queue = NULL; // Event queue to maintain events
    ALLEGRO_TIMER *timer = NULL; // Timer to control game fps

    // Initializing screen, event queue and timer
    screen = al_create_display(SCREEN_W, SCREEN_H);
    event_queue = al_create_event_queue();
    timer = al_create_timer(1.0/FPS); // Timer set to tick at 60 frames per second

    al_init_image_addon(); // Initialize Allegro image addon
    al_install_keyboard(); // Initialize Allegro keyboard
    al_start_timer(timer); // Start timer

    // Register event sources to be handled in the event queue
    al_register_event_source(event_queue,al_get_display_event_source(screen));
    al_register_event_source(event_queue,al_get_timer_event_source(timer));
    al_register_event_source(event_queue, al_get_keyboard_event_source());

    GameManager gameManager; // Object creation
    gameManager.InitLevel(); // Function call

    //Main game loop
    while(!keyboard[KEY_ESCAPE]) // Run while escape key is not pressed
    {
        ALLEGRO_EVENT event; // ALLEGRO_EVENT to hold events
        al_wait_for_event(event_queue,&event); // Wait for events to occur

        // Display handler
        // Draw if timer counter has incremented and there are no events to handle
        // and event queue is empty
        if(event.type == ALLEGRO_EVENT_TIMER && al_is_event_queue_empty(event_queue))
        {
            gameManager.DrawLevel(screen);
            al_flip_display(); // Display backbuffer on to the main screen
            al_clear_to_color(al_map_rgb(0, 0, 0)); // Clear display to black
        }

        //Event handlers
        if (event.type == ALLEGRO_EVENT_TIMER)
        {
            gameManager.UpdateLogic(); // Function call
        }
        else if(event.type==ALLEGRO_EVENT_DISPLAY_CLOSE)
        {
            break; // End game loop on closing display window
        }
        else if(event.type == ALLEGRO_EVENT_KEY_DOWN)
        {
            gameManager.KeyboardEventUpdate(event, true); // Update routine on key press
        }
        else if(event.type == ALLEGRO_EVENT_KEY_UP)
        {
            gameManager.KeyboardEventUpdate(event, false); // Update routine on key release
        }

    } // End of Game Loop

    al_destroy_display(screen); // Destroy display
    return 0;
}


Required data to run the game:

▪ Pacman_Sprite_Sheet.png
▪ block.png
▪ food.png
▪ level_1.data
 
1111111111111111111111111
1                       1
1 00000000000000000000001
1 011111111 0011111111 01
1 01        00       1 01
1 01 00000000000000001 01
1 01 011111 0011111 01 01
1 01 01     00    1 01 01
1 0  0  0000000000  0  01
1 00000000000000000000001
1 01 01 00000000001 01 01
1 01 011111 0011111 01 01
1 01 0      00      01 01
1 01 00000000000000001 01
1 011111111 0011111111 01
1 0         00         01
1 00000000000000000000001
1111111111111111111111111

Sunday, December 11, 2011

2D C++ Game: Part 7 - Game Plot

0 comments
Game Plot:
The whole idea is to make a clone of old classic game "Pacman".

Game Objects:
▪ Pacman - The main character you will be controlling.
▪ Food - To be eaten by Pacman.
▪ Level Blocks - Pacman cannot pass through these blocks.
▪ Monsters - On collision Pacman looses life.
▪ Power Ups - Makes Monsters weak for a certain period of time.

Game Objective: You have to eat all the food in the level avoiding the enemies, on completion of food, level will be completed.

Technicalities Involved:
Process plan
 Loading map file and drawing all the objects on to the screen.
 Updating Pacman direction according to keypresses.
 Check for collisions occurring in between level objects and Pacman.
 Update monster AI.
 Make monsters weak for a certain period of time when Pacman consumes Power ups.
 Load next level upon completion of food.
Level loading and drawing process:
We will be doing a tile map approach where all object/images will be of maximum dimension of 32 X 32 plotted on a imaginary grid on the screen.
Object Width = 32
Object Height = 32
Game window size = 800 X 600, i.e width = 800, height = 600
Total no. of objects along x-axis = window width / object width = 800 / 32 = 25
Total no. of objects along y-axis = window height / object height = 600 / 32 = 18
Thus, maximum no. of objects on the screen = 25 + 18 = 43
The contents of the level file is loaded into a 2D array:

2DArray[Total no. of objects along x-axis][Total no. of objects along y-axis]

The imaginary grid on the screen looks like this,

This is how the contents of level data file looks like,

Constants:
 Food - 0
 Block - 1
 Power up - 2

Lets take a small part of the data from the level file

Now plotting the selected data stored in the array on to the imaginary grid we get,
Similarly, all other objects are drawn on to imaginary grid on the screen,

Class Diagram:

Thursday, November 24, 2011

2D C++ Game: Part 6 - Image Background Transparency, Game FPS, Events, Game Loop

0 comments
// Allegro library
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>

//Screen resolution
#define SCREEN_W 640
#define SCREEN_H 480

// Game fps
#define FPS 60

int main()
{
    al_init(); // Start Allegro
    ALLEGRO_DISPLAY *screen = NULL; // Main display
    ALLEGRO_EVENT_QUEUE *event_queue = NULL; // Event queue to maintain events
    ALLEGRO_TIMER *timer = NULL; // Timer to control game fps

    // Initializing screen, event queue and timer
    screen = al_create_display(SCREEN_W, SCREEN_H);
    event_queue = al_create_event_queue();
    timer = al_create_timer(1.0/FPS); // Timer set to tick at 60 frames per second

    // Register event sources to be handled in the event queue
    al_register_event_source(event_queue,al_get_display_event_source(screen));
    al_register_event_source(event_queue,al_get_timer_event_source(timer));

    al_init_image_addon(); // Initialize Allegro image addon
    al_start_timer(timer); // Start timer

    // ALLEGRO BITMAP 'image' to hold the image
    ALLEGRO_BITMAP *image = NULL;
    // Load bitmap
    image = al_load_bitmap("Pacman_Sprite.png");
    // Convert image background to transparent
    al_convert_mask_to_alpha(image,al_map_rgb(255, 0, 255));



    int x=0; // x coordinate of the image

    while(1) //Game Loop
    {
        ALLEGRO_EVENT event; // ALLEGRO_EVENT to hold events
        al_wait_for_event(event_queue,&event); // Wait for events to occur

        // Display handler
        // Draw if timer counter has incremented and there are no events to handle
        // and event queue is empty
        if(event.type == ALLEGRO_EVENT_TIMER && al_is_event_queue_empty(event_queue))
        {
            al_draw_bitmap(image, x, SCREEN_H/2, 0); // Draw image on the backbuffer
            al_flip_display(); // Display backbuffer on to the main screen
            al_clear_to_color(al_map_rgb(0, 0, 0)); // Clear display to black
        }

        //Event handlers
        if (event.type == ALLEGRO_EVENT_TIMER)
        {
            // Increment x coordinate of the image
            // When position of the image is more than the screen width, reset x coordinate to 0
            if(++x>=SCREEN_W)x=0;
        }else if(event.type==ALLEGRO_EVENT_DISPLAY_CLOSE)
        {
            break; // End game loop on closing display window
        }


    }// End of Game Loop

    al_destroy_display(screen); // Destroy display
    return 0;
}
Explanation:
▪ Image Background Transparency
    // ALLEGRO BITMAP 'image' to hold the image
    ALLEGRO_BITMAP *image = NULL;
    // Load bitmap
    image = al_load_bitmap("Pacman_Sprite.png");
    // Convert image background to transparent
    al_convert_mask_to_alpha(image,al_map_rgb(255, 0, 255));
Image background transparency is achieved with the Allegro routine al_convert_mask_to_alpha(ALLEGRO_BITMAP *bitmap, ALLEGRO_COLOR mask_color) which takes 2 parameters:
 ALLEGRO_BITMAP structure which holds our image.
 ALLEGRO_COLOR structure, in our case we gave al_map_rgb(255, 0, 255) which is the rgb value for magenta, which is the background color of our image.
▪ Game FPS
// Game fps
#define FPS 60
ALLEGRO_TIMER *timer = NULL; // Timer to control game fps
timer = al_create_timer(1.0/FPS); // Timer set to tick at 60 frames per second
al_register_event_source(event_queue,al_get_timer_event_source(timer));
al_start_timer(timer); // Start timer

Sunday, November 6, 2011

2D C++ Game: Part 5 - Drawing Graphics From Image File

0 comments
In this part, we will be displaying this image on the screen using allegro_image functions/routines.
house.png
Objective: Load and display image file.
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>

#define SCREEN_W 640
#define SCREEN_H 480
int main()
{
    al_init();
    ALLEGRO_DISPLAY *screen = NULL;
    screen = al_create_display(SCREEN_W, SCREEN_H);

    al_init_image_addon();
    ALLEGRO_BITMAP *image= NULL;
    image = al_load_bitmap("house.png");
    al_draw_bitmap(image, SCREEN_W/2, SCREEN_H/2, 0);
    al_flip_display();

    al_rest(5.0);
    al_destroy_display(screen);
    return 0;
}

Explanation:
▪ al_init_image_addon();
Before we start, we need to initialize the image addon first before using any other image related funcitons or routines.

▪ ALLEGRO_BITMAP *image = NULL;
Then we create a pointer 'image' to ALLEGRO_BITMAP structure which will hold our image.

▪ image = al_load_bitmap("house.png");
Then we use al_load_bitmap(const char *filename) function to load the image from a specified path to our ALEGRO_BITMAP structure we created.

▪ al_draw_bitmap(image, SCREEN_W/2, SCREEN_H/2, 0);
Then we draw the image on to the back buffer using al_draw_bitmap(ALLEGRO_BITMAP *bitmap, float dx, float dy, int flags) routine which takes 3 parameters as follows:
 ALLEGRO_BITMAP structure which holds our image.
 X coordinate of the image to be drawn on the screen.
 Y coordinate of the image to be drawn on the screen.
 The flags parameter can be 0 or one of the following flags:
ALLEGRO_FLIP_HORIZONTAL - flip the bitmap about the y-axis.
ALLEGRO_FLIP_VERTICAL - flip the bitmap about the x-axis.

The picture below explains, how the image is displayed on the screen as per our specified parameters.