js实现俄罗斯方块游戏效果

代码语言:html

所属分类:游戏

代码描述:js实现俄罗斯方块游戏效果

代码标签: 方块 游戏 效果

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">

<style>
body {
  margin: 0;
  position: absolute;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  background-color: #eee;
}

.block {
  box-sizing: border-box;
  position: absolute;
  transform: scale(0.85);
  border-radius: 6px;
}

.block--test {
  background-color: rgba(152, 152, 152, 0.514);
}

.block--block {
  animation-name: drop;
  animation-timing-function: linear;
  animation-iteration-count: 1;
  background: linear-gradient(#E6DADA, #FFB88C, #FFAFBD, #606c88);
  background-size: 100vw 100vh;
  background-position: 0 0;
  background-attachment: fixed;
}

.block--invalid {
  background-color:  #e538357e;
}

@keyframes drop {
  from {
    transform: translateY(-100vh) scale(0.85);
  }
  to {
    transform: translateY(0) scale(0.85);
  }
}
</style>

</head>
<body translate="no">

<script >
/*
  Automatic and responsive Tetris
  can be made to clear the full lines
  but it's more fun to watch when it doesn't
  control it with the below 3 variables
  Created for my website https://kkmet.com
*/
const blockSize = 35
const stepSpeed = 70
const fallSpeed = 1500
const container = document.body

const viewWidth = window.innerWidth
const viewHeight = window.innerHeight

const xBlockCount = Math.ceil(viewWidth / blockSize)
const yBlockCount = Math.ceil(viewHeight / blockSize)
let currentYIndex = 0

const STATES = {
  EMPTY: 'empty',
  TEST: 'test',
  INVALID: 'invalid',
  BLOCK: 'block',
  DONE: 'done',
}

const SHAPES = [
  V_LINE,
  H_LINE,
  BOX,
  DOT,
  L_SHAPE_1,
  L_SHAPE_2,
  L_SHAPE_3,
  L_SHAPE_4,
  L_SHAPE_5,
  L_SHAPE_6,
  L_SHAPE_7,
  L_SHAPE_8,
  Z_SHAPE_1,
  Z_SHAPE_2,
  Z_SHAPE_3,
  Z_SHAPE_4,
  T_SHAPE_1,
  T_SHAPE_2,
  T_SHAPE_3,
  T_SHAPE_4,
]

let grid = Array.from({ length: yBlockCount }, () => {
  return Array.from({ length: xBlockCount}, () => {
    return STATES.EMPTY
  })
})

addPiece()

async function addPiece() {
  [x, y] = getCoordinates()
  await testShapes(x, y)
  let lastLineHasEmptyBlocks = currentYIndex < (yBlockCount - 1) || grid[yBlockCount - 1].some(x => x === STATES.EMPTY)

  if (lastLineHasEmptyBlocks) {
    addPiece()
  }
}

function getCoordinates() {
  const lineIsFull = !grid[currentYIndex].some(state => state === STATES.EMPTY)
  const lastLine = currentYIndex === (yBlockCount - 1)

  if (lineIsFull && !lastLine) {
    currentYIndex++
  }

  let randomX = Math.floor(Math.random() * xBlockCount)

  while (grid[currentYIndex][randomX] !== STATES.EMPTY) {
    if (randomX === (xBlockCount - 1)) {
      randomX = 0
    } else {
      randomX++
    }
  }
  
  return [randomX, currentYIndex]
}

async function testShapes(x, y) {
  const shapeFunction = getRandomShapeFunction()
  const shapeCoords = shapeFunction(x, y)
  const previousShapeCoordsStates = []
  let invalid = false

  shapeCoords.forEach(([x, y]) => {
    if (!grid[y] || !grid[y][x]) {
      invalid = true
    }
    previousShapeCoordsStates.push(grid[y][x])
    grid[y][x] = STATES.TEST
  })

  await draw(stepSpeed)

  if (invalid || invalidPoints(shapeCoords, previousShapeCoordsStates)) {
    setPoints(shapeCoords, STATES.INVALID)

    await draw(stepSpeed)

    shapeCoords.forEach(([x, y], index) => {
      if (grid[y] && grid[y][x]) {
        grid[y][x] = previousShapeCoordsStates[index]
      }
    })

    await draw(stepSpeed)
  } else {
    setPoints(shapeCoords, STATES.BLOCK)

    await draw(fallSpeed)
  }
}

function createBlock(type, x, y) {
  const blockElement = document.createElement('div')
  blockElement.classList.add('block', `block--${type}`)
  blockElement.style.height = blockElement.style.width = `${blockSize}px`
  blockElement.style.bottom = `${y * blockSize}px`
  blockElement.style.left = `${x * blockSize}px`
  if (type === STATES.BLOCK) {
    blockElement.style.animationDuration = `${fallSpeed}ms`
  }
  container.appendChild(blockElement)
  return blockElement
}

function hasAccessibleX(y) {
  return grid[y].some((state, x) => {
    let accessible = true
    if (state !== STATES.EMPTY) {
      accessible = false
    }
    
    grid.forEach((row, index) => {
      if (index > y && row[x] !== STATES.EMPTY) {
        accessible = false
      }
    })

    return accessible
  })
}

function invalidPoints(shapeCoords, previousShapeCoordsStates).........完整代码请登录后点击上方下载按钮下载查看

网友评论0