Angry Pigs

Web

Project Overview

  • Project Type: Web Game with Level Editor
  • Role: Programmer & UI Artist
  • Software: Box2D, VS Code & Photoshop
  • Languages: Javascript, HTML, CSS
  • Download link: Play Game

Project Brief

The main focus of this project was to work with a physics engine as well as store and retrieve game data from the server.
The project was divided in two phases. The first task was creating the level editor and the second was to create the actual game. The back end development was made using PHP to store the game data in JSON format. The level editor was made entirely by myself and the game was a 2 person team


Responsibilities/Achievements

  • - Apply the Model View Controller architectural pattern to integrate the physics engine and the graphic elements
  • - Learn and implement Box2D physics engine, creating reusable classes for the game entities
  • - Designing and storing a JSON data file that allowed fast integration with further steps in the development process
  • - Dealing with JavaScript user-driven events such as click, drag and drop to create levels
  • - Create custom JavaScript Events to be handled by other components
  • - Make sure the the level scaled correcly whith screen resizes

Code Samples


/*
* Carlos Adan Cortes De la Fuente
* All rights reserved. Copyright (c)
* Email: dev@carlosadan.com
*/

highlightSelected(event) {
    event.preventDefault();
    let collidable = $(event.target);
    collidable.siblings('div.collidable').removeClass('highlighted');
    collidable.addClass('highlighted');
    // Create a custom event to broadcast to the object inspector 
    let collidableClickEvent = new CustomEvent('collidableclicked', { 
        detail : collidable.data('id'),
        bubbles : true,
        cancelable : true
    });
    event.target.dispatchEvent(collidableClickEvent);
}											
										

/*
* Carlos Adan Cortes De la Fuente
* All rights reserved. Copyright (c)
* Email: dev@carlosadan.com
*/

import { Physics } from './Physics.js';

export const ObjectType = {
    BIRD : 0,
    COLLIDABLE : 1,
    BULLET : 2,
    ENCLOSER : 3,
    CANNON : 4
};
                                            
export class GameObject {

    constructor(options) {

        // Init the general values that every game object should have
        this.id = options.objectInfo.id;
        this.posX = options.objectInfo.posX * (options.renderArea.width / options.editorScreenSize.width);
        this.posY = options.objectInfo.posY * (options.renderArea.height / options.editorScreenSize.height);
        this.objectType = options.type;
        this.rigidBody = null;
        
        // Depending on the type of object we customize the creation of every game object
        switch(this.objectType) {
            case ObjectType.BIRD: 
                this.width = 40;
                this.height = 37; 
                break;
            case ObjectType.COLLIDABLE: 
                this.width = options.objectInfo.width * (options.renderArea.width / options.editorScreenSize.width);
                this.height = options.objectInfo.height * (options.renderArea.height / options.editorScreenSize.height);
                this.texture = options.objectInfo.texture;
                this.mass = options.objectInfo.mass;
                this.bounce = options.objectInfo.bounce;
                this.friction = options.objectInfo.friction;
                this.rotation = 0;
                break;
            case ObjectType.BULLET: 
                this.posX = options.cannonPos.posX + options.cannonPos.width / 2;
                this.posY = options.cannonPos.posY + options.cannonPos.height / 2;
                this.radius = 30;
                this.mass = 100;
                this.bounce = 0.5;
                this.friction = 0.5;
                this.rotation = 0;
                break;
            case ObjectType.ENCLOSER: 
                this.defineEnclosers(options.renderArea);
                break;
            case ObjectType.CANNON:
                this.width = 192;
                this.height =  192;
                this.rotation = 0;
                break;
        }
    }

    // Takes the physics coordinates and updates the model to be rendered
    updateModel() {
        if(this.rigidBody != null) {
            this.posX = this.rigidBody.GetBody().GetPosition().x * Physics.WORLD_SCALE;
            this.posY = this.rigidBody.GetBody().GetPosition().y * Physics.WORLD_SCALE;

            if(this.objectType == ObjectType.BIRD || this.objectType == ObjectType.COLLIDABLE || this.objectType == ObjectType.BULLET) {
                this.rotation = this.rigidBody.GetBody().GetAngle() * Physics.RAD_2_DEG;
            }
        }
    }

    // Creates the boundaries of the level in the physics engine
    defineEnclosers(renderArea) {
        switch(this.id) {
            case EncloserPosition.TOP:
                this.width = renderArea.width / 2;
                this.height = 20;
                this.posX = renderArea.width / 2;
                this.posY = 0 - this.height;
                this.position = EncloserPosition.TOP;
                break;
            case EncloserPosition.RIGHT:
                this.width = 20;
                this.height = renderArea.height / 2;
                this.posX = renderArea.width + this.width;
                this.posY = renderArea.height / 2;
                this.position = EncloserPosition.RIGHT;
                break;
            case EncloserPosition.BOTTOM:
                this.width = renderArea.width / 2;
                this.height = 20;
                this.posX = renderArea.width / 2;
                this.posY = renderArea.height + this.height;
                this.position = EncloserPosition.BOTTOM;
                break;
            case EncloserPosition.LEFT:
                this.width = 20;
                this.height = renderArea.height / 2;
                this.posX = 0 - this.width;
                this.posY = renderArea.height / 2;
                this.position = EncloserPosition.LEFT;
                break;
        }
    }  
}