making 2048 game: referencing object names - javascript

Here I had a problem with my 2048 game that I am making in HTML and Javascript and I am having trouble again. This time, I am trying to make a for/in loop that can check to see if the squares to the left, right, top and bottom are filled. What I need is a way to refer to the numbers of the squares while still being able to refer to the properties of the objects. I am doing my best to explain what I am trying to do. I hope the comments in my code explain what each block does. Thank you for your help.
/*
Math.floor(Math.random()*(1-16+1)+1) <------
|
this code picks a random number between 1 and 16___|
switch ()
*/
//this function creates a method to create objects
function square(full, color, number) {
this.full = full;
this.color = color;
this.number = number;
}
//this block creates objects for each square
var sq1 = new square(true, "black", 2);
var sq2 = new square(false, "grey", 2);
var sq3 = new square(false, "grey", 2);
var sq4 = new square(false, "grey", 2);
var sq5 = new square(false, "grey", 2);
var sq6 = new square(false, "grey", 2);
var sq7 = new square(false, "grey", 2);
var sq8 = new square(false, "grey", 2);
var sq9 = new square(false, "grey", 2);
var sq10 = new square(false, "grey", 2);
var sq11 = new square(false, "grey", 2);
var sq12 = new square(false, "grey", 2);
var sq13 = new square(false, "grey", 2);
var sq14 = new square(false, "grey", 2);
var sq15 = new square(false, "grey", 2);
var sq16 = new square(false, "grey", 2);
//creates a board with the .full properties of the squares
board = [sq1.full, sq2.full, sq3.full, sq4.full, sq5.full, sq6.full, sq7.full, sq8.full, sq9.full, sq10.full, sq11.full, sq12.full, sq13.full, sq14.full, sq15.full, sq16.full];
//creates var sq_num to help check if items to left, up, right and down are full
var sq_num =
//this giant code block conducts all movement
function movement() {
document.addEventListener('keydown', function(event) {
/*for (sq_num in board)
{
if sq_num */
if (event.keyCode == 37) //left
{
if (sq4.full == true) {
sq4.color = sq1.color
sq4.color = "grey"
sq1.color = true
}
if (sq8.full == true) {
sq8.color = sq7.color
sq7.color = "black"
}
if (sq12.full == true) {
sq12.color = sq11.color
sq11.color = "black"
}
if (sq16.full == true) {
sq16.color = sq15.color
sq15.color = "black"
}
} else if (event.keyCode == 38) //up
{
sq13.color = sq9.color
sq9.color = "black"
sq14.color = sq10.color
sq10.color = "black"
sq15.color = sq11.color
sq11.color = "black"
sq16.color = sq12.color
sq12.color = "black"
} else if (event.keyCode == 39) //right
{
if (sq1.full == true) {
sq1.color = sq2.color
sq2.color = "black"
sp2.full = true
}
if (sq2.full == true) {
sq2.color = sq3.color
sq3.color = "black"
sq3.full = true
}
if (sq5.full == true) {
sq5.color = sq6.color
sq6.color = "black"
}
if (sq9.full == true) {
sq9.color = sq10.color
sq10.color = "black"
}
if (sq13.full = true) {
sq13.color = sq14.color
sq14.color = "black"
}
} else if (event.keyCode == 40) //down
{
sq1.color = sq5.color
sq5.color = "black"
sq2.color = sq6.color
sq6.color = "black"
sq3.color = sq7.color
sq7.color = "black"
sq4.color = sq8.color
sq8.color = "black"
}
})
};
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
//this function draws each square where it should be in the formation of a board.
function draw() {
ctx.clearRect(0, 0, c.width, c.height); // clear the canvas so the old rectangles are gone
// board
ctx.beginPath();
ctx.lineWidth = "2";
ctx.strokeStyle = "grey";
ctx.rect(5, 5, 610, 610);
ctx.stroke();
// sq1
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(10, 10, 150, 150);
ctx.stroke();
ctx.fillStyle = sq1.color;
ctx.fill();
//sq2
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(160, 10, 150, 150);
ctx.stroke();
ctx.fillStyle = sq2.color;
ctx.fill();
//sq3
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(310, 10, 150, 150);
ctx.stroke();
ctx.fillStyle = sq3.color;
ctx.fill();
//sq4
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(460, 10, 150, 150);
ctx.stroke();
ctx.fillStyle = sq4.color;
ctx.fill();
//sq5
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(10, 160, 150, 150);
ctx.stroke();
ctx.fillStyle = sq5.color;
ctx.fill();
//sq6
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(160, 160, 150, 150);
ctx.stroke();
ctx.fillStyle = sq6.color;
ctx.fill();
//sq7
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(310, 160, 150, 150);
ctx.stroke();
ctx.fillStyle = sq7.color;
ctx.fill();
//sq8
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(460, 160, 150, 150);
ctx.stroke();
ctx.fillStyle = sq8.color;
ctx.fill();
//sq9
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(10, 310, 150, 150);
ctx.stroke();
ctx.fillStyle = sq9.color;
ctx.fill();
//sq10
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(160, 310, 150, 150);
ctx.stroke();
ctx.fillStyle = sq10.color;
ctx.fill();
//sq11
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(310, 310, 150, 150);
ctx.stroke();
ctx.fillStyle = sq11.color;
ctx.fill();
//sq12
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(460, 310, 150, 150);
ctx.stroke();
ctx.fillStyle = sq12.color;
ctx.fill();
//sq13
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(10, 460, 150, 150);
ctx.stroke();
ctx.fillStyle = sq13.color;
ctx.fill();
//sq14
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(160, 460, 150, 150);
ctx.stroke();
ctx.fillStyle = sq14.color;
ctx.fill();
//sq15
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(310, 460, 150, 150);
ctx.stroke();
ctx.fillStyle = sq15.color;
ctx.fill();
//sq16
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(460, 460, 150, 150);
ctx.stroke();
ctx.fillStyle = sq16.color;
ctx.fill();
}
window.setInterval(draw, 100) // repeat game loop function forever, 10 times per second(that value is measured in ms)
body {
background-color: lightgrey;
}
<canvas id="myCanvas" width="620" height="620" style="border:1px solid #d3d3d"></canvas>

Related

Using a switch case statement state machine to draw shapes in javascript

I'm trying to modify some getElementById code I found on the internet to write a function that uses a switch/case statement so that I can draw different shapes using the same function. Basically, I want to create a tiny state machine for shape drawing commands. JavaScript is still new to me, so I'm probably missing something glaringly obvious. Cheers!
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Draw a circle</title>
<script src="draw_shapes.js"></script>
</head>
<body onload="draw01();">
<canvas id="circle" width="150" height="150"></canvas>
</body>
</html>
draw_shapes.js
function draw01() {
var canvas = document.getElementById('circle');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var X = canvas.width / 2;
var Y = canvas.height / 2;
var R = 45;
ctx.beginPath();
ctx.arc(X, Y, R, 0, 2 * Math.PI, false);
ctx.lineWidth = 3;
ctx.strokeStyle = '#000000';
ctx.stroke();
}
}
function draw02() {
const canvas = document.getElementById(canvas.id);
const ctx = canvas.getContext('2d');
switch (canvas.id) {
case "circle":
var X = canvas.width / 2;
var Y = canvas.height / 2;
var R = 45;
ctx.beginPath();
ctx.arc(X, Y, R, 0, 2 * Math.PI, false);
ctx.lineWidth = 3;
ctx.strokeStyle = '#000000';
ctx.stroke();
break;
}
}
Second iteration. Still not quite working right, but I've got the setup more as I was envisioning.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Draw a circle</title>
<script src="draw_shapes_02.js"></script>
</head>
<body onload="draw(CIRCLE);">
</body>
</html>
draw_shapes_02.js
//shape enumeration (an object with constant variables with immutable property values)
const shapes = {
CIRCLE: "circle",
RECTANGLE: "rectangle",
TRIANGLE: "triangle",
HOUSE: "house",
DEFAULT:"default",
}
Object.freeze(shapes);
// shape default setting and error
let shape = shapes.DEFAULT;
if (!shape) {
throw new Error("Shape is not defined");
}
// shape state machine
function draw(shapes) {
var canvas = document.getElementById("shape");
var ctx = canvas.getContext('2d');
switch ("shape") {
case shapes.CIRCLE:
ctx.beginPath();
ctx.fillStyle = "black";
ctx.arc(150, 60, 50, 0, 2 * Math.PI);
ctx.closePath();
ctx.fill();
break;
case shapes.RECTANGLE:
ctx.beginPath();
ctx.fillStyle = "green";
ctx.rect(100, 130, 100, 50);
ctx.fill();
ctx.closePath();
break;
case shapes.TRIANGLE:
ctx.beginPath();
ctx.fillStyle = "yellow";
ctx.moveTo(150, 200);
ctx.lineTo(200, 250);
ctx.lineTo(100, 250);
ctx.lineTo(150, 200);
ctx.fill();
ctx.closePath();
break;
case shapes.HOUSE:
ctx.lineWidth = 10;
ctx.strokeRect(75, 140, 150, 110);
ctx.fillRect(130, 190, 40, 60);
ctx.beginPath();
ctx.moveTo(50, 140);
ctx.lineTo(150, 60);
ctx.lineTo(250, 140);
ctx.closePath();
ctx.stroke();
break;
case shapes.DEFAULT:
break;
}
}
I have simplified a bit but you can complicate again as you wish :)
function draw(shape) {
var canvas = document.getElementById("CIRCLE");
var ctx = canvas.getContext('2d');
console.log(shape);
switch (shape) {
case "CIRCLE":
ctx.beginPath();
ctx.fillStyle = "black";
ctx.arc(150, 60, 50, 0, 2 * Math.PI);
ctx.closePath();
ctx.fill();
break;
case "RECTANGLE":
ctx.beginPath();
ctx.fillStyle = "green";
ctx.rect(100, 130, 100, 50);
ctx.fill();
ctx.closePath();
break;
case "TRIANGLE":
ctx.beginPath();
ctx.fillStyle = "yellow";
ctx.moveTo(150, 200);
ctx.lineTo(200, 250);
ctx.lineTo(100, 250);
ctx.lineTo(150, 200);
ctx.fill();
ctx.closePath();
break;
case "HOUSE":
ctx.lineWidth = 10;
ctx.strokeRect(75, 140, 150, 110);
ctx.fillRect(130, 190, 40, 60);
ctx.beginPath();
ctx.moveTo(50, 140);
ctx.lineTo(150, 60);
ctx.lineTo(250, 140);
ctx.closePath();
ctx.stroke();
break;
default:
ctx.fillStyle = "#FF0000";
ctx.fillRect(0,0,150,75);
break;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Draw a circle</title>
</head>
<body onload="draw('HOUSE');">
<canvas width="240" height="297" style="border:1px solid #d3d3d3;" id="CIRCLE"></canvas>
</body>
</html>

JS Array Canvas

I have this array:
var Test1 = [
{ex: 'ABC', exx: 1},
{ex: 'BCA', exx: 2},
{ex: 'CBA', exx: 2}
];
And I'm developing a bar graph using the Canvas element, and I would like to know if I could go fetch the values from my array to be displayed and, how to do it.
I don't see any problem, u can access the elements from Test1 very easily:
console.log("ex: "+Test1[0].ex+" exx: "+Test1[0].exx);
or in a loop
for(var i=0;i< Test1.length;i++)
console.log("ex: "+Test1[i].ex+" exx: "+Test1[i].exx);
A DOM is nothing more than your html page. When a web page is loaded, the browser creates a Document Object Model of the page. Meanwhile the Test1 is your object in js script. So, unfortunately, No. Your DOM is nothing more than a set of html tags such as head, body,etc. Of course, it is able to render the values of scripts into the page, but it cannot fetch them on its own.
This should gives you some part of ur solution
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
//horizontal axe
ctx.beginPath();
ctx.moveTo(50, 630);
ctx.lineTo(300, 630);
ctx.lineWidth = 2;
ctx.strokeStyle = "black";
ctx.stroke();
//Vertical axe
ctx.beginPath();
ctx.moveTo(50, 630);
ctx.lineTo(50, 430);
ctx.strokeStyle = "black";
ctx.stroke();
//30 in vertical
ctx.font = 'bold small-caps sans-serif';
ctx.fillStyle = 'BLACK';
ctx.fillText('30.000', 2, 485);
ctx.beginPath();
ctx.moveTo(50, 480);
ctx.lineTo(40, 480);
ctx.lineWidth = 2;
ctx.strokeStyle = "black";
ctx.stroke();
//20 in vertical
ctx.fillText('20.000', 2, 535);
ctx.beginPath();
ctx.moveTo(50, 530);
ctx.lineTo(40, 530);
ctx.lineWidth = 2;
ctx.strokeStyle = "black";
ctx.stroke();
//10 in vertical
ctx.font = 'bold small-caps sans-serif';
ctx.fillStyle = 'BLACK';
ctx.fillText('10.000', 2, 585);
ctx.beginPath();
ctx.moveTo(50, 580);
ctx.lineTo(40, 580);
ctx.lineWidth = 2;
ctx.strokeStyle = "black";
ctx.stroke();
var Test1 = [
{ex: 'ABC', exx: 1},
{ex: 'BCA', exx: 2},
{ex: 'CBA', exx: 2}
];
///*
for(var i=0;i< Test1.length;i++){
// console.log("ex: "+Test1[i].ex+" exx: "+Test1[i].exx);
ctx.font = 'bold small-caps sans-serif';
ctx.fillStyle = 'BLACK';
ctx.fillText(Test1[i].ex,100+ i*135, 660);
ctx.beginPath();
ctx.moveTo(i*100, 630);
ctx.lineTo(i*100, 640);
ctx.strokeStyle = "black";
ctx.stroke();
ctx.beginPath();
ctx.rect(100+i*100, 400, 100, Test1[i].exx*100);
ctx.fillStyle = '#5b5b5b';
ctx.fill();
ctx.lineWidth = 1;
ctx.strokeStyle = 'black';
ctx.stroke();
}
<canvas id="canvas" width="750" height="700"></canvas>

how to implement print function in html5

I am trying to implement print function based on the layout I created below.
<html>
<canvas id="gameCanvas" width="800" height="600"></canvas>
<script>
function draw_bordered_rect(context, x, y, w, h) {
var colors = ['grey','red','black','green','orange','purple','yellow'];
context.rect(x, y, w, h);
context.fillStyle = "green";
context.fill();
context.lineWidth = 3;
context.strokeStyle = "lightblue";
context.stroke();
canvasContext.font = '25pt Arial';
canvasContext.textAlign = 'center';
canvasContext.fillStyle = colors[x];
//canvasContext.fillStyle = "black";
canvasContext.fillText('ACTIVITY 1',canvas.width/2-2, 56);
}
window.onload = function() {
canvas = document.getElementById('gameCanvas');
canvasContext = canvas.getContext('2d');
canvasContext.fillStyle = 'white';
canvasContext.fillRect(0, 0, canvas.width, canvas.height);
base_image = new Image();
base_image.src = 'http://jacobian.xyz/draw/pic1.png';
base_image.onload = function(){
canvasContext.drawImage(base_image, 250, 80);
}
bases_image = new Image();
bases_image.src = 'http://jacobian.xyz/draw/e.png';
bases_image.onload = function(){
canvasContext.drawImage(bases_image, 20, 400);
}
bases1_image = new Image();
bases1_image.src = 'http://jacobian.xyz/draw/f.png';
bases1_image.onload = function(){
canvasContext.drawImage(bases1_image, 250, 550);
}
bases2_image = new Image();
bases2_image.src = 'http://jacobian.xyz/draw/g.png';
bases2_image.onload = function(){
canvasContext.drawImage(bases2_image, 450, 545);
}
bases3_image = new Image();
bases3_image.src = 'http://jacobian.xyz/draw/h.png';
bases3_image.onload = function(){
canvasContext.drawImage(bases3_image, 350, 545);
}
draw_bordered_rect(canvasContext, 0, 0, 790, 70);
draw_bordered_rect(canvasContext, 0, 540, 790, 70);
canvasContext.fillStyle = 'grey';
canvasContext.fillRect(20, 150, 40, 40);
canvasContext.fillStyle = 'orange';
canvasContext.fillRect(20, 200, 40, 40);
canvasContext.fillStyle = 'purple';
canvasContext.fillRect(20, 250, 40, 40);
canvasContext.fillStyle = 'magenta';
canvasContext.fillRect(20, 300, 40, 40);
canvasContext.fillStyle = 'red';
canvasContext.fillRect(70, 150, 40, 40);
canvasContext.fillStyle = 'green';
canvasContext.fillRect(70, 200, 40, 40);
canvasContext.fillStyle = 'blue';
canvasContext.fillRect(70, 250, 40, 40);
canvasContext.fillStyle = 'yellow';
canvasContext.fillRect(70, 250, 40, 40);
canvasContext.fillStyle = 'black';
canvasContext.fillRect(70, 300, 40, 40);
}
</script>
</html>
so that when they click on the print button in the picture then the print dialog would come up.
I think the print function is like this.
function printPage()
{
window.print();
}
any help would be appreciated though.
Just make the buttons not part of the canvas. Have them part of normal html <a> or <button> tags that you styled.
Then add the the print function to an onclick event on those buttons/links.
That way you can also hide them in your CSS from printing. So they won't show up on the printed end result.

How can I stop filling my circle at some point?

How can I stop filling my circle at some point?
Like only fill 50% of the circle or 25% of the circle and leave the left over. Just like progress bar.
below is the code Im using but it is filling entire circle.
Kindly please give me suggestions.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
ctx.lineCap = "round";
var y = ch - 10;
var drawingColor = "#0092f9";
animate();
function animate() {
if (y > 0) {
requestAnimationFrame(animate);
}
ctx.clearRect(0, 0, cw, ch);
ctx.save();
drawContainer(0, null, null);
drawContainer(15, drawingColor, null);
drawContainer(7, "white", "white");
ctx.save();
ctx.clip();
drawLiquid();
ctx.restore();
ctx.restore();
y--;
}
function drawLiquid() {
ctx.beginPath();
ctx.moveTo(0, y);
for (var x = 0; x < 300; x += 1) {
ctx.quadraticCurveTo(x + 5, y+5, x + 5, y);
}
ctx.lineTo(cw, ch);
ctx.lineTo(0, ch);
ctx.closePath();
ctx.fillStyle = drawingColor;
ctx.fill();
}
function drawContainer(linewidth, strokestyle, fillstyle) {
ctx.beginPath();
ctx.arc(cw/2, ch/2,cw/2-30,0,2*Math.PI);
ctx.lineWidth = linewidth;
ctx.strokeStyle = strokestyle;
ctx.stroke();
if (fillstyle) {
ctx.fillStyle = fillstyle;
ctx.fill();
}
}
<canvas id="canvas" width=200 height=200></canvas>
I know zit at javascript but: Just change the limit of y in animate. I put 100 instead of 0 and it fills half the circle.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
ctx.lineCap = "round";
var y = ch - 10;
var drawingColor = "#0092f9";
animate();
function animate() {
if (y > 100) {
requestAnimationFrame(animate);
}
ctx.clearRect(0, 0, cw, ch);
ctx.save();
drawContainer(0, null, null);
drawContainer(15, drawingColor, null);
drawContainer(7, "white", "white");
ctx.save();
ctx.clip();
drawLiquid();
ctx.restore();
ctx.restore();
y--;
}
function drawLiquid() {
ctx.beginPath();
ctx.moveTo(0, y);
for (var x = 0; x < 300; x += 1) {
ctx.quadraticCurveTo(x + 5, y+5, x + 5, y);
}
ctx.lineTo(cw, ch);
ctx.lineTo(0, ch);
ctx.closePath();
ctx.fillStyle = drawingColor;
ctx.fill();
}
function drawContainer(linewidth, strokestyle, fillstyle) {
ctx.beginPath();
ctx.arc(cw/2, ch/2,cw/2-30,0,2*Math.PI);
ctx.lineWidth = linewidth;
ctx.strokeStyle = strokestyle;
ctx.stroke();
if (fillstyle) {
ctx.fillStyle = fillstyle;
ctx.fill();
}
}
<canvas id="canvas" width=200 height=200></canvas>

Drawing a slime from Dragon Quest

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?
Update:
I actually got everything to look like how I want it, except for the gradient for the glow spots (white)
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);
}
End update
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:
Why! Why! Why! .......... Did I enjoy creating a Slime Man??
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>

Categories