I am trying to do a tetris game for a task in an apprentice ship we were provided with the html background and so on but the logic we have to write ourselfes in js i choose to do a class based approach by coding the shapes as a class and the blocks that they are made out of as a class aswell the gameboard which i call gameLogicState is a 10 by 20 array in which i move the blocks my error is that when the shape spawns in only the lower half is created and i have no idea why
I was guessing the function which translates the shapes into the block class is broken but it seems to work fine i am going to paste the important code here when i move the cube to the left it displays the cube very briefly before it is just a two block line when i move it to the right it only displays the upper right and lower right block of the cube very briefly
const horizontalCells = 10;
let grid = generateGridArray();
function colorCell(cell, color) {
cell.style.background = color;
}
function generateGridArray() {
let cells = document.querySelectorAll('.cell');
let grid = [];
for (let i = 0; i < cells.length; i++) {
let cell = cells[i];
let x = (i % horizontalCells);
let y = Math.floor(i / horizontalCells);
// Wenn noch kein Array in grid[x] initialisiert wurde, tun wir das.
if (!grid[x]) {
grid[x] = [];
}
grid[x][y] = cell;
}
return grid;
}
document.addEventListener("keydown", function (event) {
let joystick = document.querySelector('.joystick');
if (event.code === "ArrowLeft") {
joystick.classList.remove('right');
joystick.classList.add('left');
} else if (event.code === "ArrowRight") {
joystick.classList.remove('left');
joystick.classList.add('right');
}
// Weitere Tasten-Abfragen hier einfügen...
});
document.addEventListener("keyup", function (event) {
let joystick = document.querySelector('.joystick');
if (event.code === "ArrowLeft") {
joystick.classList.remove('left');
} else if (event.code === "ArrowRight") {
joystick.classList.remove('right');
}
// Weitere Tasten-Abfragen hier einfügen...
});
function gravity(currentItem, gameLogicState) {
let gameData = currentItem.move(gameLogicState, 'down')
return gameData;
}
function generateArrayForTheGame() {
gameBoard = [];
for (let i = 0; i < 10; i++) {
const row = [];
for (let j = 0; j < 20; j++) {
row.push(null);
}
gameBoard.push(row);
}
return gameBoard;
}
const tetrinoShapes = {
'Line': [
[1, 1, 1, 1],
[0, 0, 0, 0]
],
'L': [
[1, 0, 0, 0],
[1, 1, 1, 0]
],
'Cube': [
[1, 1, 0, 0],
[1, 1, 0, 0]
],
'T': [
[0, 1, 0, 0],
[1, 1, 1, 0]
],
'Z': [
[1, 1, 0, 0],
[0, 1, 1, 0]
],
}
class shape {
constructor(spawnPoint, shapeForm) {
//todo tetrino hsapes const setzen
let form = tetrinoShapes[shapeForm];
this.blocks = [];
this.spawnPoint = spawnPoint
let position = this.spawnPoint
this.shapeName = shapeForm
// Translate the shape into a list of blocks
//todo vertical and horizontal are switched
for (let vertical = 0; vertical < form.length; vertical++) {
for (let horizontal = 0; horizontal < form[vertical].length; horizontal++) {
if (form[vertical][horizontal] === 1) {
const blockPosition = [spawnPoint[0] + horizontal, spawnPoint[1] + vertical];
console.log(`Erstelle Block an Position ${blockPosition}`);
this.blocks.push(new block(blockPosition, this));
}
}
}
}
move(gameLogicState, direction) {
for (let block = 0; block < this.blocks.length; block++) {
let location = this.blocks[block].location
let selectedBlock = this.blocks[block]
let x = location[0]
let y = location [1]
switch (direction) {
case 'left':
//if (this.blocks[block].collisionCheck(gameLogicState, 'left') === false) {
gameLogicState[x][y] = null
x -= 1
gameLogicState[x][y] = selectedBlock
selectedBlock.location[1] = y
selectedBlock.location[0] = x
//}
break;
case 'right':
//if (this.blocks[block].collisionCheck(gameLogicState, 'right') === false) {
gameLogicState[x][y] = null
x += 1
gameLogicState[x][y] = selectedBlock
selectedBlock.location[1] = y
selectedBlock.location[0] = x
//}
break;
case 'down':
gameLogicState[x][y] = null
y += 1
gameLogicState[x][y] = selectedBlock
selectedBlock.location[1] = y
selectedBlock.location[0] = x
break;
}
}
return [this, gameLogicState]
}
collision(gameLogicState, direction) {
for (let each = 0; each < 4; each++) {
if (this.blocks[each].collisionCheck(gameLogicState, direction)) {
return true
} else {
return false
}
}
}
}
class block {
constructor(location, shape) {
this.location = location
this.shape = shape
}
collisionCheck(gameLogicState, direction) {
let x = this.location[0];
let y = this.location[1];
// Calculate the new coordinates based on the direction
let newX = x;
let newY = y;
switch (direction) {
case 'left':
newX = x - 1;
break;
case 'right':
newX = x + 1;
break;
case 'down':
newY = y + 1;
break;
}
// Check if the new coordinates are within the bounds of the gameLogicState
if (newX < 0 || newX >= gameLogicState.length || newY < 0 || newY >= gameLogicState[0].length) {
return true; // The block cannot move because it's out of bounds
}
// Check if the new location is null or occupied by the same block
if (gameLogicState[newX][newY] !== null && gameLogicState[newX][newY] === "block") {
return true; // The block cannot move because of a collision
}
// Update the block's location
return false; // The block can move in the specified direction
}
}
function createItem(array, item) {
randomformlist = ["Cube", "T", "Z", "Line"]
randomint = Math.floor(Math.random() * 4);
let currentItem = new shape([4, 1], "Cube")
for (let each = 0; each < currentItem.blocks.length; each++) {
let x = currentItem.blocks[each].location[0]
let y = currentItem.blocks[each].location[1]
gameLogicState[x][y] = currentItem.blocks[each]
}
console.log(gameLogicState)
return [currentItem, gameLogicState];
}
function render(gameLogicState, gameRenderState) {
try {
for (let i = 0; i < gameLogicState.length; i++) {
for (let j = 0; j < gameLogicState[i].length; j++) {
if (gameLogicState[i][j] !== null) {
colorCell(gameRenderState[i][j], '#1e90ff');
} else if (gameLogicState[i][j] == null) {
colorCell(gameRenderState[i][j], 'transparent')
}
}
}
} catch (TypeError) {
}
}
//todo test move function maybe its a reason for the infinte array bug
function store(gameLogicState, currentItem) {
for (let each = 0; each < 4; each++) {
y = currentItem.blocks[each].location[1]
x = currentItem.blocks[each].location[0]
gameLogicState[x][y] = "block"
}
return gameLogicState
}
function checkIfLineIsFull() {
let row = 0
let line = 19
let counter = 0
let lineFull = false
for (line; line > 0; line--) {
for (row; row < 10; row++) {
if (gameLogicState[row][line] != null) {
counter++
if (counter == 10) {
lineFull = true
return {lineFull: lineFull, line: line}
}
} else {
counter = 0
}
}
return {lineFull: lineFull}
}
}
function removeLine(line) {
buffer = undefined
for (horiontal = 0; horiontal < 10; horiontal++) {
for (vertical = line; vertical > 0; vertical--) {
if (vertical == 0) {
buffer = gameLogicState[horiontal][vertical]
gameLogicState[horiontal][vertical] = null
} else {
gameLogicState[horiontal][vertical] = gameLogicState[horiontal][vertical - 1]
}
}
}
return gameLogicState
}
var gameLogicState = generateArrayForTheGame()
currentItem = null
wingame = true;
var itemList = [];
document.addEventListener('keydown', function (event) {
if (event.key === 'ArrowLeft') {
// Left arrow key pressed
gameData = currentItem.move(gameLogicState, "left")
} else if (event.key === 'ArrowRight') {
// Right arrow key pressed
gameData = currentItem.move(gameLogicState, "right")
}
gameLogicState = gameData[1]
currentItem = gameData[0]
render(gameLogicState, grid)
});
//todo gameloop neu schreiben
function gameLoop() {
if (currentItem == null) {
gameData = createItem(gameLogicState, currentItem);
currentItem = gameData[0]
gameLogicState = gameData[1]
}
if (currentItem.collision(gameLogicState, 'down')) {
gameLogicState = store(gameLogicState, currentItem);
if (checkIfLineIsFull().lineFull) {
line = checkIfLineIsFull().line
gameLogicState = removeLine(checkIfLineIsFull().line)
console.log("removed line number", line)
}
gameData = createItem(gameLogicState, currentItem);
currentItem = gameData[0];
gameLogicState = gameData[1];
} else {
gameData = gravity(currentItem, gameLogicState);
currentItem = gameData[0];
gameLogicState = gameData[1];
}
render(gameLogicState, grid);
setTimeout(gameLoop, 150);
}
gameLoop()


