0
\$\begingroup\$

I am creating a game with HTML5 canvas for browser. I want to create animations with many shapes, which would be drawed with canvas, not from spritesheets.

The problem i face now is - to create formulas for so many shapes. I need them resizeable, also different width/height ratio. I was drawing chess pawn, but took 1 week to complete it right using arc's.

This is that pawn formula:

function pawn_shape(ctx, xx, yy, fill, stroke, grid_size) {
  var g = grid_size / 100;
  g *= 0.8;
  ctx.lineWidth = grid_size / 10;
  xx += g * 12;
  yy += g * 10;
  ctx.fillStyle = fill;
  ctx.strokeStyle = stroke;
  ctx.lineJoin = "miter";

  ctx.beginPath();

  var x = xx + 50 * g;
  var y = yy + 25 * g;
  var radius = 10 * g;
  var startAngle = 0.8 * Math.PI;
  var endAngle = 2.2 * Math.PI;

  ctx.arc(x, y, radius, startAngle, endAngle);

  x = xx + 55 * g;
  y = yy + 48 * g;
  radius = 15 * g;
  startAngle = 1.6 * Math.PI;
  endAngle = 2.4 * Math.PI;

  ctx.arc(x, y, radius, startAngle, endAngle);

  x = xx + 50 * g;
  y = yy + 97 * g;
  radius = 35 * g;
  startAngle = 1.7 * Math.PI;
  endAngle = 1.955 * Math.PI;

  ctx.arc(x, y, radius, startAngle, endAngle);

  x = xx + 30 * g;
  y = yy + 92 * g;

  ctx.lineTo(x, y);

  x = xx + 50 * g;
  y = yy + 98 * g;
  radius = 35 * g;
  startAngle = 3.055 * Math.PI;
  endAngle = 3.3 * Math.PI;

  ctx.arc(x, y, radius, startAngle, endAngle);


  x = xx + 45 * g;
  y = yy + 48 * g;
  radius = 15 * g;
  startAngle = 2.6 * Math.PI;
  endAngle = 3.4 * Math.PI;

  ctx.arc(x, y, radius, startAngle, endAngle);
  ctx.stroke();
  ctx.fill();
  ctx.closePath();
}

This is only 1 pawn. I need many more figures as configurable formulas. What would be the ways to get faster such formulas?

So far I am thinking about a new open source project, where people could draw shapes and these would be converted into such formulas. Or maybe even extract formulas from simple images, like programs do image to vector.

Another idea was to find out how does normal vectors work - what formulas they have. Maybe i could reuse and modify that? No idea, hoping to find answer here..

\$\endgroup\$
  • \$\begingroup\$ Have you tried bézier curves? They only need a couple of points and make the path round by default \$\endgroup\$ – Bálint May 15 '18 at 18:46
  • \$\begingroup\$ Yes, i have tried. I had the whole thing with bezier curves, but with arcs i had better results and easier with scale. \$\endgroup\$ – mansim May 16 '18 at 5:55
2
\$\begingroup\$

A number of vector drawing tools like Illustrator or Gimp will allow you to export to a format called SVG, or Scalable Vector Graphics.

This is a reasonably human-readable-ish XML specification for vector drawings, and many of the tags and primitives align closely with the drawing commands you use with a canvas.

So you could use the vector drawing tool as a WYSIWYG editor to make your shape, then export to SVG to get a list of drawing commands you can convert to code. Or you can render SVG directly in the browser, or draw the SVG into the canvas natively.

As an example, here's a quick rook I drafted up in Illustrator:

Rook drawn in graphics software

And here's the SVG description:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
<g>
    <polygon fill="#231F20" points="307.862,18.222 307.862,65.191 287.312,65.191 287.312,18.222 215.881,18.222 215.881,65.191 
        195.333,65.191 195.333,18.222 123.901,18.222 123.901,65.191 123.901,165 379.292,165 379.292,65.191 379.292,18.222   "/>
    <polygon fill="#231F20" points="342.601,388.099 164.998,388.099 197.61,165 313.102,165  "/>
    <rect x="128.304" y="388.099" fill="#231F20" width="255.392" height="64.582"/>
    <rect x="101.886" y="452.681" fill="#231F20" width="308.229" height="41.097"/>
    <circle fill="#231F20" cx="101.886" cy="473.23" r="20.548"/>
    <circle fill="#231F20" cx="410.115" cy="473.23" r="20.548"/>
    <circle fill="#231F20" cx="128.303" cy="408.648" r="20.548"/>
    <path fill="#231F20" d="M197.61,185.547c-11.349,0-20.547-9.201-20.547-20.547h20.547V185.547z"/>
    <path fill="#231F20" d="M333.649,165c0,11.347-9.199,20.547-20.548,20.547V165H333.649z"/>
    <circle fill="#231F20" cx="383.696" cy="408.648" r="20.547"/>
</g>
</svg>
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ hi. thanks for this descriptive answer. i trough about native vector on canvas but as i have so many objects, native vectors will drop down the performance. \$\endgroup\$ – mansim May 16 '18 at 4:23
  • \$\begingroup\$ i see that i gonna need to use regex to fetch the data for shapes and remake them canvas compatible. but thats really a easier way than all others i know. and to make them resizeable just create the form in a 300x300 pixel size area and divide all numbers by 300 and set the scale to any i need. sounds good. \$\endgroup\$ – mansim May 16 '18 at 4:27
  • \$\begingroup\$ i mean to use regex if i'd do a converter project. but probably i wont need that. i can create canvas formula for every figure hand-ish, that wouldnt take too much time. \$\endgroup\$ – mansim May 16 '18 at 4:30
  • \$\begingroup\$ Why do you suppose drawing the SVG using the built-in methods would have worse performance than running equivalent drawing commands one by one in JavaScript? \$\endgroup\$ – DMGregory May 16 '18 at 10:26

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.