{"id":208,"date":"2023-12-13T17:46:48","date_gmt":"2023-12-13T17:46:48","guid":{"rendered":"https:\/\/stephanietoudeka.be\/?page_id=208"},"modified":"2023-12-13T17:51:55","modified_gmt":"2023-12-13T17:51:55","slug":"teris","status":"publish","type":"page","link":"https:\/\/stephanietoudeka.be\/?page_id=208","title":{"rendered":"Teris"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"208\" class=\"elementor elementor-208\">\n\t\t\t\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-0581fdd elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"0581fdd\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-9579d23\" data-id=\"9579d23\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-element elementor-element-fda0170 elementor-widget elementor-widget-html\" data-id=\"fda0170\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<!DOCTYPE html>\n<html>\n<head>\n  <title>Basic Tetris HTML Game<\/title>\n  <meta charset=\"UTF-8\">\n  <style>\n  html, body {\n    height: 100%;\n    margin: 0;\n  }\n\n  body {\n    background: black;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n  }\n\n  canvas {\n    border: 1px solid white;\n  }\n  <\/style>\n<\/head>\n<body>\n<canvas width=\"320\" height=\"640\" id=\"game\"><\/canvas>\n<script>\n\/\/ https:\/\/tetris.fandom.com\/wiki\/Tetris_Guideline\n\n\/\/ get a random integer between the range of [min,max]\n\/\/ @see https:\/\/stackoverflow.com\/a\/1527820\/2124254\nfunction getRandomInt(min, max) {\n  min = Math.ceil(min);\n  max = Math.floor(max);\n\n  return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\n\/\/ generate a new tetromino sequence\n\/\/ @see https:\/\/tetris.fandom.com\/wiki\/Random_Generator\nfunction generateSequence() {\n  const sequence = ['I', 'J', 'L', 'O', 'S', 'T', 'Z'];\n\n  while (sequence.length) {\n    const rand = getRandomInt(0, sequence.length - 1);\n    const name = sequence.splice(rand, 1)[0];\n    tetrominoSequence.push(name);\n  }\n}\n\n\/\/ get the next tetromino in the sequence\nfunction getNextTetromino() {\n  if (tetrominoSequence.length === 0) {\n    generateSequence();\n  }\n\n  const name = tetrominoSequence.pop();\n  const matrix = tetrominos[name];\n\n  \/\/ I and O start centered, all others start in left-middle\n  const col = playfield[0].length \/ 2 - Math.ceil(matrix[0].length \/ 2);\n\n  \/\/ I starts on row 21 (-1), all others start on row 22 (-2)\n  const row = name === 'I' ? -1 : -2;\n\n  return {\n    name: name,      \/\/ name of the piece (L, O, etc.)\n    matrix: matrix,  \/\/ the current rotation matrix\n    row: row,        \/\/ current row (starts offscreen)\n    col: col         \/\/ current col\n  };\n}\n\n\/\/ rotate an NxN matrix 90deg\n\/\/ @see https:\/\/codereview.stackexchange.com\/a\/186834\nfunction rotate(matrix) {\n  const N = matrix.length - 1;\n  const result = matrix.map((row, i) =>\n    row.map((val, j) => matrix[N - j][i])\n  );\n\n  return result;\n}\n\n\/\/ check to see if the new matrix\/row\/col is valid\nfunction isValidMove(matrix, cellRow, cellCol) {\n  for (let row = 0; row < matrix.length; row++) {\n    for (let col = 0; col < matrix[row].length; col++) {\n      if (matrix[row][col] && (\n          \/\/ outside the game bounds\n          cellCol + col < 0 ||\n          cellCol + col >= playfield[0].length ||\n          cellRow + row >= playfield.length ||\n          \/\/ collides with another piece\n          playfield[cellRow + row][cellCol + col])\n        ) {\n        return false;\n      }\n    }\n  }\n\n  return true;\n}\n\n\/\/ place the tetromino on the playfield\nfunction placeTetromino() {\n  for (let row = 0; row < tetromino.matrix.length; row++) {\n    for (let col = 0; col < tetromino.matrix[row].length; col++) {\n      if (tetromino.matrix[row][col]) {\n\n        \/\/ game over if piece has any part offscreen\n        if (tetromino.row + row < 0) {\n          return showGameOver();\n        }\n\n        playfield[tetromino.row + row][tetromino.col + col] = tetromino.name;\n      }\n    }\n  }\n\n  \/\/ check for line clears starting from the bottom and working our way up\n  for (let row = playfield.length - 1; row >= 0; ) {\n    if (playfield[row].every(cell => !!cell)) {\n\n      \/\/ drop every row above this one\n      for (let r = row; r >= 0; r--) {\n        for (let c = 0; c < playfield[r].length; c++) {\n          playfield[r][c] = playfield[r-1][c];\n        }\n      }\n    }\n    else {\n      row--;\n    }\n  }\n\n  tetromino = getNextTetromino();\n}\n\n\/\/ show the game over screen\nfunction showGameOver() {\n  cancelAnimationFrame(rAF);\n  gameOver = true;\n\n  context.fillStyle = 'black';\n  context.globalAlpha = 0.75;\n  context.fillRect(0, canvas.height \/ 2 - 30, canvas.width, 60);\n\n  context.globalAlpha = 1;\n  context.fillStyle = 'white';\n  context.font = '36px monospace';\n  context.textAlign = 'center';\n  context.textBaseline = 'middle';\n  context.fillText('GAME OVER!', canvas.width \/ 2, canvas.height \/ 2);\n}\n\nconst canvas = document.getElementById('game');\nconst context = canvas.getContext('2d');\nconst grid = 32;\nconst tetrominoSequence = [];\n\n\/\/ keep track of what is in every cell of the game using a 2d array\n\/\/ tetris playfield is 10x20, with a few rows offscreen\nconst playfield = [];\n\n\/\/ populate the empty state\nfor (let row = -2; row < 20; row++) {\n  playfield[row] = [];\n\n  for (let col = 0; col < 10; col++) {\n    playfield[row][col] = 0;\n  }\n}\n\n\/\/ how to draw each tetromino\n\/\/ @see https:\/\/tetris.fandom.com\/wiki\/SRS\nconst tetrominos = {\n  'I': [\n    [0,0,0,0],\n    [1,1,1,1],\n    [0,0,0,0],\n    [0,0,0,0]\n  ],\n  'J': [\n    [1,0,0],\n    [1,1,1],\n    [0,0,0],\n  ],\n  'L': [\n    [0,0,1],\n    [1,1,1],\n    [0,0,0],\n  ],\n  'O': [\n    [1,1],\n    [1,1],\n  ],\n  'S': [\n    [0,1,1],\n    [1,1,0],\n    [0,0,0],\n  ],\n  'Z': [\n    [1,1,0],\n    [0,1,1],\n    [0,0,0],\n  ],\n  'T': [\n    [0,1,0],\n    [1,1,1],\n    [0,0,0],\n  ]\n};\n\n\/\/ color of each tetromino\nconst colors = {\n  'I': 'cyan',\n  'O': 'yellow',\n  'T': 'purple',\n  'S': 'green',\n  'Z': 'red',\n  'J': 'blue',\n  'L': 'orange'\n};\n\nlet count = 0;\nlet tetromino = getNextTetromino();\nlet rAF = null;  \/\/ keep track of the animation frame so we can cancel it\nlet gameOver = false;\n\n\/\/ game loop\nfunction loop() {\n  rAF = requestAnimationFrame(loop);\n  context.clearRect(0,0,canvas.width,canvas.height);\n\n  \/\/ draw the playfield\n  for (let row = 0; row < 20; row++) {\n    for (let col = 0; col < 10; col++) {\n      if (playfield[row][col]) {\n        const name = playfield[row][col];\n        context.fillStyle = colors[name];\n\n        \/\/ drawing 1 px smaller than the grid creates a grid effect\n        context.fillRect(col * grid, row * grid, grid-1, grid-1);\n      }\n    }\n  }\n\n  \/\/ draw the active tetromino\n  if (tetromino) {\n\n    \/\/ tetromino falls every 35 frames\n    if (++count > 35) {\n      tetromino.row++;\n      count = 0;\n\n      \/\/ place piece if it runs into anything\n      if (!isValidMove(tetromino.matrix, tetromino.row, tetromino.col)) {\n        tetromino.row--;\n        placeTetromino();\n      }\n    }\n\n    context.fillStyle = colors[tetromino.name];\n\n    for (let row = 0; row < tetromino.matrix.length; row++) {\n      for (let col = 0; col < tetromino.matrix[row].length; col++) {\n        if (tetromino.matrix[row][col]) {\n\n          \/\/ drawing 1 px smaller than the grid creates a grid effect\n          context.fillRect((tetromino.col + col) * grid, (tetromino.row + row) * grid, grid-1, grid-1);\n        }\n      }\n    }\n  }\n}\n\n\/\/ listen to keyboard events to move the active tetromino\ndocument.addEventListener('keydown', function(e) {\n  if (gameOver) return;\n\n  \/\/ left and right arrow keys (move)\n  if (e.which === 37 || e.which === 39) {\n    const col = e.which === 37\n      ? tetromino.col - 1\n      : tetromino.col + 1;\n\n    if (isValidMove(tetromino.matrix, tetromino.row, col)) {\n      tetromino.col = col;\n    }\n  }\n\n  \/\/ up arrow key (rotate)\n  if (e.which === 38) {\n    const matrix = rotate(tetromino.matrix);\n    if (isValidMove(matrix, tetromino.row, tetromino.col)) {\n      tetromino.matrix = matrix;\n    }\n  }\n\n  \/\/ down arrow key (drop)\n  if(e.which === 40) {\n    const row = tetromino.row + 1;\n\n    if (!isValidMove(tetromino.matrix, row, tetromino.col)) {\n      tetromino.row = row - 1;\n\n      placeTetromino();\n      return;\n    }\n\n    tetromino.row = row;\n  }\n});\n\n\/\/ start the game\nrAF = requestAnimationFrame(loop);\n<\/script>\n<\/body>\n<\/html>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Basic Tetris HTML Game<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"site-sidebar-layout":"no-sidebar","site-content-layout":"","ast-site-content-layout":"full-width-container","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"disabled","ast-breadcrumbs-content":"","ast-featured-img":"disabled","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"","footnotes":""},"class_list":["post-208","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Teris -<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/stephanietoudeka.be\/?page_id=208\" \/>\n<meta property=\"og:locale\" content=\"nl_NL\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Teris -\" \/>\n<meta property=\"og:description\" content=\"Basic Tetris HTML Game\" \/>\n<meta property=\"og:url\" content=\"https:\/\/stephanietoudeka.be\/?page_id=208\" \/>\n<meta property=\"article:modified_time\" content=\"2023-12-13T17:51:55+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verwachte leestijd\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minuut\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/stephanietoudeka.be\/?page_id=208\",\"url\":\"https:\/\/stephanietoudeka.be\/?page_id=208\",\"name\":\"Teris -\",\"isPartOf\":{\"@id\":\"https:\/\/stephanietoudeka.be\/#website\"},\"datePublished\":\"2023-12-13T17:46:48+00:00\",\"dateModified\":\"2023-12-13T17:51:55+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/stephanietoudeka.be\/?page_id=208#breadcrumb\"},\"inLanguage\":\"nl-NL\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/stephanietoudeka.be\/?page_id=208\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/stephanietoudeka.be\/?page_id=208#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/stephanietoudeka.be\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Teris\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/stephanietoudeka.be\/#website\",\"url\":\"https:\/\/stephanietoudeka.be\/\",\"name\":\"\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/stephanietoudeka.be\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"nl-NL\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Teris -","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/stephanietoudeka.be\/?page_id=208","og_locale":"nl_NL","og_type":"article","og_title":"Teris -","og_description":"Basic Tetris HTML Game","og_url":"https:\/\/stephanietoudeka.be\/?page_id=208","article_modified_time":"2023-12-13T17:51:55+00:00","twitter_card":"summary_large_image","twitter_misc":{"Verwachte leestijd":"1 minuut"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/stephanietoudeka.be\/?page_id=208","url":"https:\/\/stephanietoudeka.be\/?page_id=208","name":"Teris -","isPartOf":{"@id":"https:\/\/stephanietoudeka.be\/#website"},"datePublished":"2023-12-13T17:46:48+00:00","dateModified":"2023-12-13T17:51:55+00:00","breadcrumb":{"@id":"https:\/\/stephanietoudeka.be\/?page_id=208#breadcrumb"},"inLanguage":"nl-NL","potentialAction":[{"@type":"ReadAction","target":["https:\/\/stephanietoudeka.be\/?page_id=208"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/stephanietoudeka.be\/?page_id=208#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/stephanietoudeka.be\/"},{"@type":"ListItem","position":2,"name":"Teris"}]},{"@type":"WebSite","@id":"https:\/\/stephanietoudeka.be\/#website","url":"https:\/\/stephanietoudeka.be\/","name":"","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/stephanietoudeka.be\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"nl-NL"}]}},"_links":{"self":[{"href":"https:\/\/stephanietoudeka.be\/index.php?rest_route=\/wp\/v2\/pages\/208","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/stephanietoudeka.be\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/stephanietoudeka.be\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/stephanietoudeka.be\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/stephanietoudeka.be\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=208"}],"version-history":[{"count":4,"href":"https:\/\/stephanietoudeka.be\/index.php?rest_route=\/wp\/v2\/pages\/208\/revisions"}],"predecessor-version":[{"id":218,"href":"https:\/\/stephanietoudeka.be\/index.php?rest_route=\/wp\/v2\/pages\/208\/revisions\/218"}],"wp:attachment":[{"href":"https:\/\/stephanietoudeka.be\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=208"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}