0

I am making a game, and I faced one problem. I need to reverse my character when he moves left and I can't just create a reverse image and use it and I can't reverse canvas because I'll have some new characters and they shouln't reverse. One way is to refer to my character css properties and using js add something like this:

-webkit-transform: scaleX(-1);
transform: scaleX(-1);

Can I do that in canvas and how?


Move with arrows

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var lifes = 700;

var fon = new Image();
fon.src = "https://i.stack.imgur.com/HjXpq.jpg";

var life_red = new Image();
life_red.src = "https://i.stack.imgur.com/sGZ7l.jpg";

var life_green = new Image();
life_green.src = "https://i.stack.imgur.com/9eWXX.jpg";

var iron_man_img = new Image(); // Player walking right
iron_man_img.src = 'https://i.stack.imgur.com/aeTtS.png';
var iron_man = {
  x: 300,
  y: 50,
  dx: 100,
  dy: 0.1,
  dfly: 500,
  run: 0, //animation
  runspeed: 5, // animation speed
  fly: false,
  timeforflying: 0,
  alive: true
}
var keys = {};

function setKey(event, status) {
  var code = event.keyCode;
  var key;
  if (code == 32) {
    key = "Space";
  } else if (code == 37) {
    key = "Left";
  } else if (code == 38) {
    key = "Up";
  } else if (code == 39) {
    key = "Right";
  } else if (code == 40) {
    key = "Down";
  } else {
    key = String.fromCharCode(code);
  }
  keys[key] = status;
}

document.addEventListener('keydown', function(e) {
  setKey(e, true);
});
document.addEventListener('keyup', function(e) {
  setKey(e, false);
});
document.addEventListener('blur', function() {
  keys = {};
});

function isDown(key) {
  return keys[key];
}
iron_man_img.onload = function() {
  last = Date.now();
  game();
}

function game() {

  var now = Date.now();
  var dt = (now - last) / 1000;
  update(dt);
  render();
  last = now;
  requestAnimFrame(game);
}

function update(dt) {
  if (isDown("Right") || isDown("D")) {
    iron_man.run += iron_man.runspeed * dt;
    iron_man.x += iron_man.runspeed * dt * 10;
  }
  if (isDown("Left") || isDown("A")) {
    iron_man.run += iron_man.runspeed * dt;
    iron_man.x -= iron_man.runspeed * dt * 10;
  }
  //console.log(iron_man.runspeed * dt);
}

function render() {
  var width = window.innerWidth;
  var height = window.innerHeight;
  //console.log(width/height);
  //console.log(700/500);
  if (width / height > 700 / 500) {
    $('canvas').css('height', height);
    $('canvas').css('width', height / 500 * 700);
  } else {
    $('canvas').css('width', width);
    $('canvas').css('height', width / 700 * 500);
  }


  context.fillStyle = "green";
  curr_life = new Image();
  curr_life.src = "Sprites/life_green.jpg";
  for (var i = 0; i < 1800; i++) { // HP
    if (i == lifes) {
      curr_life.src = "Sprites/life_red.jpg";
    }
    //context.drawImage(curr_life, 240, 268, i, 0, 1, 1);
    context.drawImage(curr_life, i, 0, 10, 10);
  }
  if (lifes != 0) {
    //lifes--;
  }
  context.drawImage(fon, 0, 0, 1000, 1000);
  context.drawImage(iron_man_img, 44 * (Math.round(iron_man.run) % 8) + 1.2, 0, 44, 65, iron_man.x, iron_man.y, 50, 60);
  //console.log(iron_man.run);
  //iron_man.x+=1; 
  //iron_man.x+=1; 
}
var requestAnimFrame = (function() {
  return window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    function(callback) {
      window.setTimeout(callback, 50);
    };
})();
#canvas {
  background-color: lightblue;
  margin: 0 auto;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  display: block;
  padding: 0;
}

body {
  overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div align="center" class="canvas-div">
  <canvas id="canvas" width="700" height="500" style="border: 1px solid black" class="canvas">
    Canvas is not working in your browser
  </canvas>
</div>
  • You might want to reduce your code to a [mcve]. – Haem Nov 05 '18 at 13:58
  • @Haem Sorry, but it is the least code I could make. All parts are needed. –  Nov 05 '18 at 14:00
  • Why can't you use reversed images? it's faster that way. https://stackoverflow.com/questions/8168217/html-canvas-how-to-draw-a-flipped-mirrored-image – arieljuod Nov 05 '18 at 14:20
  • @arieljuod The problem is that I tried to use it, and canvas is really lagging. Really lagging. –  Nov 05 '18 at 14:22
  • I don't see why it would lag, the left and right sprites should be all on the same image file, not a different image file, so walking left or right should have the same impact because it will just show one frame from the same image. – arieljuod Nov 05 '18 at 14:25
  • @arieljuod Well, the character stops for a few seconds, and then he appears somewhere in x+100px. –  Nov 05 '18 at 14:28
  • If you have all the frames on a single file (8 frames to walk left, 8 frames to walk right, you can even have 1 frame looking to the camera to animate a "flip" frame when changing direction), walking left or right would just mean select one position of the image or another with the drawImage method. Maybe you have to fix your drawImage parameters, but it should not produce any lag since it's just displaying another part of the image like you are already doing walking on one direction. I insist, it's the faster way to do that and it shouldn't produce any lag. – arieljuod Nov 05 '18 at 14:39
  • @arieljuod Well, it's just a beggining, it's not a finished game. –  Nov 05 '18 at 14:50

1 Answers1

1

Right, the best thing to do is a canvas scale, in order to make that work well have to make a few changes but I'll try and explain them to the best of my ability.

In order to keep note of orientation I added iron_man.z and used -1 for facing left and 1 for facing right, this is because that's how scaling works.

Next, in update() we need to set iron_man.z to either 1 or -1 depending on which key we press.

Now for the complex bit. We run context.save() to remember all of our settings before we play with translate and scale.

We have to translate to set the scale origin we want the origin to be the centre of iron man. To work out that we do iron_man.x + width/2 and iron_man.y + height/2 (context.translate(iron_man.x + 25, iron_man.y + 30)), this means ironman's position will need to be different too but we need to scale first.

For scale we just need iron_man.z so we have this context.scale(iron_man.z,1).

Finally we draw the image, now because we've set the origin as the centre of ironman we need to put the x and y coords at -(width/2), -(height/2).

And lastly, we want to restore the canvas with context.restore()

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var lifes = 700;

var fon = new Image();
fon.src = "https://i.stack.imgur.com/HjXpq.jpg";

var life_red = new Image();
life_red.src = "https://i.stack.imgur.com/sGZ7l.jpg";

var life_green = new Image();
life_green.src = "https://i.stack.imgur.com/9eWXX.jpg";

var iron_man_img = new Image(); // Player walking right
iron_man_img.src = 'https://i.stack.imgur.com/aeTtS.png';
var iron_man = {
  x: 300,
  y: 50,
  z: -1,
  dx: 100,
  dy: 0.1,
  dfly: 500,
  run: 0, //animation
  runspeed: 5, // animation speed
  fly: false,
  timeforflying: 0,
  alive: true
}
var keys = {};

function setKey(event, status) {
  var code = event.keyCode;
  var key;
  if (code == 32) {
    key = "Space";
    console.log(iron_man)
  } else if (code == 37) {
    key = "Left";
  } else if (code == 38) {
    key = "Up";
  } else if (code == 39) {
    key = "Right";
  } else if (code == 40) {
    key = "Down";
  } else {
    key = String.fromCharCode(code);
  }
  keys[key] = status;
}

document.addEventListener('keydown', function(e) {
  setKey(e, true);
});
document.addEventListener('keyup', function(e) {
  setKey(e, false);
});
document.addEventListener('blur', function() {
  keys = {};
});

function isDown(key) {
  return keys[key];
}
iron_man_img.onload = function() {
  last = Date.now();
  game();
}

function game() {

  var now = Date.now();
  var dt = (now - last) / 1000;
  update(dt);
  render();
  last = now;
  requestAnimFrame(game);
}

function update(dt) {
  if (isDown("Right") || isDown("D")) {
    iron_man.run += iron_man.runspeed * dt;
    iron_man.x += iron_man.runspeed * dt * 10;
    iron_man.z = 1;
  }
  if (isDown("Left") || isDown("A")) {
    iron_man.run += iron_man.runspeed * dt;
    iron_man.x -= iron_man.runspeed * dt * 10;
    iron_man.z = -1;
  }
  //console.log(iron_man.runspeed * dt);
}

function render() {
  var width = window.innerWidth;
  var height = window.innerHeight;
  //console.log(width/height);
  //console.log(700/500);
  if (width / height > 700 / 500) {
    $('canvas').css('height', height);
    $('canvas').css('width', height / 500 * 700);
  } else {
    $('canvas').css('width', width);
    $('canvas').css('height', width / 700 * 500);
  }


  context.fillStyle = "green";
  curr_life = new Image();
  curr_life.src = "Sprites/life_green.jpg";
  for (var i = 0; i < 1800; i++) { // HP
    if (i == lifes) {
      curr_life.src = "Sprites/life_red.jpg";
    }
    //context.drawImage(curr_life, 240, 268, i, 0, 1, 1);
    context.drawImage(curr_life, i, 0, 10, 10);
  }
  if (lifes != 0) {
    //lifes--;
  }
  context.drawImage(fon, 0, 0, 1000, 1000);
  context.save();
  context.translate(iron_man.x + 25, iron_man.y + 30);
  context.scale(iron_man.z, 1);
  context.drawImage(iron_man_img, 44 * (Math.round(iron_man.run) % 8) + 1.2, 0, 44, 65, -25, -30, 50, 60);
  context.restore();
  //console.log(iron_man.run);
  //iron_man.x+=1; 
  //iron_man.x+=1; 
}
var requestAnimFrame = (function() {
  return window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    function(callback) {
      window.setTimeout(callback, 50);
    };
})();
#canvas {
  background-color: lightblue;
  margin: 0 auto;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  display: block;
  padding: 0;
}

body {
  overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div align="center" class="canvas-div">
  <canvas id="canvas" width="700" height="500" style="border: 1px solid black" class="canvas">
    Canvas is not working in your browser
  </canvas>
</div>
Andrew Bone
  • 7,092
  • 2
  • 18
  • 33