📜 ⬆️ ⬇️

Development of 2D sandboxes on JavaScript from scratch

Somehow for my some plans I needed to make a small sandbox in 2D space with basic features:

1. Moving around the game world
2. Physics in motion, collisions
3. Creating blocks
4. Removing blocks

The graphic design did not bother me, so I decided to arrange everything in shades of gray, it looks like this:
')
image

Training


JavaScript is used for the work, as the project is needed for the demonstration, and there was no desire to sharpen it under the platform, and a quick review of the result was meant.
I use PointJS as a renderer.

I put all the sandbox code in one file, since writing a lot was not meant.
For this, I created a game.js file, all the source codes appearing in the article are inside this file and are described in order. The final version and a live launch at the end of the article.

The first thing to do is to initialize the engine and put the necessary methods into variables for quick access:

var pjs = new PointJS(640, 480, { // ,  backgroundColor : '#4b4843' //   }); pjs.system.initFullPage(); //   (      ) 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 width = game.getWH().w; //   var height = game.getWH().h; //      var BW = 40, BH = 40; //  ,     pjs.system.initFPSCheck(); //   fps 

After initialization, we need to create a single game loop within which our game world will exist.

 game.newLoopFromConstructor('myGame', function () { // game loop }); 

Inside this constructor, we need to define the required update method:

 game.newLoopFromConstructor('myGame', function () { // init this.update = function () { // game loop } }); 

Where // init is specified, we need to place the game world in internal variables:

  var pPos; //       var world = []; //   ,   //   ,     //     ,   //   0  P,   - ,  -   //       , // ,  ,   ,   //   . pjs.levels.forStringArray({w : BW, h : BH, source : [ '0000000000000000000000000000', '0000000000000000000000000000', '0000000000000000000000000000', '0000000000000000000000000000', '000000 00000000000000', '000 00000000000000', '000 P 000000000000000000', '000 000000000000000000', '0000000000000000000000000000', '0000000000000000000000000000' ]}, function (S, X, Y, W, H) { if (S === '0') { //      world.push(game.newRectObject({ //     x : X, y : Y, //     w : W, h : H, //    -  fillColor : '#bcbcbc' //   })); } else if (S === 'P') { //       P pPos = point(X, Y); //        } }); //     ,    var pl = game.newRectObject({ x : pPos.x, y : pPos.y, //      w : 30, h : 50, //    fillColor : 'white' //  }); var speed = point(); //        Y 

And most importantly - the mechanics of the game cycle, and all that will make the game world "come to life":

 this.update = function () { //   ,  , ,  if (key.isDown('A')) speed.x = -2; else if (key.isDown('D')) speed.x = 2; else speed.x = 0; //     ,    //     Y,   W,   -7 ( ) if (speed.x < 5) speed.y += 0.5; //    ,   if (key.isPress('W')) speed.y = -7; //    pl.draw(); //    var collisionBlocks = []; //   var drawBlocks = []; //    var selBlocks = []; //    //      var R = mouse.isPress('RIGHT'); //   var L = mouse.isPress('LEFT'); //   var MP = mouse.getPosition(); //   //    //          var createPos = point(BW * Math.floor(MP.x / BW), BH * Math.floor(MP.y / BH)); //       OOP.forArr(world, function (w, idW) { //     if (w.isInCameraStatic()) { //      drawBlocks.push(w); //       //       if (pl.getDistanceC(w.getPositionC()) < 80) { //  ,      if (mouse.isInStatic(w.getStaticBox())) { selBlocks.push(w); //  ,        if (L) { //    ,  world.splice(idW, 1); //     } } } } }); //     ,   (   ) OOP.forArr(drawBlocks, function (d) { //          d.setAlpha(1 - pl.getDistanceC(d.getPositionC()) / 250); // , ,    -     //  ,   d.draw(); //      ,      //   if (pl.getDistanceC(d.getPositionC()) < 100) { collisionBlocks.push(d); } }); //      OOP.forArr(selBlocks, function (s) { brush.drawRect({ //      x : sx, y : sy, w : sw, h : sh, strokeColor : '#ac5a5a', //   strokeWidth : 2 //  2  }); }); //      var canCreate = false; var dist = pl.getDistanceC(MP); //      if (!selBlocks.length && dist > 50 && dist < 100) { //     canCreate = true; //     brush.drawRect({ //    ,   x : createPos.x, y : createPos.y, //    w : BW, h : BH, strokeColor : '#69ac5a', //  strokeWidth : 2 }); } //         if (L && canCreate) { world.push(game.newRectObject({ //    x : createPos.x, y : createPos.y, w : BW, h : BH, fillColor : '#e2e2e2' })); } //   ,   ,   //    pl ()   speed,    //    collisionBlocks pjs.vector.moveCollision(pl, collisionBlocks, speed); //       camera.follow(pl, 10); //   fps brush.drawTextS({ text : pjs.system.getFPS(), color : 'white', size : 50 }); }; 

This is all the code required for the game.

Result: In the browser
Source: On GitHub

For those who are more comfortable and clearer to watch video tutorials, there is a video option:

Video Lesson 2D sandbox on JavaScript

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


All Articles