πŸ“œ ⬆️ ⬇️

Developing the mechanics of the game Bounce from Nokia JavaScript

I have not written for a long time for Habr, today I would like to speculate on how to organize the simplest level mechanics for the game Bounce in case someone wants to do something similar and there will be questions. I think special introductions are not required, so let's start!

image

Let's start in order. I will not paint all unnecessary, but just go over the code commenting on certain points.

The first is index.html - the main executable file:
')
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta name="viewport" content="width=device-width,user-scalable=no"/> <title>Bounce</title> </head> <body> <script type="text/javascript" src="point.js"></script> <script type="text/javascript" src="init.js"></script> <script type="text/javascript" src="menu.js"></script> <script type="text/javascript" src="game.js"></script> <script type="text/javascript"> game.startLoop('menu'); </script> </body> </html> 

β†’ Watch on github

Here, I think everything is clear: we created a page frame and connected several JavaScript files.


Consider the init.js file:

 //   ,   pjs   var pjs = new PointJS('2D', 400, 400, { backgroundColor : '#C9D6FF' }); //    pjs.system.initFullPage(); //         var log = pjs.system.log; //   var game = pjs.game; //       var point = pjs.vector.point; //   var camera = pjs.camera; /    var brush = pjs.brush; /      var OOP = pjs.OOP; /      var math = pjs.math; /    //     var key = pjs.keyControl.initKeyControl(); var mouse = pjs.mouseControl.initMouseControl(); //        var score = 0; var record = 0; 

β†’ Watch on github

This is how the code turned out, so far this is enough.

Now we need to create a menu for the game, since we start the game from the cycle β€œmenu”, all that is necessary for this is already in the menu.js file that we connected, we just need to initiate the corresponding game cycle, which will be our menu, this is done in in the same menu.js file, just add the following there:

 game.newLoopFromClassObject('menu', new Menu(pjs, { name : 'Bounce', //   ( ) author : 'SkanerSoft', //   radius : 15, //     items : { //  , : loopName :   game : ' ', //     game about : ' ', //     about } })); 

β†’ See whole menu.js file on github

If we start, we get the running menu:

image

Now the most difficult: the gameplay. Everything is simple enough, but not quite. The code is divided into blocks.

The first thing we need to do is declare a game loop. Since we will have it as an independent object, with its scope, and we do not need to make it global (the game state data will not be visible in other game cycles), we will use a simple construction:

 game.newLoopFromConstructor('game', function () { /*your code*/ }); 

Here we can set the game cycle name and constructor.

Now let's move inside the constructor, and write the logic (mechanics) of the level inside it. We currently only need one cycle event: update. We will work with him and we will:

 game.newLoopFromConstructor('game', function () { //      var map = { width : 50, //   height : 50, //   source : [ //    ( ) '', '', ' 0-', ' | P 0000', // P -   ' 00000 000 00000', ' 0 0| |0 |', '0000000 000000W00 000000000000', ' 000 0W00 0 ', ' 0W0 0 ', ' 0W | 0 ', ' 000000 ', ] }; //   () var plStartPosition = false; var walls = []; //   (,    ) var cells = []; //  (,   ) var waters = []; //    (    ),    // OOP.forArr -     OOP.forArr(map.source, function (string, Y) { //     (Y -     ) OOP.forArr(string, function (symbol, X) { //      (X -     ) if (!symbol || symbol == ' ') return; //      -    //    if (symbol == 'P') { //   //   plStartPosition = point(map.width*X, map.height*Y); //    ,    } else if (symbol == 'W') { //  waters.push(game.newRectObject({ //   w : map.width, h : map.height, //   x : map.width*X, y : map.height*Y, //  fillColor : '#084379', //  alpha : 0.5 //  })); } else if (symbol == '|') { //  () cells.push(game.newRectObject({ w : map.width/2, h : map.height, x : map.width*X, y : map.height*Y, fillColor : '#FFF953', userData : { active : true //  ,     -   } })); } else if (symbol == '-') { //   cells.push(game.newRectObject({ w : map.width, h : map.height/2, x : map.width*X, y : map.height*Y, fillColor : '#FFF953', userData : { active : true } })); } else if (symbol == '0') { //   walls.push(game.newRectObject({ w : map.width, h : map.height, x : map.width*X, y : map.height*Y, fillColor : '#B64141' })); } }); }); //      //    , ,   //  ,      var player = game.newCircleObject({ radius : 20, fillColor : '#FF9191', position : plStartPosition ? plStartPosition : point(0, 0) }); player.gr = 0.5; //   player.speed = point(0, 0); //    //          this.update = function () { game.clear(); //    player.draw(); //   player.speed.y += player.gr; //   //   , ,   if (key.isDown('RIGHT')) player.speed.x = 2; else if (key.isDown('LEFT')) player.speed.x = -2; else player.speed.x = 0; //       OOP.drawArr(walls, function (wall) { if (wall.isInCameraStatic()) { //      ( ) // wall.drawStaticBox(); if (wall.isStaticIntersect(player)) { //      //       (    ) //   Y if (player.x+player.w > wall.x+wall.w/4 && player.x < wall.x+wall.w-wall.w/4) { if (player.speed.y > 0 && player.y+player.h < wall.y+wall.h/2) { //     if (key.isDown('UP')) //        "" player.speed.y = -10; //     else { //   ""    player.y = wall.y - player.h; player.speed.y *= -0.3; if (player.speed.y > -0.3) player.speed.y = 0; //      } } else if (player.speed.y < 0 && player.y > wall.y+wall.h/2) { //     player.y = wall.y+wall.h; //  ( ) player.speed.y *= -0.1; //   } } //     ,     X if (player.y+player.h > wall.y+wall.h/4 && player.y < wall.y+wall.h-wall.h/4) { if (player.speed.x > 0 && player.x+player.w < wall.x+wall.w/2) { //    player.x = wall.x-player.w; //   player.speed.x = 0; //    } if (player.speed.x < 0 && player.x > wall.x+wall.w/2) { //    player.x = wall.w+wall.x; //   player.speed.x = 0; //    } } } } }); //      () OOP.drawArr(cells, function (cell) { if (cell.active) { //    if (cell.isStaticIntersect(player)) { //   cell.active = false; //   cell.fillColor = '#9A9A9A'; //     score++; //   } } }); //    ,    //    var onWater = false; //     OOP.drawArr(waters, function (water) { //       ,    if (onWater) return; //      //     () //     //   ,     //   ,      //       if (water.isStaticIntersect(player) && player.y+player.h/2 > water.y) { player.speed.y -= 0.9; //    onWater = true; } }); //     if (player.speed.y) { player.y += player.speed.y; } if (player.speed.x) { player.x += player.speed.x; } //   brush.drawTextS({ //   text : 'Score: '+score, //    size : 30, //   color : '#FFFFFF', //   strokeColor : '#002C5D', //    strokeWidth : 1, //   x : 10, y : 10, //  style : 'bold' //   }); camera.follow(player, 50); //      }; }); 

β†’ View file on githab

Now, if we run and go into the game, we will see the following:

image

Thus, we built a simple mechanics of the game, it is not so difficult to supplement it with new elements, to enter into processing is similar.

The physics algorithm itself can be refined and coefficients can be changed, allowing you to narrow or expand the collision fields. You can also make them dynamic, based on the speed of movement of the character.

β†’ View the source of the project Bounce on github
β†’ Run example live

Video in which I develop a physics algorithm for a game of 20 minutes
Game physics



Addition of the game with new objects:


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


All Articles