Talking about Bubbles 2 game, Game development, Javascript and Users contributions.
Following the example published in HTML5 game creation prototype post, Esteban Gallardo from Free Creation Games shares with us a more compex prototype to create a game like Bubbles 2.
This is what you’ll get (not on IE):
And this is the commented javascript to manage the whole game:
// ************************************
// Class Ball
// The user will control the ball movements
// with the control keys.
// ************************************
function Ball()
{
// CONSTRUCTOR
this.x = 0;
this.y = 0;
this.vx = 0;
this.vy = 0;
this.radius = 10;
this.color = "#000000";
this.iterator =0;
// ------------------------------------
// Ball reset
this.ResetBall = function()
{
this.x = 0;
this.y = 0;
this.vx = 0;
this.vy = 0;
this.radius = 10;
this.color = "#000000";
this.iterator =0;
}
// ------------------------------------
// Ball's logic
this.Update = function()
{
if (m_controlMode==CONTROL_MODE_MOUSE)
{
if (m_mouseDown)
{
this.vx=(m_mousePositionX-this.x)/5;
this.vy=(m_mousePositionY-this.y)/5;
}
}
else
{
// PROCESS INPUT
if (m_keyPressedLeft) this.vx--;
if (m_keyPressedRight) this.vx++;
if (m_keyPressedUp) this.vy--;
if (m_keyPressedDown) this.vy++;
}
// BALL'S LOGIC
this.x+=this.vx;
this.y+=this.vy;
this.vx*=friction;
this.vy*=friction;
// CONTROL LIMITS
if (this.xSCREEN_WIDTH) this.x=SCREEN_WIDTH-this.radius;
if (this.y+this.radius>SCREEN_HEIGHT) this.y=SCREEN_HEIGHT-this.radius;
}
// ------------------------------------
// Ball's Render
this.Render = function()
{
// FILL AREA
/*
m_context.beginPath();
m_context.fillStyle=this.color;
m_context.arc(this.x,this.y,this.radius,0,Math.PI*2,true);
m_context.closePath();
m_context.fill();
*/
// DRAW BUBBLE
m_context.drawImage(m_bubbleImage, this.x-this.radius, this.y-this.radius, this.radius*2, this.radius*2);
}
}
// ************************************
// Class Item
// Represent the items that the user's ball can collide to
// ************************************
function Item(type)
{
// var TYPE_ITEM_BUBBLE = 1;
// var TYPE_ITEM_ENEMY = 2;
// CONSTRUCTOR
this.type = type;
this.x = 0;
this.y = 0;
this.vx = 0;
this.vy = 0;
this.radius = 0;
this.color = "#000000";
this.iterator = 0;
this.isAlive = false;
// ------------------------------------
// Item Initialitzation
this.Init = function(radiusIni, radiusEnd, speedIni, speedEnd)
{
this.isAlive = true;
this.radius = radiusIni+Math.floor(Math.random()*(radiusEnd-radiusIni));
this.x = Math.floor(Math.random()*SCREEN_WIDTH);
this.y = 0;
this.vx = 0;
this.vy = speedIni+Math.floor(Math.random()*(speedEnd-speedIni));
// alert("Item::Init: Initialitzation of a bubble::this.radius="+this.radius);
}
// ------------------------------------
// Reset the object to its initial values
this.ResetItem = function()
{
this.x = 0;
this.y = 0;
this.vx = 0;
this.vy = 0;
this.isAlive = false;
}
// ------------------------------------
// Check if the bubble collide with the bubble of the player
this.IsCollision = function()
{
if (this.isAlive)
{
if (Math.abs(this.x-m_ball.x)+Math.abs(this.y-m_ball.y)x)&&(this.y+this.widthText+10>y));
case 'center':
return ((this.x-5-(this.widthText/2)x)&&(this.y+this.widthText+10>y));
default:
return ((this.x-5x)&&(this.y+this.widthText+10>y));
break;
}
}
// ------------------------------------
// Render the text
this.Render = function()
{
// ++ RENDER ++
m_context.font = this.font;
m_context.textAlign = this.textAlign;
m_context.textBaseline = this.textBaseline;
this.sizeText = m_context.measureText(this.text);
this.widthText = this.sizeText.width;
// DRAW RECTANGLE IN THE BACKGROUND OF TEXT
if (enableBackground)
{
m_context.beginPath();
m_context.strokeStyle = '#000000';
m_context.fillStyle = this.color;
switch (align)
{
case 'left':
m_context.rect(this.x-5, this.y-5, this.widthText+10, this.heightText+10);
break;
case 'center':
m_context.rect(this.x-5-(this.widthText/2), this.y-5, this.widthText+10, this.heightText+10);
break;
case 'right':
break;
}
m_context.fill();
m_context.stroke();
}
// DRAW TEXT
if (enableBackground)
{
m_context.fillStyle = '#000000';
}
else
{
m_context.fillStyle = this.color;
}
m_context.fillText(this.text, this.x, this.y);
m_context.closePath();
}
}
// ++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++
// GLOBAL CODE
// ++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++
// ++ CONSTANTS ++
var SCREEN_WIDTH = 500;
var SCREEN_HEIGHT = 500;
var STATE_LOAD = 0;
var STATE_MENU = 1;
var STATE_RUN = 2;
var STATE_END = 3;
var CONTROL_MODE_KEYBOARD = 0;
var CONTROL_MODE_MOUSE = 1;
var TYPE_ITEM_BUBBLE = 1;
var TYPE_ITEM_ENEMY = 2;
var TOTAL_NUMBER_BUBBLES = 20;
var TOTAL_NUMBER_ENEMIES = 20;
// ++ MEMBERS ++
var m_context; // Document context
var m_state = STATE_LOAD; // Main game state
var m_iterator = 0;
var m_lastTime = 0; // The time of the last frame
var m_difTime = 0; // The time spent between two frames
var m_askToLose = false;
var m_score = 0;
var m_controlMode; // Select between two control modes (KEYBOARD,MOUSE)
var m_mouseDown; // Reports when the mouse is being pressed
var m_mousePositionX; // X coordinate of the pressed mouse
var m_mousePositionY; // Y coordinate of the pressed mouse
// BUTTONS
var m_playWidthMouse;
var m_playWidthKeyboard;
var m_pressHereToPlayAgain;
// IMAGES
var m_bgMenuImage;
var m_bgGameImage;
var m_bubbleImage;
var m_thornsImage;
// ACTORS
var m_ball;
var m_bubbles; // List of bubbles
var m_bubbleTimeGeneration=0; // Time acumulator
var m_bubbleTimeGeneration_Limit=2000; // Time needed between two bubble generations
var m_bubbleTimeGeneration_Factor=1.1; // Decrease factor in the generation bubble time
var m_enemies;
var m_enemyTimeGeneration=0; // Time acumulator
var m_enemyTimeGeneration_Limit=2000; // Time needed between two enemies generations
var m_enemyTimeGeneration_Factor=0.8; // Time decrease factor in the generation of an enemy
var m_level=1; // Game level
var m_timeLevelUp=0; // Time acumulator
var m_timeLevelUp_Limit = 15000; // Time to reach a level up
var m_timeLevelUp_Factor = 1.1; // Grow time factor for level up
var m_timeoutLevelUpTitle = 0; // Grow time factor for level up
// INPUT
var m_keyPressedLeft=false;
var m_keyPressedRight=false;
var m_keyPressedUp=false;
var m_keyPressedDown=false;
var friction=0.9;
// ------------------------------------
// OnKeyDown
document.onkeydown = function(event)
{
var key_pressed;
if(event == null)
{
key_pressed = window.event.keyCode;
}
else
{
key_pressed = event.keyCode;
}
switch(key_pressed)
{
case 37:
m_keyPressedLeft=true;
break;
case 38:
m_keyPressedUp=true;
break;
case 39:
m_keyPressedRight=true;
break;
case 40:
m_keyPressedDown=true;
break;
}
}
// ------------------------------------
// OnKeyUp
document.onkeyup = function(event)
{
var key_pressed;
if(event == null)
{
key_pressed = window.event.keyCode;
}
else
{
key_pressed = event.keyCode;
}
switch(key_pressed)
{
case 37:
m_keyPressedLeft=false;
break;
case 38:
m_keyPressedUp=false;
break;
case 39:
m_keyPressedRight=false;
break;
case 40:
m_keyPressedDown=false;
break;
}
}
// ------------------------------------
// Ask to create a new bubble
function AskNewBubble()
{
var i=0;
for (i=0;im_bubbleTimeGeneration_Limit)
{
m_bubbleTimeGeneration=0;
if (m_timeoutLevelUpTitle<=0) AskNewBubble();
}
// UPDATE BUBBLE
for (i=0;im_enemyTimeGeneration_Limit)
{
m_enemyTimeGeneration=0;
if (m_timeoutLevelUpTitle<=0) AskNewEnemy();
}
// UPDATE ENEMIES
for (i=0;im_timeLevelUp_Limit)
{
m_level++;
m_timeoutLevelUpTitle = 2000;
m_timeLevelUp = 0;
m_timeLevelUp_Limit*=m_timeLevelUp_Factor;
// CHANGE BUBBLE RATE
m_bubbleTimeGeneration_Limit*=m_bubbleTimeGeneration_Factor;
// CHANGE ENEMY RATE
m_enemyTimeGeneration_Limit*=m_enemyTimeGeneration_Factor;
}
if (m_timeoutLevelUpTitle>0)
{
m_timeoutLevelUpTitle -= m_difTime;
}
// EVALUATE MAIN GAME STATE
switch (m_state)
{
/////////////////////////
case STATE_LOAD:
switch (m_iterator)
{
case 1:
// INIT GRAPHICS
m_context=game_area.getContext('2d');
// LOAD IMAGES
m_bgGameImage = new Image();
m_bgGameImage.src = 'images/bg_game.jpg';
m_bubbleImage = new Image();
m_bubbleImage.src = 'images/bubble.png';
m_thornsImage = new Image();
m_thornsImage.src = 'images/thorns.png';
m_bgMenuImage = new Image();
m_bgMenuImage.onload = function() { m_iterator=100; };
m_bgMenuImage.src = 'images/bg_menu.jpg';
// INIT GAME ELEMENTS
m_ball = new Ball();
// BUBBLES INIT
m_bubbles=new Array(TOTAL_NUMBER_BUBBLES);
var i;
for (i=0;i0)
{
var titleLevelUp = new MyText('LEVEL '+m_level, SCREEN_WIDTH/2, (SCREEN_HEIGHT/4), 24, '#ffffff', '50px sans-serif', 'center', 'top', false);
titleLevelUp.Render();
}
// ++ END CONDITIONS ++
if (m_askToLose)
{
m_askToLose=true;
ChangeState(STATE_END);
}
break;
/////////////////////////
case STATE_END:
switch (m_iterator)
{
case 1:
// INIT TEXT
var titleGameOver = new MyText('GAME OVER',SCREEN_WIDTH/2,SCREEN_HEIGHT/6,24,'#ff0000', '30px sans-serif', 'center', 'top', true);
var titleFinalScore = new MyText('YOUR SCORE: '+m_score,SCREEN_WIDTH/2,SCREEN_HEIGHT/2,24,'#ffffff', '30px sans-serif', 'center', 'top', false);
m_pressHereToPlayAgain = new MyText('Press here to go to menu screen',SCREEN_WIDTH/2,5*SCREEN_HEIGHT/6,24,'#00ff00', '20px sans-serif', 'center', 'top', true);
// RENDER TEXT
titleGameOver.Render();
titleFinalScore.Render();
m_pressHereToPlayAgain.Render();
break;
}
// CHECK BUTTON SELECTION
if (m_mouseDown)
{
if (m_pressHereToPlayAgain.IsInside(m_mousePositionX,m_mousePositionY))
{
m_mouseDown=false;
ChangeState(STATE_MENU);
}
}
break;
}
}
// SET MAIN LOOP
setInterval(Update, 30);
Download the source code with all images.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.