📜 ⬆️ ⬇️

Making Doodle Jump to HTML5

Doodle Jump
Hello, Habrazhiteli!
In this topic, I want to talk about how I created the HTML5 DoodleJump browser game without using any frameworks. For those who do not know, DoodleJump is a popular mobile game where the main character “doodler” endlessly jumps up the platforms, overcoming various obstacles, and collecting bonuses. This game is widely distributed on almost all mobile platforms, but there is no decent browser version of this game, so I decided to write a browser version of this game, even if it is controlled by keys and not a gyroscope.

So, let's begin. To begin with, we denote the scene where everything will happen:
<div id="stage"></div> 

and apply styles to it:
  #stage{ position:absolute; top:0px; left:0px; background-color:#fff3f7; background-image:url(grid.gif); width:320px; height:480px; } 

where we fill the scene with a checkered background (grid.gif), and make the resolution 320 by 480 pixels. In this scene we place a few more divs: the top panel (tray), where points will be written and the pause button (pause) will be placed, the main character of the game (doodler) and bullet (bullet) that our character will shoot. For such objects as platforms and bonuses, we create divs - containers in which, with the help of a java cycle, we will place diva for each object separately.
 <div id="stage"> <div id="header"> <div id="tray"></div> <div id="tray-border"></div> <div id="pause" onClick="gotoPause();"></div> </div> <div id="doodler"></div> <div id="bullet"></div> <div id="footer"></div> <div id="obstacle"></div> <div id="platforms"> <!-- --> </div> <div id="objects"> <!-- --> </div> <div id="doodler"></div> <div id="ammunition"></div> <div id="bullet"></div> <div id="records"></div> </div> 

Now we need to apply styles to our objects, fill them with sprites, set the width and height of objects, and also make them absolute positioning so that we can place each object regardless of other objects on the stage.
I prepared several sprites and pictures for coloring our game:

sprite screensaver

master sprite
')
footer

Here is an example of styles for the doodler element:
  #doodler{ position:absolute; background:url(sprite.png); width:62px; height:59px; } 

Knowing the coordinates of the location of the elements on the sprite, we can fill all the objects on the model above.
But the styles for springs and platforms will be slightly different, as they lie in the container, and the other parameters for them will be set from the java-script:
  #objects div{ position:absolute; background:url(sprite.png); } 

After we have created all the objects on the stage and gave them styles, we can start writing a java script. First, for the convenience of writing the game code, we stuff object selectors into variables:
  var d = document.getElementById('doodler'); var tray = document.getElementById('tray'); var header = document.getElementById('header'); var ammun = document.getElementById('ammunition'); //  ... 

As I said earlier, divs are containers such as: platforms and objects we fill with Java with a loop:
  for(i=0;i'<numPlatform;i++){ document.getElementById('platforms').innerHTML+='<div class="platform" id="p'+i+'"></div>'; } 

where numPlatform is the number of platforms in the container (the maximum number of platforms that fit on the stage, in our case there are 16). For convenience, you can create a function for moving platforms:
  function setPlatform(n,x,y,t){ p = document.getElementById('p'+n); p.style.top = y+"px"; p.style.left = x+"px"; if(t==-1){p.style.backgroundPosition = "100px 100px";} if(t>=0&&t<8){ p.style.height=16+"px"; p.style.backgroundPosition = "-399px -"+(16*t)+"px"; } if(t==8){p.style.height=24+"px"; p.style.backgroundPosition = "-399px -128px";} if(t==9){p.style.height=16+"px"; p.style.backgroundPosition = "-399px -151px";} if(t==10){p.style.height=34+"px"; p.style.backgroundPosition = "-399px -168px";} } 

Now you can easily move any platform to the desired place on the stage, and change its type:
 setPlatform([ ],[   ],[  ],[ ]); setPlatform(9,50,100,0); 

displaced platform pattern

create some more similar functions:
  setBullet(x,y);//  setObstacle(x,y,t);//    setObject(n,x,y,t);//    doodle(x,y,t,a,alpha);// . 


Create several global variables and arrays that we need in the future.
Here are some of them:
  var life = true;//   var stageSpeed = 0;//   var gravitation = 0.08; var ySpeed = 5;//   var numPlatform = 16;//  var numObjects = numPlatform;//  var xObject = new Array;//X  var yObject = new Array;//Y  var tObject = new Array;//  var yFooter = 1000;//  (footer.png) var tAmmunition = 0;//    var xPlatform = new Array;//X  var yPlatform = new Array;//Y  var tPlatform = new Array;//  var xDoodler = 136;// X  var yDoodler = 136;// Y  var tDoodler = 136;//   var record = 0;//   var xBullet;//X  var yBullet;//Y  var xSpeedBullet;//   var ySpeedBullet;//   var pause = false;// ... 

Now consider the main part of the java script of the game itself, most of the code will be in the frame () function, and run 100 times per second. Inside this function, the doodler will be constantly checked for collisions with monsters and bonuses, as well as there will be a cycle, inside which we wake up to check the doodler for collisions with each platform separately:
  function frame(){//   100    ySpeed -= gravitation;//   yDoodler -= ySpeed;//  if(xDoodler+46>=xObstacle&&xDoodler+16<=xObstacle+65&&yDoodler+59>=yObstacle&& yDoodler+59<=yObstacle+60&&tObstacle != 0){//     if(tObstacle != 6){//    if(tAmmunition>=1){//     tObstacle = 0;//   }else if(ySpeed<0){//  ,      tObstacle = 0;//  ySpeed = 10;//  }else{//     tAmmunition = 8;//    stageSpeed = 7;//     ySpeed = 0;//  life = false;//    } }else{//   if(tAmmunition == 0){//     ySpeed = 0;//  gravitation = 0;//   yDoodler -= (yDoodler - yObstacle)/6;//     X xDoodler -= (xDoodler - (xObstacle+10))/6;//     Y alphaDoodler -= 3;//   life = false;//  } } } yObstacle -= stageSpeed;//      setObstacle(parseInt(xObstacle), parseInt(yObstacle+obstacleYPosition), tObstacle);//  doodle(parseInt(xDoodler), parseInt(yDoodler), tDoodler, tAmmunition, alphaDoodler);//  ... for(i=0;i < numPlatform;i++){ yPlatform[i]-=stageSpeed;//       if(xDoodler+46>=xPlatform[i]&&xDoodler+16<=xPlatform[i]+65&& yDoodler+59>=yPlatform[i]&&yDoodler+59<=yPlatform[i]+16&&tPlatform[i]!=-1&&life&& tAmmunition == 0||tAmmunition == 7){//       if(tPlatform[i]==2){//   if(ySpeed<0){//     ySpeed = 5;//    tPlatform[i]=-1;//  } }else if(tPlatform[i]==9){//       if(ySpeed<0){ //     tPlatform[i]=10;//   } }else{//       if(ySpeed<=0){//     ySpeed = 5;//     } } } ...//       (. ) } if(tAmmunition>0&&tAmmunition<7&&ySpeed<2){ //     gravitation = 0.08; ySpeed -= 2; tAmmunition=0;//  } if(yFooter > 434){//      yFooter -= stageSpeed;//  }else{//       death();//    } footer.style.top = yFooter+"px"; if(xDoodler>296){lDoodler = xDoodler = -24;} //  «» if(xDoodler<-24){lDoodler = xDoodler = 296;} } fr = setInterval("frame()", 10);//   frame() (100  ) 

To ensure the fall of broken platforms, we write:
  if(tPlatform[i]==10){//    yPlatform[i]+=4;//    4  } 

All platforms that leave the bottom edge of the scene should appear on top, that is, if yPlatform[i] > 480 yPlatform[i] = -30, but since we have brown platforms that can fall down not depending on others, breaking order of extinction - this option will lead to an arbitrary distance between the platforms:
bug

Therefore, all platforms that are beyond the scope of visibility, we put 30 pixels above the previous hidden platform:
  if(yPlatform[i] > 480){ xPlatform[i] = parseInt(Math.random()*260); yPlatform[i] = yPlatform[lastPlatform]-30; lastPlatform = i; ... } 

Depending on which bonus the doodler stumbles upon, one of the following conditions is fulfilled: for example, if the doodler falls on a spring:
  if(tObject[i] == 0&&ySpeed<0){ //     ySpeed = 10;//    10 (    = 5) tObject[i] = 1;//       } 

This is what happens when the doodler stumbles upon other bonuses:
  if(tObject[i] == 2){// gravitation = 0.01; ySpeed = 10; tObject[i] = -1;//  tAmmunition = 1; } if(tObject[i] == 3){// gravitation = 0.008; ySpeed = 15; tObject[i] = -1; tAmmunition = 5; } if(tObject[i] == 4){// tObject[i] = -1; tAmmunition = 7; setTimeout('stopBonus()',5000);//     5  } 

Of course, this is not all, there are a lot of unexplained things left, but we have considered the main part of our work. I think the principle is clear, then we had to do so that the complexity of the game increased depending on the points scored:

how the difficulty of the game depends on the score

then we added a splash screen (with the possibility of skipping), menus, records, help, pause menu, soundtrack, and information on achievements after the fall of the doodler:

how the difficulty of the game depends on the score

When you start the game, it accesses the server and gets a list of results, which is available on the "Records" button. If the user overcomes the minimum record (located in the list on the 16th line), the game asks him a nickname, then, depending on the points scored, places him in a certain position, shifting the smaller records down.

A simple working example: here

Source: https://habr.com/ru/post/128347/


All Articles