$P@D$3RV£R commited on
Commit
f7e450a
·
1 Parent(s): 33012c5

Fix tile flickering by stabilizing rendering logic and removing inconsistent visibility toggles

Browse files
Files changed (2) hide show
  1. game.js +41 -32
  2. styles.css +5 -0
game.js CHANGED
@@ -219,10 +219,9 @@ class Match3Game {
219
 
220
  this.lastBoardState = currentState;
221
 
222
- // Use requestAnimationFrame for smooth updates
223
- requestAnimationFrame(() => {
224
- for (let row = 0; row < this.boardRows; row++) {
225
- for (let col = 0; col < this.boardCols; col++) {
226
  let cell = existingCells[row * this.boardCols + col];
227
 
228
  if (!cell || needsFullRender) {
@@ -261,18 +260,25 @@ class Match3Game {
261
  const isMatchEnlarge = cell.classList.contains('match-enlarge');
262
  const hasActiveAnimation = isMatched || isMatchEnlarge;
263
 
264
- // Skip if cell is marked as empty (-1) - it will be handled by gravity
265
- if (gemType === -1 && !hasActiveAnimation) {
266
- // Keep cell hidden/empty until gravity fills it
267
- cell.style.display = 'none';
268
- cell.style.opacity = '0';
269
- cell.style.visibility = 'hidden';
 
270
  continue;
271
  }
272
 
273
- // Only update if not animating and not empty
274
- if (!hasActiveAnimation && gemType !== -1) {
275
- // Restore cell visibility if it was hidden
 
 
 
 
 
 
276
  cell.style.display = '';
277
  cell.style.opacity = '';
278
  cell.style.visibility = '';
@@ -286,10 +292,22 @@ class Match3Game {
286
  cell.style.transition = '';
287
  }
288
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  }
290
  }
291
  }
292
- });
293
 
294
  // Add board-level mousemove for better drag tracking
295
  boardElement.addEventListener('mousemove', (e) => {
@@ -919,17 +937,8 @@ class Match3Game {
919
  matches.forEach(match => {
920
  this.board[match.row][match.col] = -1; // Mark as empty
921
 
922
- // Remove the matched cell from DOM completely
923
- const cell = document.querySelector(
924
- `[data-row="${match.row}"][data-col="${match.col}"]`
925
- );
926
- if (cell) {
927
- cell.classList.remove('matched');
928
- // Hide the cell completely
929
- cell.style.display = 'none';
930
- cell.style.opacity = '0';
931
- cell.style.visibility = 'hidden';
932
- }
933
  });
934
 
935
  // Make pieces fall
@@ -938,8 +947,11 @@ class Match3Game {
938
  // Fill empty spaces
939
  this.fillEmptySpaces();
940
 
941
- // Re-render board to show new tiles and remove empty spaces
942
- this.renderBoard(true);
 
 
 
943
 
944
  // Very short delay before checking for new matches
945
  await this.sleep(50);
@@ -947,13 +959,10 @@ class Match3Game {
947
 
948
  this.isProcessing = false;
949
 
950
- // Render any pending updates after processing completes
951
  if (this.renderPending) {
952
  this.renderPending = false;
953
- // Use requestAnimationFrame for smooth update
954
- requestAnimationFrame(() => {
955
- this.renderBoard(true);
956
- });
957
  }
958
 
959
  this.checkGameOver();
 
219
 
220
  this.lastBoardState = currentState;
221
 
222
+ // Update cells directly without requestAnimationFrame to prevent flickering
223
+ for (let row = 0; row < this.boardRows; row++) {
224
+ for (let col = 0; col < this.boardCols; col++) {
 
225
  let cell = existingCells[row * this.boardCols + col];
226
 
227
  if (!cell || needsFullRender) {
 
260
  const isMatchEnlarge = cell.classList.contains('match-enlarge');
261
  const hasActiveAnimation = isMatched || isMatchEnlarge;
262
 
263
+ // Skip if cell is marked as empty (-1)
264
+ if (gemType === -1) {
265
+ // Hide empty cells but don't manipulate inline styles repeatedly
266
+ if (!cell.classList.contains('empty-cell')) {
267
+ cell.classList.add('empty-cell');
268
+ cell.style.display = 'none';
269
+ }
270
  continue;
271
  }
272
 
273
+ // Remove empty-cell class if present
274
+ if (cell.classList.contains('empty-cell')) {
275
+ cell.classList.remove('empty-cell');
276
+ cell.style.display = '';
277
+ }
278
+
279
+ // Only update if not animating
280
+ if (!hasActiveAnimation) {
281
+ // Always ensure cell is visible for non-empty cells
282
  cell.style.display = '';
283
  cell.style.opacity = '';
284
  cell.style.visibility = '';
 
292
  cell.style.transition = '';
293
  }
294
  }
295
+ } else {
296
+ // Even if no update needed, ensure visibility is correct
297
+ if (gemType === -1) {
298
+ if (!cell.classList.contains('empty-cell')) {
299
+ cell.classList.add('empty-cell');
300
+ cell.style.display = 'none';
301
+ }
302
+ } else {
303
+ if (cell.classList.contains('empty-cell')) {
304
+ cell.classList.remove('empty-cell');
305
+ cell.style.display = '';
306
+ }
307
+ }
308
  }
309
  }
310
  }
 
311
 
312
  // Add board-level mousemove for better drag tracking
313
  boardElement.addEventListener('mousemove', (e) => {
 
937
  matches.forEach(match => {
938
  this.board[match.row][match.col] = -1; // Mark as empty
939
 
940
+ // Mark cell as empty - renderBoard will handle hiding it
941
+ // Don't manipulate DOM directly here to prevent flickering
 
 
 
 
 
 
 
 
 
942
  });
943
 
944
  // Make pieces fall
 
947
  // Fill empty spaces
948
  this.fillEmptySpaces();
949
 
950
+ // Re-render board to show new tiles - do it synchronously to prevent flickering
951
+ // Only render if not already processing (double-check)
952
+ if (!this.isProcessing) {
953
+ this.renderBoard(true);
954
+ }
955
 
956
  // Very short delay before checking for new matches
957
  await this.sleep(50);
 
959
 
960
  this.isProcessing = false;
961
 
962
+ // Render any pending updates after processing completes - do it synchronously
963
  if (this.renderPending) {
964
  this.renderPending = false;
965
+ this.renderBoard(true);
 
 
 
966
  }
967
 
968
  this.checkGameOver();
styles.css CHANGED
@@ -477,6 +477,11 @@ body.dark-theme .level-complete-content {
477
  display: flex;
478
  justify-content: center;
479
  align-items: center;
 
 
 
 
 
480
  font-size: 3.24em;
481
  padding: 0;
482
  position: relative;
 
477
  display: flex;
478
  justify-content: center;
479
  align-items: center;
480
+ }
481
+
482
+ .cell.empty-cell {
483
+ display: none !important;
484
+ }
485
  font-size: 3.24em;
486
  padding: 0;
487
  position: relative;