Canvas
My canvas piece was a variation of the character Isaac from The Binding of Isaac. The game has a very simple art style while still having distinct character designs, which is why I chose it. To create a variation on it, I included the evil eye symbol as part of the game involves becoming increasingly morphed and deformed. I created Isaac through using Adobe Dreamweaver to create a series of shapes (primarily circles, quadratic curves, and Bezier curves). In total, it took me about 8 hours to create from start to finish.
Given that it was my first exploration into working with Dreamweaver, I was really proud of how this turned out. It was pleasantly surprising how fun it was to manipulate code into something recognizable. It was daunting at first, but realizing that it was essentially just geometry reframed how I approached it into something a lot more manageable. I was particularly satisfied with how the eyes came out to create this mix of sad and eerie look (which is very tonally appropriate for the character). While there are some flaws, I think that overall the product came out well.
Sketch:
Isaac Inspiration:
Evil Eye Inspiration:
Code Used:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title> -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- </title>
<!-- import external .js scripts here -->
<!-- <script type="text/javascript" src="#" ></script> -->
<!-- modify CSS properties here -->
<style type="text/css">
body,td,th {
font-family: Monaco, "Courier New", "monospace";
font-size: 14px;
color: rgba(255,255,255,1);
}
body {
background-color: rgba(0,0,0,1);
}
#container {
position: relative;
text-align: left;
width: 95%;
height: 800px;
}
#fmxCanvas {
position: relative;
background-color:rgba(73,31,31,1.00);
border: rgba(255,255,255,0) thin dashed;
cursor: crosshair;
display: inline-block;
}
</style>
</head>
<body>
<div id="container">
<!-- START HTML CODE HERE -->
<canvas id="fmxCanvas" width="600" height="800"></canvas>
<div id="display"></div>
<!-- FINISH HTML CODE HERE -->
</div>
<script>
///////////////////////////////////////////////////////////////////////
// DECLARE requestAnimFrame
var rAF = window.requestAnimFrame ||
window.mozRequestAnimFrame ||
window.webkitRequestAnimFrame ||
window.msRequestAnimFrame;
var fps = 30;
window.requestAnimFrame = (
function(callback) {
return rAF ||
function(callback) {
window.setTimeout(callback, 1000 / fps);
};
})();
///////////////////////////////////////////////////////////////////////
// DEFINE GLOBAL VARIABLES HERE
var canvas;
var context;
canvas = document.getElementById("fmxCanvas");
context = canvas.getContext("2d");
var canvas1;
var context1;
canvas1 = document.createElement("canvas");
context1 = canvas1.getContext("2d");
canvas1.width = canvas.width;
canvas1.height = canvas.height;
var display;
display = document.getElementById('display');
var counter;
///////////////////////////////////////////////////////////////////////
// DEFINE YOUR GLOBAL VARIABLES HERE
///////////////////////////////////////////////////////////////////////
// CALL THE EVENT LISTENERS
window.addEventListener("load", setup, false);
//////////////////////////////////////////////////////////////////////
// ADD EVENT LISTENERS
canvas.addEventListener("mousemove", mousePos, false);
//////////////////////////////////////////////////////////////////////
// MOUSE COORDINATES
var stage, mouseX, mouseY;
function mousePos(event) {
stage = canvas.getBoundingClientRect();
mouseX = event.clientX - stage.left;
mouseY = event.clientY - stage.top;
}
/////////////////////////////////////////////////////////////////////
// INITIALIZE THE STARTING FUNCTION
function setup() {
/////////////////////////////////////////////////////////////////////
// DECLARE STARTING VALUES OF GLOBAL VARIABLES
counter = 0;
mouseX = canvas.width/2;
mouseY = canvas.height/2;
/////////////////////////////////////////////////////////////////////
// CALL SUBSEQUENT FUNCTIONS, as many as you need
clear(); // COVER TRANSPARENT CANVAS OR CLEAR CANVAS
draw(); // THIS IS WHERE EVERYTHING HAPPENS
}
////////////////////////////////////////////////////////////////////
// CLEAR THE CANVAS FOR ANIMATION
// USE THIS AREA TO MODIFY BKGD
function clear() {
context.clearRect(0,0,canvas.width, canvas.height);
context1.clearRect(0,0,canvas.width, canvas.height);
// clear additional contexts here if you have more than canvas1
}
////////////////////////////////////////////////////////////////////
// THIS IS WHERE EVERYTHING HAPPENS
function draw() {
counter += 0.1; // EASIER FOR SINE COSINE FUNCTIONS
if (counter > Math.PI*200) { counter = 0; } // RESET COUNTER
clear(); // USE THIS TO REFRESH THE FRAME AND CLEAR CANVAS
////////////////////////////////////////////////////////////////////
// >>>START HERE>>>START HERE>>>START HERE>>>START HERE>>>START HERE
//background
context.beginPath();
for (var i=150; i<canvas.height; i+=50) {
context.moveTo(0,i);
//context.lineTo(canvas.width,i);
//context.lineTo(canvas.width-i,i);
context.lineTo(i,canvas.height);
context.lineTo(canvas.width, canvas.height-i);
context.lineTo(canvas.width - i, 0);
context.lineTo(0,i+50);
context.lineWidth = 20;
context.strokeStyle = "rgba(95,15,172,.20)";
context.stroke();
}
context.closePath();
//Left Arm
context.beginPath();
context.moveTo(390, 429);
context.bezierCurveTo(515, 600, 525, 780, 400, 655);
context.fillStyle = 'rgba(235,196,183,1.00)';
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,1.00)";
context.lineCap = 'round'
context.stroke();
//Right Arm
context.beginPath();
context.moveTo(210, 429);
context.bezierCurveTo(85, 600, 75, 780, 200, 655);
context.fillStyle = 'rgba(235,196,183,1.00)';
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,1.00)";
context.lineCap = 'round'
context.stroke();
//body
context.beginPath();
context.moveTo(125, 800);
context.quadraticCurveTo(300, -200, 475, 800);
context.fillStyle = 'rgba(235,196,183,1.00)';
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgb(0,0,0)";
context.stroke();
//head
context.beginPath();
context.arc(300, 250, 200, 0, 2*Math.PI, false);
context.fillStyle = 'rgb(237,199,187)' ;
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,1.00)";
context.stroke();
//frown
context.beginPath();
context.arc(300, 400, 50, 0, Math.PI, true);
context.fillStyle = 'rgba(47,33,34,1.00)';
context.fill();
context.lineWidth = 2;
context.strokeStyle = "black";
context.stroke();
//frown - tongue
context.beginPath();
context.moveTo(250, 400);
context.quadraticCurveTo(300, 360, 350, 400);
context.fillStyle = 'rgba(227,157,175,1.00)';
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,1.00)";
context.stroke();
//frown - lower lip
context.beginPath();
context.moveTo(250, 400);
context.quadraticCurveTo(300, 375, 350, 400);
context.fillStyle = 'rgba(237,199,187,1.00)';
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,1.00)";
context.stroke();
//evil eye 1
context.beginPath();
context.arc(300, 145, 85, 0, 2*Math.PI, false);
context.fillStyle = 'rgba(21,8,127,1.00)' ;
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,00)";
context.stroke();
//evil eye 2
context.beginPath();
context.arc(300, 145, 50, 0, 2*Math.PI, false);
context.fillStyle = 'rgba(255,255,255,1.00)' ;
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,00)";
context.stroke();
//evil eye 3
context.beginPath();
context.arc(300, 145, 30, 0, 2*Math.PI, false);
context.fillStyle = 'rgba(152,208,249,1.00)' ;
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,00)";
context.stroke();
//evil eye 4
context.beginPath();
context.arc(300, 145, 10, 0, 2*Math.PI, false);
context.fillStyle = 'rgba(0,0,0,1.00)' ;
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,00)";
context.stroke();
//left tears
context.beginPath();
context.moveTo(200,360);
context.bezierCurveTo(230, 440, 170, 520, 200, 600);
context.bezierCurveTo(230, 680, 170, 760, 200, 840);
context.lineWidth = 50;
context.strokeStyle = "rgba(78,214,252,0.75)";
context.lineCap = 'round'
context.stroke();
//right tears
context.beginPath();
context.moveTo(400,360);
context.bezierCurveTo(370, 520, 430, 440, 400, 600);
context.bezierCurveTo(370, 760, 430, 680, 400, 840);
context.lineWidth = 50;
context.strokeStyle = "rgba(78,214,252,0.75)";
context.lineCap = 'round'
context.stroke();
//left eye
context.beginPath();
context.arc(200, 285, 75, 0, 2*Math.PI, false);
context.fillStyle = 'rgba(0,0,0,1.00)' ;
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,1.00)";
context.stroke();
//right eye
context.beginPath();
context.arc(400, 285, 75, 0, 2*Math.PI, false);
context.fillStyle = 'rgba(0,0,0,1.00)' ;
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,1.00)";
context.stroke();
//left pupil
context.beginPath();
context.arc(180, 260, 40, 0, 2*Math.PI, false);
context.fillStyle = 'rgba(255,255,255,1.00)' ;
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,00)";
context.stroke();
//right pupil
context.beginPath();
context.arc(380, 260, 40, 0, 2*Math.PI, false);
context.fillStyle = 'rgba(255,255,255,1.00)' ;
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,00)";
context.stroke();
//right eye shine
context.beginPath();
context.arc(440, 325, 15, 0, 2*Math.PI, false);
context.fillStyle = 'rgba(255,255,255,1.00)' ;
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,00)";
context.stroke();
//left eye shine
context.beginPath();
context.arc(235, 325, 15, 0, 2*Math.PI, false);
context.fillStyle = 'rgba(255,255,255,1.00)' ;
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,00)";
context.stroke();
//feet line
context.beginPath();
context.moveTo(125,800)
context.lineTo(475, 800);
context.lineWidth = 2; // STROKE WIDTH
context.strokeStyle = 'rgba(0,0,0,1.00)';
context.stroke(); // STROKE
//leg arc
context.beginPath();
context.moveTo(250, 800);
context.quadraticCurveTo(300, 600, 350, 800);
context.fillStyle = 'rgba(73,31,31,1.00)';
context.fill();
context.lineWidth = 2;
context.strokeStyle = "rgba(0,0,0,1.00)";
context.stroke();
// <<<END HERE<<<END HERE<<<END HERE<<<END HERE<<<END HERE<<<END HERE
///////////////////////////////////////////////////////////////////
// CREDITS
context.save();
var credits = "Sage Boutelle, Canvas, FMX 210, SP 2022";
context.font = 'bold 12px Helvetica';
context.fillStyle = "rgba(255,255,255,1.00)"; // change the color here
context.shadowColor = "rgba(0,0,0,1.00)"; // change shadow color here
context.shadowBlur = 12;
context.shadowOffsetX = 2;
context.shadowOffsetY = 2;
context.fillText(credits, 10, canvas.height - 10); // CHANGE THE LOCATION HERE
context.restore();
//////////////////////////////////////////////////////////////////
// HTML DISPLAY FIELD FOR TESTING PURPOSES
display.innerHTML = Math.round(mouseX) + " || " + Math.round(mouseY) + " || counter = " + Math.round(counter);
/////////////////////////////////////////////////////////////////
// LAST LINE CREATES THE ANIMATION
requestAnimFrame(draw); // CALLS draw() every nth of a second
}
</script>
</body>
</html>
Hi Sage,
ReplyDeleteThis is so well done. Not sure if you have worked in Dreamweaver before but this project makes it look like you have. One of my favorites from the class!