Tyler Dalton Tyler Dalton - 7 months ago 19
Javascript Question

Drawing a slime from Dragon Quest with JavaScript and HTML canvas

Basically I want to draw a slime from Dragon Quest (it looks like a water drop). I have done the following, but I'd like to know if there is a better way to do it. Maybe using bezier curves or something like that?

enter image description here

context.beginPath();

context.ellipse(
this.x,
this.y,
this.w,
this.h / 2,
0,
degreesToRadians(-135),
degreesToRadians(-45), true
);

context.fill();

context.stroke();

context.beginPath();

context.moveTo(this.x, this.y - this.h * 0.35);

context.ellipse(
this.x + this.w * 0.7,
this.y - this.h * 2 / 3,
this.w * 0.7,
this.h * 0.31,
0,
degreesToRadians(180),
degreesToRadians(89),
true
);

context.ellipse(
this.x - this.w * 0.7,
this.y - this.h * 2 / 3,
this.w * 0.7,
this.h * 0.31,
0,
degreesToRadians(91),
degreesToRadians(0),
true
);

context.closePath();

context.fill();

context.stroke();

context.beginPath();

context.lineWidth += 2;

context.moveTo(this.x, this.y - this.h * 0.54);

context.lineTo(this.x, this.y - this.h * 0.35);

context.moveTo(this.x - this.w * 0.7, this.y - this.h * 0.35);

context.lineTo(this.x + this.w * 0.7, this.y - this.h * 0.35);

context.strokeStyle = this.colors["body"];

context.stroke();

context.strokeStyle = "#000000";

context.lineWidth = 5;

Answer

Yes, you can draw the droplet outline using just 4 cubic Bezier curves.

Here's a proof-of-concept using just 4 C-Bez curves:

enter image description here

Why! Why! Why! .......... Did I enjoy creating a Slime Man??

enter image description here

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

drawDropletMan(20,20,'rgb(63,187,255)');
drawDropletMan(255,55,'rgb(255,180,155)');

function drawDropletMan(x,y,fill){
    ctx.translate(x,y);
    drawBody(fill);
    circularGlow(158,111,3,18,fill);
    circularGlow(32,107,3,18,fill);
    eye(65,87,17,10);
    eye(120,90,17,10);
    mouth(33,130);
    ctx.translate(-x,-y);
}
//
function drawBody(fillcolor){
    ctx.save();
    ctx.beginPath();
    ctx.moveTo(109,0);
    ctx.bezierCurveTo(111,64,199,35,198,123);
    ctx.bezierCurveTo(199,139,183,192,99,190);
    ctx.bezierCurveTo(66,193,-4,167,1,110);
    ctx.bezierCurveTo(9,47,97,45,109,1);
    ctx.fillStyle=fillcolor;
    ctx.fill();
    ctx.strokeStyle='black';
    ctx.lineWidth=2;
    ctx.stroke();
    ctx.clip();
    ctx.shadowColor='black';
    ctx.shadowBlur=15;
    ctx.lineWidth=1;
    for(var i=0;i<8;i++){ctx.stroke();}
    ctx.restore();
}
//
function circularGlow(x,y,r1,r2,fillcolor){
    var g=ctx.createRadialGradient(x,y,r1,x,y,r2);
    g.addColorStop(0.00,'white');
    g.addColorStop(1.00,fillcolor);
    ctx.beginPath();
    ctx.arc(x,y,r2,0,Math.PI*2);
    ctx.fillStyle=g;
    ctx.fill();
}
//
function eye(x,y,r1,r2){
    ctx.beginPath();
    ctx.arc(x,y,r1,0,Math.PI*2);
    ctx.fillStyle='white';
    ctx.strokeStyle='black';
    ctx.fill();
    ctx.lineWidth=2;
    ctx.stroke();
    //
    ctx.beginPath();
    ctx.arc(x,y,r2,0,Math.PI*2);
    ctx.fillStyle='black';
    ctx.fill();
}
//
function mouth(){
    ctx.save();
    ctx.translate(5,5);
    ctx.beginPath();
    ctx.moveTo(44,120);
    ctx.bezierCurveTo(56,136,112,132,128,123);
    ctx.bezierCurveTo(138,123,143,123,132,138);
    ctx.bezierCurveTo(113,165,49,169,39,127);
    ctx.bezierCurveTo(41,128,32,122,44,120);
    ctx.closePath();
    ctx.fillStyle='black';
    ctx.fill();
    ctx.clip();
    ctx.beginPath();
    ctx.arc(90,200,56,0,Math.PI*2);
    ctx.fillStyle='coral';
    ctx.fill();
    ctx.restore();
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=500 height=300></canvas>