从勇者斗恶龙中汲取灵魂

时间:2016-04-25 22:27:30

标签: javascript canvas drawing

基本上我想绘制a slime from Dragon Quest(看起来像水滴)。我做了以下几点,但我想知道是否有更好的方法来做到这一点。也许使用贝塞尔曲线或类似的东西?

更新

我实际上看起来像我想要的一切,除了发光点的渐变(白色)

Slime.prototype.drawEye = function(x,y,w,h)
{

    ctx.save();
    ctx.lineWidth = 3;

    ctx.beginPath();
    var c = [];
    c.push("sclera");
    //c.push("iris");
    c.push("pupil");
    var wScale = [1,2.2,3];
    var hScale = [1,2,1.3];
    for (var i = 0; i < c.length; i++)
    {
        w /= wScale[i];
        h /= hScale[i];
        ctx.beginPath();
        ctx.ellipse(x,y,w,h,0,degreesToRadians(360),false);
        ctx.fillStyle = this.colors[c[i]];
        ctx.fill();
        ctx.stroke();
    }
    ctx.restore();

}
Slime.prototype.drawMouth = function()
{
    ctx.save();
    ctx.beginPath();

    var x = this.x+this.w/30;
    var y = this.y+this.h/8;
    var w = this.w;
    var h = this.h/8;
    var start = [x-w/3,y];
    var end = [x+w/8,y+h/5];

    // mouth
    bezierCurve(start,[x-w/3.3,y+h*2.3],[x+w/8,y+h*1.8],end);
    bezierCurveTo([x-w/10,y+h*0.6],[x-w/6,y+h*0.6],start);
    ctx.lineCap = "round";
    ctx.lineWidth = 8;
    ctx.stroke();
    ctx.clip();
    ctx.fillStyle = this.colors["mouth"];
    ctx.fill();

    start = [x-w/3.5,y+h*1];
    // tongue
    ctx.beginPath();
    bezierCurve(start,[x-w/5,y+h*2.5],[x+w/6.5,y+h*1.6],[x+w/9,y+h*0.75]);
    bezierCurveTo([x+w/10,y+h/4],[x-w/5,y],start);
    ctx.fillStyle = this.colors["tongue"];
    ctx.fill();
    //ctx.stroke();

    ctx.restore();
}
Slime.prototype.drawHealthBar = function()
{
    ctx.beginPath();
    ctx.rect(this.x-this.w,this.y+this.h/2+30,this.w*2*this.health/this.maxHealth,20);
    ctx.fillStyle = "#00ff00";
    ctx.fill();
    ctx.beginPath();
    ctx.rect(this.x-this.w+(this.w*2*this.health/this.maxHealth),this.y+this.h/2+30,(this.maxHealth-this.health)/this.maxHealth*this.w*2,20);
    ctx.fillStyle = "#ff0000";
    ctx.fill();
    ctx.beginPath();
    ctx.rect(this.x-this.w,this.y+this.h/2+30,this.w*2,20);
    ctx.strokeStyle = "#000000";
    ctx.stroke();
}
Slime.prototype.drawBody = function()
{
    ctx.save();
    ctx.fillStyle = this.colors["body"];
    ctx.beginPath();
    var x = this.x;
    var y = this.y+this.h*0.4;
    var w = this.w/2;
    var h = this.h;
    var left = [x-w*0.97,this.y+h/11];
    var bottom = [x,this.y+h*0.495];
    var right = [x+w*0.97,this.y+h/15];
    var top = [x+this.w/30,this.y-h/2+this.topOffset];
    bezierCurve(left,[x-w,y+h/10],[x-w/7,y+h/12],bottom);
    bezierCurveTo([x+w*0.8,y+h/10],[x+w*1.05,y-h/7],right);
    y = this.y - (y - this.y);
    bezierCurveTo([x+w*0.75,y+h/15],[x+w*0.2,y+h/4.5],top);
    bezierCurveTo([x-w*0.2,y+h/5],[x-w*0.8,y+h/10],left);
    ctx.lineWidth = 3;
    ctx.fill();
    ctx.strokeStyle = this.colors["bodyOutline"];
    ctx.stroke();
    ctx.clip();
    ctx.shadowColor = "#000033";
    ctx.shadowBlur = 40;
    ctx.shadowOffsetX = ctx.shadowBlur/4;
    ctx.shadowOffsetY = ctx.shadowOffsetX*-0.8;
    ctx.lineWidth = 4;
    for (var i = 0; i < 7; i++)
    {
        if (i%2==0)
        {
             ctx.shadowColor = "#000033";
        }
        else
        {
            ctx.shadowColor = "rgba(0,0,80,0.5)";
        }
        ctx.stroke();
    }
    ctx.restore();
}
Slime.prototype.drawGlow = function(x,y,r1,r2)
{
    ctx.save();
    var g = ctx.createRadialGradient(x,y,r1,x,y,r2);
    g.addColorStop(0.0,"#ffffff");
    g.addColorStop(1.0,this.colors["body"]);
    ctx.beginPath();
    ctx.arc(x,y,r2,0,degreesToRadians(360),false);
    ctx.fillStyle = g;
    ctx.fill();
    ctx.restore();
}
Slime.prototype.draw = function()
{
    ctx.lineWidth = 2;
    this.drawBody();
    this.drawMouth();
    var w = this.w/10;
    var h = this.h/10;
    var x = this.x;
    var y = this.y;
    this.drawEye(x-this.w/4.5,y-h/2.5,w,h);
    this.drawEye(this.x+this.w/13,y-h/10,w,h);
    this.drawGlow(this.x-this.w/2.5,this.y+this.h/12,this.w/50,this.w/16);
    this.drawGlow(this.x+this.w/2*0.7,this.y+this.h/10,this.w/50,this.w/16);
}

结束更新

Slime

1 个答案:

答案 0 :(得分:2)

是的,您可以使用4个立方贝塞尔曲线绘制液滴轮廓。

这是一个仅使用4条C-Bez曲线的概念验证:

enter image description here

为什么!为什么! 为什么! ..........我喜欢创造一个史莱姆男人吗?

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>