I'm working on creating a pixel-based light in the dark simulation with JavaScript to improve my coding skills. The goal is to create a bubble of light around the cursor as it moves. I'm only rendering a small portion around the cursor to ensure real-time results. I tried to create this code as scalable and friendly as possible, as even the light of the cursor and resolution of the pixels and be customized. Here is my code:
var Canvas = {
Element: document.createElement("canvas"),
Width: 500,
Height: 500,
Style: "border: 1px solid black;",
Resolution: 10,
Matrix: [],
Context: null,
};
var Light = {
Intensity: 20,
};
document.body.appendChild(Canvas.Element);
Canvas.Element.style = Canvas.Style;
Canvas.Element.width = Canvas.Width;
Canvas.Element.height = Canvas.Height;
Canvas.Matrix = new Array(Canvas.Height / Canvas.Resolution).fill().map(() =>
new Array(Canvas.Width / Canvas.Resolution).fill({
Intensity: 0,
})
);
console.log(Canvas.Matrix);
Canvas.Context = Canvas.Element.getContext("2d");
Canvas.Element.addEventListener("mousemove", function (event) {
var Rect = Canvas.Element.getBoundingClientRect();
var Mouse = {
X: event.clientX - Rect.left,
Y: event.clientY - Rect.top,
};
Canvas.Context.fillRect(0, 0, Canvas.Width, Canvas.Height);
Canvas.Context.clearRect(
Mouse.X - (Light.Intensity / 2) * Canvas.Resolution,
Mouse.Y - (Light.Intensity / 2) * Canvas.Resolution,
Light.Intensity * Canvas.Resolution,
Light.Intensity * Canvas.Resolution
);
for (
var x = Mouse.X / Canvas.Resolution - Light.Intensity / 2;
x < Mouse.X / Canvas.Resolution + Light.Intensity / 2;
x++
) {
for (
var y = Mouse.Y / Canvas.Resolution - Light.Intensity / 2;
y < Mouse.Y / Canvas.Resolution + Light.Intensity / 2;
y++
) {
if (x || y <= 0) {
CellDistance = Math.sqrt(
Math.pow(Mouse.X - Light.Intensity / 2, 2) +
Math.pow(Mouse.X - Light.Intensity / 2, 2)
);
Canvas.Matrix[x][y].Intensity = CellDistance;
}
}
}
});
As you can see, I receive the following error:
Uncaught TypeError: Cannot read properties of
undefined
I'm sure I've lost brain cells looking through this code as I'm positive I've defined Canvas.Matrix. I'm fairly new to coding a this is probably a stupid mistake. Any help is helpful. Thank you!
You are trying to access elements in your .Matrix that are outside it's 0 to 49 boundaries. This caused by your if() statement. You need to change it to ensure that your x and y values are between 0 to 49 before you use them to index into your .Matrix.
There is also the need for Math.floor() around your x and y's as already pointed out by @egorgrushin.
I suggest you take a closer look at your x, y values in your for() statements, to see if you are really getting what you expect. Since depending on where your mouse is, you are getting a lot of negative values, which can't use to index your matrix.
See the snippet for edited if() statement.
var Canvas = {
Element: document.createElement("canvas"),
Width: 500,
Height: 500,
Style: "border: 1px solid black;",
Resolution: 10,
Matrix: [],
Context: null,
};
var Light = {
Intensity: 20
}
document.body.appendChild(Canvas.Element);
Canvas.Element.style = Canvas.Style;
Canvas.Element.width = Canvas.Width;
Canvas.Element.height = Canvas.Height;
Canvas.Matrix = new Array(Canvas.Height / Canvas.Resolution).fill().map(() => new Array(Canvas.Width / Canvas.Resolution).fill({Intensity: 0}));
// console.log(Canvas.Matrix);
Canvas.Context = Canvas.Element.getContext("2d");
Canvas.Element.addEventListener('mousemove', function(event){
var Rect = Canvas.Element.getBoundingClientRect();
var Mouse = {
X: event.clientX - Rect.left,
Y: event.clientY - Rect.top,
}
Canvas.Context.fillRect(0, 0, Canvas.Width, Canvas.Height);
Canvas.Context.clearRect(Mouse.X - (Light.Intensity / 2) * Canvas.Resolution, Mouse.Y - (Light.Intensity / 2) * Canvas.Resolution, Light.Intensity * Canvas.Resolution, Light.Intensity * Canvas.Resolution)
for(var x = Mouse.X / Canvas.Resolution - (Light.Intensity / 2); x < Mouse.X / Canvas.Resolution + (Light.Intensity / 2); x++){
for(var y = Mouse.Y / Canvas.Resolution - (Light.Intensity / 2); y < Mouse.Y / Canvas.Resolution + (Light.Intensity / 2); y++){
// EDIT This if() is letting you try to access your Matrix bounds
// if(x || y <= 0){
if( x >= 0 && x < Canvas.Matrix.length && y >= 0 && y < Canvas.Matrix[0].length ){
CellDistance = Math.sqrt(Math.pow(Mouse.X - (Light.Intensity / 2), 2) + Math.pow(Mouse.X - (Light.Intensity / 2), 2));
// EDIT Deal with fractional x and y values
// Canvas.Matrix[x][y].Intensity = CellDistance
Canvas.Matrix[Math.floor(x)][Math.floor(y)].Intensity = CellDistance
}
}
}
});
<html>
</html>