I’m fairly new to HTML/CSS/JS programming and could use some help.
I am trying to reverse engineer a Pacman clone originally built with HTML5/CSS3/JQuery. I have been making headway in getting what I needed to get done: I’ve added a custom overlay, changed some graphics around, etc. The wall I keep hitting is replacing the Pacman character with a custom one. I’m able to add a static PNG file and use that, but I wanted it to be animated. So I learned how to create a spritesheet and animate it using requestAnimationFrame. I added it to the project, but I’m having trouble moving it dynamically using the javascript code.
Here is the code I originally had that replaces the original pacman character (which was created with a canvas arc method) with a static PNG image for each direction:
function drawPacman() {
var ctx = getPacmanCanevasContext();
ctx.beginPath();
if (PACMAN_DIRECTION === 1) {
img = document.getElementById("pacmanright");
ctx.drawImage(img, PACMAN_POSITION_X - (PACMAN_SIZE / 2), PACMAN_POSITION_Y - (PACMAN_SIZE / 2), PACMAN_SIZE, PACMAN_SIZE);
} else if (PACMAN_DIRECTION === 2) {
img = document.getElementById("pacmandown");
ctx.drawImage(img, PACMAN_POSITION_X - (PACMAN_SIZE / 2), PACMAN_POSITION_Y - (PACMAN_SIZE / 2), PACMAN_SIZE, PACMAN_SIZE);
} else if (PACMAN_DIRECTION === 3 ) {
img = document.getElementById("pacmanleft");
ctx.drawImage(img, PACMAN_POSITION_X - (PACMAN_SIZE / 2), PACMAN_POSITION_Y - (PACMAN_SIZE / 2), PACMAN_SIZE, PACMAN_SIZE);
} else {
img = document.getElementById("pacmanup");
ctx.drawImage(img, PACMAN_POSITION_X - (PACMAN_SIZE / 2), PACMAN_POSITION_Y - (PACMAN_SIZE / 2), PACMAN_SIZE, PACMAN_SIZE);
}
//ctx.arc(PACMAN_POSITION_X, PACMAN_POSITION_Y, PACMAN_SIZE, startAngle, endAngle, false);
//ctx.lineTo(lineToX, lineToY);
//ctx.fill();
ctx.closePath();
}
So I went about creating an spritesheet animation inside of a canvas element.
window.onload = function() {
var canvas = document.querySelector("#myCanvas");
var context = canvas.getContext("2d");
var myImage = new Image();
myImage.src = "https://i.ibb.co/NrJYyQj/spritesheet2-removebg-preview.png";
myImage.addEventListener("load", loadImage, false);
var shift = 0;
var frameWidth = 133;
var frameHeight = 114;
var totalFrames = 3;
var currentFrame = 0;
function loadImage(e) {
animate();
}
function animate() {
requestAnimationFrame(animate);
context.clearRect(0, 0, 133, 114);
context.drawImage(myImage, shift, 0, frameWidth, frameHeight, 0, 0, frameWidth, frameHeight);
shift += frameWidth + 1;
/*
Start at the beginning once you've reached the
end of your sprite!
*/
if (currentFrame == totalFrames) {
shift = 0;
currentFrame = 0;
}
currentFrame++;
}
}
I only got as far as making it appear in the game, but I can’t figure out how to move it dynamically in JS similar to the drawPacman function above. I made some attempts to no avail:
function positionCanvas(canvasId, x, y) {
const direction = document.getElementById(canvasId);
const ctx = canvas.getContext("2d")
direction.style.position = "absolute";
direction.style.left = x + "px";
direction.style.top = y + "px";
}
function drawPacman() {
var ctx = getPacmanCanevasContext();
ctx.beginPath();
if (PACMAN_DIRECTION === 1) {
right = document.getElementById("myCanvas");
positionCanvas(right, PACMAN_POSITION_X, PACMAN_POSITION_Y);
It doesn’t position the canvas element where I want it. Just stays at 0,0 unless I hard code a position in a CSS file.
I hope my explanation made enough sense. I can share more code if needed.
2
Answers
Your
positionCanvas()
function is expecting an id, but you are passing an element to it. So change your call to this:Ok, close to the goal, however by removing
drawPacman()
you remove the pacman’s ability to move.Notice how in each
if()
statement you callctx.drawImage()
.That is reupdating the position of the pacman, after the scene (or canvas) rewrites.
So in order to move the pacman, or custom sprite map, you’ll need to bind something to the movement of the sprite. Before this was the
<button>
s or<div>
s accessed bydocument.getElementById()
, now there is no binding.Unless you bound the coordinates into something like a key binding or mouse position, the pacman won’t move.
The
<button>
s or<div>
s are a good middle-ground for now.In regards, you don’t have state management over the coordinates of the pacman. So in order to bind, the coordinates need to be persisted in variables or some sort of data structure.
You’ll also need to refresh the
<canvas>
occasionally in order to prevent the pacman from tracing like those windows bugs and viruses…You may want to look into animation frames for the
<canvas>
api. Here’s some relevant code to the discussion: