Skip to content

Instantly share code, notes, and snippets.

@jcreighton

jcreighton/tamagotchi.js

Last active Mar 25, 2017
Embed
What would you like to do?
Tamagotchi Game
function Canvas() {
var options = {
width: 600,
height: 400,
backgroundColor: '#eeeeee'
}
// Create canvas
this.canvas = document.createElement('canvas');
this.canvas.className = 'tamagotchi-game';
this.canvas.style.backgroundColor = options.backgroundColor;
this.canvas.width = options.width;
this.canvas.height = options.height;
this.context = this.canvas.getContext('2d');
document.body.append(this.canvas);
this.x = this.canvas.width / 2;
this.y = this.canvas.height / 2;
this.startGame();
}
Canvas.prototype.startGame = function() {
this.egg = new Egg(this.context, this.x - 45, this.y + 45);
this.tamagotchi = new Tamagotchi(this.context, this.x, this.y);
this.egg.hatch()
.then(() => this.open())
.then(() => {
var image = this.toImage();
this.animate((x, y, boundaryX, boundaryY) => {
this.clear();
this.tamagotchi.update(x, y);
this.context.drawImage(image, 0, 0, 600, 400, 0, 0, 600, 400);
return x >= boundaryX && y <= boundaryY;
}, 260, 250, 1, -1, 280, 230)
.then(() => {
return this.animateX((x, y) => {
this.clear();
this.tamagotchi.update(x, y);
this.context.drawImage(image, 0, 0, 600, 400, 0, 0, 600, 400);
}, 280, 230, 1, 330);
})
.then(() => {
return this.animate((x, y, boundaryX, boundaryY) => {
this.clear();
this.tamagotchi.update(x, y);
this.context.drawImage(image, 0, 0, 600, 400, 0, 0, 600, 400);
return x >= boundaryX && y >= boundaryY;
}, 330, 230, 1, 1, 360, 280);
});
});
};
Canvas.prototype.draw = function() {
// Get tamagotchi draw state
// Get game draw state
};
Canvas.prototype.clear = function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
};
Canvas.prototype.toImage = function() {
var data = this.canvas.toDataURL('image/png');
var image = new Image();
image.src = data;
return image;
}
Canvas.prototype.open = function() {
var image = this.toImage();
var open = (topY, bottomY, topYBoundary, bottomYBoundary) => {
this.clear();
this.context.drawImage(image, 0, 0, 600, 210, 0, topY, 600, 210);
this.context.drawImage(image, 0, 210, 600, 210, 0, bottomY, 600, 210);
return topY <= topYBoundary && bottomY >= bottomYBoundary;
}
return this.animate(open, 0, 210, -1, 1, -26, 60);
};
Canvas.prototype.animateX = function(draw, x, y, changeXBy, boundaryX) {
var horizontal = (x, y, boundaryX, boundaryY) => {
draw(x, y);
return x === boundaryX;
};
return this.animate(horizontal, x, y, changeXBy, 0, boundaryX, y);
};
Canvas.prototype.animateY = function(draw, x, y, changeYBy, boundaryY) {
var horizontal = (x, y, boundaryX, boundaryY) => {
draw(x, y);
return y === boundaryY;
};
return this.animate(horizontal, x, y, 0, changeYBy, x, boundaryY);
};
Canvas.prototype.animate = function(draw, x, y, changeXBy, changeYBy, boundaryX, boundaryY) {
return new Promise((resolve, reject) => {
var animation = (x, y) => {
x = x + changeXBy;
y = y + changeYBy;
if (draw(x, y, boundaryX, boundaryY)) {
return resolve();
}
requestAnimationFrame(() => animation(x, y));
}
requestAnimationFrame(() => animation(x, y));
});
};
function Egg(context, x, y) {
this.egg = {
color: '#2ed6b2',
outlineColor: 'white',
spotsColor: '#e2ed6b',
hatchLineColor: '#eeeeee',
activeState: 'unhatched',
};
this.context = context;
this.x = x;
this.y = y;
this.update = this.update.bind(this);
}
Egg.prototype.update = function(x, y) {
this.x = x;
this.y = y;
};
Egg.prototype.hatch = function() {
this.drawUnhatched();
return this.drawCracking()
.then(() => this.drawShaking())
.then(() => {
this.context.setTransform(1, 0, 0, 1, 0, 0);
this.update();
this.drawHatched();
});
};
Egg.prototype.drawShell = function() {
this.context.beginPath();
this.context.moveTo(this.x, this.y);
// Bottom curve
this.context.quadraticCurveTo(this.x + 44, this.y + 46, this.x + 74, this.y - 10);
// Right curve
this.context.quadraticCurveTo(this.x + 86, this.y - 40, this.x + 68, this.y - 70);
// Top curve
this.context.quadraticCurveTo(this.x + 30, this.y - 120, this.x, this.y - 70);
// Left curve
this.context.quadraticCurveTo(this.x - 20, this.y - 40, this.x, this.y);
this.context.closePath();
this.context.lineWidth = 4;
this.context.strokeStyle = this.egg.outlineColor;
this.context.stroke();
this.context.fillStyle = this.egg.color;
this.context.fill();
};
Egg.prototype.drawSpots = function() {
this.context.beginPath();
this.context.arc(this.x + 32, this.y + 2, 12, 0, Math.PI * 2);
this.context.fillStyle = this.egg.spotsColor;
this.context.fill();
this.context.beginPath();
this.context.arc(this.x + 60, this.y - 30, 8, 0, Math.PI * 2);
this.context.fillStyle = this.egg.spotsColor;
this.context.fill();
this.context.beginPath();
this.context.arc(this.x + 16, this.y - 40, 8, 0, Math.PI * 2);
this.context.fillStyle = this.egg.spotsColor;
this.context.fill();
this.context.beginPath();
this.context.arc(this.x + 34, this.y - 70, 12, 0, Math.PI * 2);
this.context.fillStyle = this.egg.spotsColor;
this.context.fill();
};
Egg.prototype.drawHatchLines = function() {
this.context.beginPath();
this.context.moveTo(this.x - 14, this.y - 26);
this.context.lineTo(this.x + 18, this.y - 44);
this.context.lineTo(this.x + 33, this.y - 24);
this.context.lineTo(this.x + 48, this.y - 41);
this.context.lineTo(this.x + 72, this.y - 26);
this.context.lineTo(this.x + 82, this.y - 36);
this.context.lineWidth = 6;
this.context.strokeStyle = this.egg.hatchLineColor;
this.context.stroke();
};
Egg.prototype.drawUnhatched = function() {
this.drawShell();
this.drawSpots();
};
Egg.prototype.drawCracking = function() {
var points = [
[this.x - 14, this.y - 26],
[this.x + 18, this.y - 44],
[this.x + 33, this.y - 24],
[this.x + 48, this.y - 41],
[this.x + 72, this.y - 26],
[this.x + 82, this.y - 36]
];
return new Promise((resolve, reject) => {
var counter = 0;
this.context.beginPath();
this.context.moveTo(...points[0]);
var interval = setInterval(() => {
if (counter === (points.length - 1)) {
clearInterval(interval);
return resolve();
}
this.context.lineTo(...points[counter + 1]);
this.context.lineWidth = 6;
this.context.strokeStyle = this.egg.hatchLineColor;
this.context.stroke();
counter++;
}, 300);
});
};
Egg.prototype.rotate = function() {
var x = this.x;
var y = this.y;
return (deg, boundary) => {
return new Promise((resolve, reject) => {
var animation = () => {
this.context.save();
this.context.clearRect(0, 0, 600, 400);
this.context.translate(x, y);
this.context.rotate(deg * Math.PI / 180);
this.x = 0;
this.y = 0;
this.drawHatched();
this.context.restore();
if (deg < boundary) {
deg++;
} else if (deg > boundary) {
deg--;
} else if (deg === boundary) {
return resolve();
}
requestAnimationFrame(animation);
};
requestAnimationFrame(animation);
});
};
};
Egg.prototype.drawShaking = function() {
var rotate = this.rotate();
return rotate(-2, 4)
.then(() => rotate(4, -4))
.then(() => rotate(-4, 4))
.then(() => rotate(4, -2))
.then(() => rotate(-2, 2));
};
Egg.prototype.drawHatched = function() {
this.drawShell();
this.drawSpots();
this.drawHatchLines();
};
function Tamagotchi(context, x, y) {
this.tamagotchi = {
color: '#666666',
happyLevel: 0,
hungerLevel: 0,
activeState: '',
idleStates: ['Bounce', 'Stand', 'Jump'],
animationQueue: []
};
this.context = context;
this.x = x;
this.y = y;
this.update = this.update.bind(this);
};
Tamagotchi.prototype.update = function(x, y) {
this.x = x;
this.y = y;
this.draw();
};
Tamagotchi.prototype.getCoordinates = function() {
return {
x: this.x,
y: this.y
};
};
Tamagotchi.prototype.draw = function() {
this.drawBody();
this.drawEyes();
this.drawMouth();
};
Tamagotchi.prototype.drawBody = function() {
this.context.beginPath();
this.context.fillStyle = this.tamagotchi.color;
this.context.fillRect(this.x, this.y, 4, 4);
// Bottom row
for (var i = 6; i <= 36; i += 6) {
this.context.fillRect(this.x + i, this.y + 4, 4, 4);
}
this.context.fillRect(this.x + 42, this.y, 4, 4);
// Right row
for (var i = 6; i <= 30; i += 6) {
this.context.fillRect(this.x + 48, this.y - i, 4, 4);
}
this.context.fillRect(this.x + 42, this.y - 36, 4, 4);
// Top row
for (var i = 6; i <= 36; i += 6) {
this.context.fillRect(this.x + i, this.y - 42, 4, 4);
}
this.context.fillRect(this.x, this.y - 36, 4, 4);
// Left row
for (var i = 6; i <= 30; i += 6) {
this.context.fillRect(this.x - 6, this.y - i, 4, 4);
}
};
Tamagotchi.prototype.drawEyes = function() {
this.context.beginPath();
this.context.fillStyle = this.tamagotchi.color;
this.context.fillRect(this.x + 16, this.y - 26, 4, 4);
this.context.fillRect(this.x + 28, this.y - 26, 4, 4);
};
Tamagotchi.prototype.drawMouth = function() {
this.context.beginPath();
this.context.fillStyle = this.tamagotchi.color;
this.context.fillRect(this.x + 20, this.y - 12, 4, 4);
this.context.fillRect(this.x + 25, this.y - 12, 4, 4);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment