0
\$\begingroup\$

We are working in a simple MP strategy game using Node, Express and Sockets! I'm wondering if there's an easy approach to a transformation to make a Top View game into a 3D Isometric, without adding a Z axis to all positions in the game.

Ideally by just updating all the graphic files and the contents on drawing.js which is the controller in charge of doing all graphical operations.

function Drawing(context, images) {
  this.context = context;
  //this.context.imageSmoothingEnabled = false;
  this.images = images;
  console.log('once');
}

//show names
var show_names = '1';

/************************************************************/
/* Definiciones generales ***********************************/

Drawing.NAME_FONT             = '14px Questrial';
Drawing.NAME_COLOR            = '#FFF';
Drawing.HP_COLOR              = '#89D926';
Drawing.HP_MISSING_COLOR      = '#FF0000';
Drawing.SHIELD_COLOR          = '#26C6D9';
Drawing.SHIELD_MISSING_COLOR  = '#BEF8FF';
Drawing.BASE_IMG_URL          = '/public/img/';
Drawing.TILE_SIZE             = 2500;

/************************************************************/
/* Localizamos las imágenes a usar **************************/

Drawing.IMG_SRCS = {
  'explosion':              '/public/img/explosion.png',
  'smoke':                  '/public/img/smoke.svg',
  'panzer':                 '/public/img/panzer.png',
  'self_turret':            '/public/img/self_turret.png',
  'other_tank':             '/public/img/other_tank.png',
  'other_turret':           '/public/img/other_turret.png',
  'drone':                  '/public/img/drone.png',
  'shadow':                 '/public/img/broken_panzer.png',
  'nada':                   '/public/img/nada.png',
  'shield':                 '/public/img/shield.png',
  'ammo_regular':           '/public/img/game/ammo/regular.png',
  'ammo_healco_care':       '/public/img/game/ammo/healco_care.png',
  'ammo_slowco_frozen':     '/public/img/game/ammo/slowco_frozen.png',
  'tile':                   '/public/img/full_map_02.png',
  'shotgun_powerup':        '/public/img/shotgun_powerup.png',
  'speedboost_powerup':     '/public/img/speedboost_powerup.png',
  'rapidfire_powerup':      '/public/img/rapidfire_powerup.png',
  'shield_powerup':         '/public/img/shield_powerup.png',
  'healthpack_powerup':     '/public/img/healthpack_powerup.png',
  'explosion_media':        '/public/img/explosion.png',
  'zombie':                 '/public/img/boxes.png',
  'people':                 '/public/img/boxes.png',
};

/************************************************************/
/* Crea las imagenes en canvas ******************************/

Drawing.create = function(context) {
  var images = {};
  for (var key in Drawing.IMG_SRCS) {
    images[key] = new Image();
    images[key].src = Drawing.IMG_SRCS[key];
  }
  return new Drawing(context, images);
};

/************************************************************/
/* Limpiamos el canvas **************************************/

Drawing.prototype.clear = function() {
  this.context.clearRect(0, 0, Constants.CANVAS_WIDTH, Constants.CANVAS_HEIGHT);
};

/************************************************************/
/* Crea las unidades en el mapa *****************************/

Drawing.prototype.drawTank = function(isSelf, coords, orientation, turretAngle, name, kind, health, hasShield, shieldsize) {
  if (show_names == 1) {
    this.context.save();
    //presición pixelar
    coords[0] = (0.5 + coords[0]) | 0;
    coords[1] = (0.5 + coords[1]) | 0;
    //ahora si
    this.context.translate(coords[0], coords[1]);
    this.context.textAlign = 'center';
    this.context.font = Drawing.NAME_FONT;
    this.context.fillStyle = Drawing.NAME_COLOR;
    this.context.fillText(name, 0, -50);
    this.context.restore();
    this.context.save();
    //presición pixelar
    coords[0] = (0.5 + coords[0]) | 0;
    coords[1] = (0.5 + coords[1]) | 0;
    //ahora si
    this.context.translate(coords[0], coords[1]);
    //los pixeles que ocupa cada unidad
    var unidad_w = 3;
    //barra de escude
    if (hasShield != null && hasShield != undefined) {
      //console.log('shield size: ' + shieldsize);
      for (var s = 0; s < 20; s++) {
        //escude
        if (s < shieldsize) {
          this.context.fillStyle = Drawing.SHIELD_COLOR;
          this.context.fillRect((s * unidad_w) + (unidad_w * 10), -42, unidad_w, 5);
        }
      }
    }
    //barra de vida
    for (var i = 0; i < 20; i++) {
      //salud
      if (i < health) {
        this.context.fillStyle = Drawing.HP_COLOR;
        this.context.fillRect((i * unidad_w) - (unidad_w * 10), -42, unidad_w, 5);
      }
      //salud perdida
      else {
        this.context.fillStyle = Drawing.HP_MISSING_COLOR;
        this.context.fillRect((i * unidad_w) - (unidad_w * 10), -42, unidad_w, 5);
        }
    }
    //c-c-coom-bo breaker!
    this.context.restore();
  }
  this.context.save();
  //presición pixelar
  coords[0] = (0.5 + coords[0]) | 0;
  coords[1] = (0.5 + coords[1]) | 0;
  //ahora si
  this.context.translate(coords[0], coords[1]);
  this.context.rotate(orientation);
  //acá arma la unidad
  var unidad = null;
  if (kind == "drone") { unidad = this.images['drone']; }
  if (kind == "panzer") { unidad = this.images['panzer']; }
  if (kind == "shadow") { unidad = this.images['shadow']; }
  //draw, primero el normal, después el volado
  if (kind != "shadow") { this.context.drawImage(unidad, -unidad.width / 2, -unidad.height / 2); }
  if (kind == "shadow") { this.context.drawImage(unidad, -170, -128); }
  //acomodamos
  this.context.restore();
  this.context.save();
  //presición pixelar
  coords[0] = (0.5 + coords[0]) | 0;
  coords[1] = (0.5 + coords[1]) | 0;
  //ahora si
  this.context.translate(coords[0], coords[1]);
  this.context.rotate(turretAngle);
  //acá arma el cañon
  var turret = null;
  if (kind == "drone") { turret = this.images['nada']; }
  if (kind == "panzer") { turret = this.images['self_turret']; }
  if (kind == "shadow") { turret = this.images['nada']; }
  this.context.drawImage(turret, -turret.width / 2, -turret.height / 2);
  this.context.restore();
  //revisa si posee escudo
  if (hasShield != null && hasShield != undefined) {
  this.context.save();
  //presición pixelar
  coords[0] = (0.5 + coords[0]) | 0;
  coords[1] = (0.5 + coords[1]) | 0;
  //ahora si
  this.context.translate(coords[0], coords[1]);
  var shield = this.images['shield'];
  this.context.drawImage(shield, -shield.width / 2, -shield.height / 2);
  this.context.restore();
  }
  //usando las proximas 7 lineas es posible hacer que la unidad disipe fuego.
  if (health < 3) {
  this.context.save();
  //presición pixelar
  coords[0] = (0.5 + coords[0]) | 0;
  coords[1] = (0.5 + coords[1]) | 0;
  //ahora si
  this.context.translate(coords[0], coords[1]);
  var smoke = this.images['smoke'];
  this.context.drawImage(smoke, -smoke.width / 2, -smoke.height / 2);
  this.context.restore();
  }

};

/************************************************************/
/* Creación de balas ****************************************/

Drawing.prototype.drawBullet = function(coords, orientation, ammo, source_x, source_y) {
  this.context.save();
  //presición pixelar
  coords[0] = (0.5 + coords[0]) | 0;
  coords[1] = (0.5 + coords[1]) | 0;

  //pixel wise, hace rendir más el GPU, previniendo posiciones imposibles
  source_x = (0.5 + source_x) | 0;
  source_y = (0.5 + source_y) | 0;

  //lineas
  this.context.beginPath();
  this.context.moveTo(source_x, source_y);
  this.context.lineTo(coords[0], coords[1]);

  //disfuminación de linea
  var grad = this.context.createLinearGradient(source_x, source_y, coords[0], coords[1]);
  grad.addColorStop(0, 'transparent');

  //color de la linea
  if(ammo == 'slowco_frozen') { grad.addColorStop(1, '#0B95FB'); }
  else if(ammo == 'healco_care') { grad.addColorStop(1, '#6CFA0B'); }
  else { grad.addColorStop(1, '#FF3939'); }
  this.context.strokeStyle = grad;
  this.context.stroke();

  //ahora si, la imagen
  this.context.translate(coords[0], coords[1]);
  this.context.rotate(orientation);
  var bullet = this.images['ammo_regular'];
  if(ammo == 'slowco_frozen') { var bullet = this.images['ammo_slowco_frozen']; }
  if(ammo == 'healco_care') { var bullet = this.images['ammo_healco_care']; }
  this.context.drawImage(bullet, -bullet.width / 2, -bullet.height / 2);
  //this.context.filter = 'blur(3px)';
  //this.context.drawImage(bullet, -bullet.width / 2, -bullet.height / 2);
  this.context.restore();
};

/************************************************************/
/* Creación de bloques **************************************/

Drawing.prototype.drawBlock = function(coords, name) {
  this.context.save();
  //presición pixelar
  coords[0] = (0.5 + coords[0]) | 0;
  coords[1] = (0.5 + coords[1]) | 0;
  //ahora si
  this.context.translate(coords[0], coords[1]);
  var block_media = this.images[name];
  this.context.drawImage(block_media, -block_media.width / 2, -block_media.height / 2);
  this.context.restore();
};

/************************************************************/
/* Creación de powerups *************************************/

Drawing.prototype.drawPowerup = function(coords, name) {
  this.context.save();
  //presición pixelar
  coords[0] = (0.5 + coords[0]) | 0;
  coords[1] = (0.5 + coords[1]) | 0;
  //ahora si
  this.context.translate(coords[0], coords[1]);
  var powerup_icon = this.images[name];
  this.context.drawImage(powerup_icon, -powerup_icon.width / 2, -powerup_icon.height / 2);
  this.context.restore();
};

/************************************************************/
/* Creación de explosiones **********************************/

Drawing.prototype.drawExplosion = function(coords) {
  this.context.save();
  //presición pixelar
  coords[0] = (0.5 + coords[0]) | 0;
  coords[1] = (0.5 + coords[1]) | 0;
  //ahora si
  this.context.translate(coords[0], coords[1]);
  var explosion_media = this.images['explosion_media'];
  this.context.drawImage(explosion_media, -explosion_media.width / 2, -explosion_media.height / 2);
  this.context.restore();
};

/************************************************************/
/* Creación del mapa ****************************************/

 // param {number} minX The minimum canvas x coordinate to start drawing from.
 // param {number} minY The minimum canvas y coordinate to start drawing from.
 // param {number} maxX The maximum canvas x coordinate to draw to.
 // param {number} maxY The maximum canvas y coordinate to draw to.

Drawing.prototype.drawTiles = function(minX, minY, maxX, maxY, salud) {
  this.context.save();
  var tile = this.images['tile'];
  for (var x = minX; x < maxX; x += Drawing.TILE_SIZE) {
    for (var y = minY; y < maxY; y += Drawing.TILE_SIZE) {
      this.context.drawImage(tile, x, y);
    }
  }
  this.context.restore();
};

My apologies if this question isn't good, first one here I believe!

Thanks in advance! Chris

\$\endgroup\$
-1
\$\begingroup\$

Well Chris, I am not going to pretend that I know how to do this from scratch. And that's isn't because I don't want to, but mainly because there are a good number of better options out there.

For example, if you were using PhaserJS you could add a plugin that converts your game from flat 2D to an isometric view.

|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for?Browse other questions tagged or ask your own question.