Reputation:
So - I am trying to create a game where you move the character across a grid. I have a main grid container div, then loads of separate divs within that container that form the grid (using grid layout css).
<div id="grid-container">
<div id='player'></div>
<div id='a'>
<h3>Start</h3>
</div>
<div id='b'></div>
<div id='c'></div>
<div id='d'></div>
<div id='e'></div>
<div id='f'></div>
<div id='g'></div>
<div id='h'></div>
<div id='i'></div>
<div id='j'></div>
<div id='k'></div>
<div id='l'></div>
<div id='m'></div>
<div id='n'></div>
<div id='o'>
<h3>Finish</h3>
</div>
</div>
I then have a div for my character which I have placed on the grid. I was originally moving the character around using positioning as such -
document.addEventListener('keyup', event => {
switch (event.keyCode){
case 37:
if (leftDistance > 0) {
player.style.left = --leftDistance + '%';
}
break;
case 38:
if (topDistance > 0) {
player.style.top = --topDistance + '%';
}
break;
I then wanted to create logic to say, 'when character is in such position, alert user with this and place character back to starting position'. I was told that this would be complicated to do with numbered positioning and that by using a grid, I am able to move the character from one div to another when the user presses arrow keys. I cannot seem to figure out the best way to go about this. I tried to name my divs with numbers so that when the character moves I can essentially add a number to their location id so they end up in the subsequent div but I seem to be unable to name my divs with numbers? Perhaps I am over complicating things but any insight would be helpful!
Upvotes: 1
Views: 1467
Reputation: 1305
First of all I'd suggest a complete overhaul. The game you've got there, naming all those id's is not scalable or practical. It violates the DRY principle (look it up).
Instead of having a div with an id
of player, just allow .grid-square
divs to take on the class of .contains-player
. This way, you won't be shuffling the layout around every time your player moves.
You'd want to have an array of all the divs, then use some logic like so to determine what should happen in the case of moving in a direction. This is what I would do, please adapt to your taste and needs.
window.onload = function() {
const gameHeight = 10;
const gameWidth = 10;
const container = document.getElementById("grid-container");
for(let i = 0; i < gameWidth * gameHeight; i++) {
container.innerHTML += `<div class="grid-square"></div>`;
}
const gridSquares = document.querySelectorAll(".grid-square");
gridSquares[0].classList.add("contains-player");
let playerX = 0,
playerY = 0;
function move(direction) {
const playerDiv = document.querySelector(".grid-square.contains-player");
playerDiv.classList.remove("contains-player");
let newPlayerDiv;
switch(direction) {
case "left": playerX--; break;
case "up": playerY--; break;
case "right": playerX++; break;
case "down": playerY++; break;
// ...
}
newPlayerDiv = gridSquares[(playerY * gameWidth) + playerX]
newPlayerDiv = gridSquares[(playerY * gameWidth) + playerX];
// Add some logic in here to make sure player isn't offscreen;
newPlayerDiv.classList.add("contains-player");
}
function toBeExecutedOnKeyDown(event) {
let direction;
switch(event.which) {
case 37: direction = "left"; break;
case 38: direction = "up"; break;
case 39: direction = "right"; break;
case 40: direction = "down"; break;
}
if(direction) {
event.preventDefault(); // Prevent screen from moving around
// More readable
move(direction);
}
}
window.onkeydown = toBeExecutedOnKeyDown;
}
:root {
--game-size: 10;
--game-scale: 10px;
--game-actual-size: calc(var(--game-size) * var(--game-scale));
}
#grid-container {
width: var(--game-actual-size);
height: var(--game-actual-size);
clear: both;
}
#grid-container .grid-square {
width: var(--game-scale);
height: var(--game-scale);
float: left;
background-color: grey;
}
.grid-square.contains-player {
background-color: red !important;
}
<!DOCTYPE html>
<html>
<head>
<title>Game</title>
<script src="./script.js"></script>
<link rel="stylesheet" href="./style.css"/>
</head>
<body>
<div id="grid-container">
<!--
This will be filled with divs like the following when the JS loads
<div class="grid-square"></div>
The div containing the player will look like this
<div class="grid-square contains-player"></div>
-->
</div>
</body>
</html>
Upvotes: 1