0% found this document useful (0 votes)
76 views3 pages

JavaScript Canvas Game Movement

The document is a JavaScript code that implements a simple canvas-based game where a player can move in four directions and capture territory. The player's movement is controlled via keyboard arrows or touch gestures, and the game features territory filling and trail drawing mechanics. The code includes functions for drawing, updating the game state, and managing player territory using a grid system.

Uploaded by

1808veershah
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
76 views3 pages

JavaScript Canvas Game Movement

The document is a JavaScript code that implements a simple canvas-based game where a player can move in four directions and capture territory. The player's movement is controlled via keyboard arrows or touch gestures, and the game features territory filling and trail drawing mechanics. The code includes functions for drawing, updating the game state, and managing player territory using a grid system.

Uploaded by

1808veershah
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

const canvas = document.

getElementById("gameCanvas");
const ctx = [Link]("2d");
[Link] = [Link];
[Link] = [Link];

const gridSize = 20;


let cameraX = 0, cameraY = 0;
let direction = "";

function lightenColor(color) {
let hsl = [Link](/\d+/g);
return `hsl(${hsl[0]}, ${hsl[1]}%, ${[Link](90, parseInt(hsl[2]) + 10)}%)`;
}

let player = {
x: 0,
y: 0,
size: gridSize,
color: "hsl(" + [Link]() * 360 + ", 100%, 50%)",
trailColor: "",
trail: [],
territory: new Set()
};
[Link] = lightenColor([Link]);

function addToTerritory(x, y) {
[Link](`${x},${y}`);
}

// Initialize starting territory


for (let i = -1; i <= 1; i++) {
for (let j = -1; j <= 1; j++) {
addToTerritory(i * gridSize, j * gridSize);
}
}

function drawGridSquare(x, y, color) {


[Link] = color;
[Link](x - cameraX + [Link] / 2, y - cameraY + [Link] / 2,
gridSize, gridSize);
}

function drawPlayer() {
[Link] = [Link];
drawGridSquare(player.x, player.y, [Link]);
}

function drawTrail() {
[Link] = [Link];
[Link](pos => {
drawGridSquare(pos.x, pos.y, [Link]);
});
}

function fillTerritory() {
[Link](pos => {
let [x, y] = [Link](",").map(Number);
drawGridSquare(x, y, [Link]);
});
}

function isEnclosed() {
if ([Link] < 4) return false;
let first = [Link][0];
let last = [Link][[Link] - 1];
return [Link](`${last.x},${last.y}`);
}

function floodFill(x, y, color) {


let stack = [[x, y]];
let visited = new Set();
let toFill = [];

while ([Link] > 0) {


let [cx, cy] = [Link]();
let key = `${cx},${cy}`;

if ([Link](key) || [Link](key)) continue;


[Link](key);
[Link]([cx, cy]);

[[gridSize, 0], [-gridSize, 0], [0, gridSize], [0, -


gridSize]].forEach(([dx, dy]) => {
let nx = cx + dx;
let ny = cy + dy;
if (![Link](`${nx},${ny}`)) [Link]([nx, ny]);
});
}

[Link](([fx, fy]) => addToTerritory(fx, fy));


}

function captureTerritory() {
if (!isEnclosed()) return;
[Link](pos => addToTerritory(pos.x, pos.y));
let midX = [Link](([Link][0].x + [Link][[Link] -
1].x) / 2);
let midY = [Link](([Link][0].y + [Link][[Link] -
1].y) / 2);
floodFill(midX, midY, [Link]);
[Link] = [];
}

function update() {
let targetX = [Link](player.x / gridSize) * gridSize;
let targetY = [Link](player.y / gridSize) * gridSize;
if (direction === "up") targetY -= gridSize;
else if (direction === "down") targetY += gridSize;
else if (direction === "left") targetX -= gridSize;
else if (direction === "right") targetX += gridSize;

player.x += (targetX - player.x) * 0.1;


player.y += (targetY - player.y) * 0.1;

let newGridX = [Link](player.x / gridSize) * gridSize;


let newGridY = [Link](player.y / gridSize) * gridSize;

if (![Link](`${newGridX},${newGridY}`)) {
[Link]({ x: newGridX, y: newGridY });
}

captureTerritory();
cameraX = player.x;
cameraY = player.y;

[Link](0, 0, [Link], [Link]);


fillTerritory();
drawTrail();
drawPlayer();
requestAnimationFrame(update);
}

function movePlayer(newDirection) {
direction = newDirection;
}

[Link]("keydown", (e) => {


if ([Link] === "ArrowUp") movePlayer("up");
else if ([Link] === "ArrowDown") movePlayer("down");
else if ([Link] === "ArrowLeft") movePlayer("left");
else if ([Link] === "ArrowRight") movePlayer("right");
});

let startX, startY, endX, endY;


[Link]("touchstart", (event) => {
startX = [Link][0].clientX;
startY = [Link][0].clientY;
});

[Link]("touchend", (event) => {


endX = [Link][0].clientX;
endY = [Link][0].clientY;
let diffX = endX - startX;
let diffY = endY - startY;

if ([Link](diffX) > [Link](diffY)) {


if (diffX > 0) movePlayer("right");
else movePlayer("left");
} else {
if (diffY > 0) movePlayer("down");
else movePlayer("up");
}
});

requestAnimationFrame(update);

Common questions

Powered by AI

The game ensures that a player's trail area is not recaptured by using a 'Set' to maintain unique territory coordinates and by checking the 'isEnclosed' condition before territory conversion. If the trail is confirmed enclosed, only then is the path added to the territory, guaranteeing single capture instances of any path sequence, preventing redundant conversions and ensuring logical territory expansion .

Adjusting the canvas to match window dimensions ensures that the game scales dynamically to fit any display size, providing a full-screen experience. This responsiveness enhances visual continuity and user engagement by eliminating scrolling or resizing artifacts and ensures that game elements remain visible and accessible, adapting smoothly to different screens .

The code mitigates the impact of imprecise floating point arithmetic by snapping the player's position to the nearest grid square using rounding. Before updating the player's position, target coordinates are calculated by rounding the current position divided by 'gridSize' and then multiplying back by 'gridSize', ensuring alignment with the grid and preventing drift during movement .

Using requestAnimationFrame in the update loop provides benefits over setInterval by synchronizing rendering with the browser's refresh rate. This method results in smoother animations and optimizes performance by reducing unnecessary frame calculations, as updates pause when the tab is inactive, conserving system resources and improving game fluidity .

The function 'lightenColor' adjusts the player's trail color by slightly increasing the lightness of the HSL color representation. This is achieved by adding 10 to the current lightness value, ensuring it does not exceed 90%, which gives the trail a lighter appearance than the player's color, enhancing visual contrast .

The game interprets directional input from touch events by calculating the difference in the starting and ending positions of a swipe. If the swipe is more horizontal, it moves the player left or right based on the swipe direction; if more vertical, it moves the player up or down. This approach contrasts with arrow key controls, which directly map specific key presses to movement, offering different usability experiences between touch and keyboard interactions .

The use of HSL (Hue, Saturation, Lightness) color space benefits visual customization by allowing intuitive manipulation of color properties, such as lightness and saturation. This approach enables dynamic color adjustments like lightening the player's trail for better visibility, and generating unique player colors through random hues, enhancing aesthetic variety and improving user experience .

The 'floodFill' function expands the player's territory by starting from a given x and y coordinate and iterating through each adjacent square, checking if it has not been visited and is not part of the territory yet. The 'visited' set tracks the squares that have already been considered, preventing the algorithm from revisiting them, which helps in efficient territory marking. Unvisited squares are pushed to the stack for further exploration, enabling a comprehensive territory capture .

The 'captureTerritory' function checks if the player's trail encloses a loop by verifying that the trail's end overlaps with the existing territory and, if enclosed, it converts the trail into an extension of the territory. Subsequently, it uses the 'floodFill' function to complete the capture process, effectively transforming enclosed spaces into territory, enabling territorial expansion and strategic advantage .

The player's starting territory is initialized by adding squares in a 3x3 grid centered around the origin, which provides a base from which players can expand by laying trails. This setup prevents immediate setbacks from failure to enclose new territory at the game's start, offering players stability, allowing them to focus on learning movement mechanics and strategy building for future expansion .

You might also like