html 俄罗斯方块w /高分跟踪

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了html 俄罗斯方块w /高分跟踪相关的知识,希望对你有一定的参考价值。

Tetris w/ high score tracking
-----------------------------
Hope you have fun playing! Feature suggestions and improvements are very welcome! 

Browser version available here: https://dutchbones.github.io/tetris

A [Pen](https://codepen.io/harunpehlivan/pen/pZzLze) by [HARUN PEHLİVAN](https://codepen.io/harunpehlivan) on [CodePen](https://codepen.io).

[License](https://codepen.io/harunpehlivan/pen/pZzLze/license).
$darkBlue:#202028;
$white: #fff;
$transBlack: rgba(0, 0, 0, .65);

body, html {
    background-image: url('https://s19.postimg.cc/53hmmyd9f/stars-3000x2000-pink-cosmos-hd-7164.jpg');
    background-size: cover;
    background-repeat: no-repeat;
    background-position: center;
    color:$white;
    font-family: 'Lucida Console';
    height: 100%;
    overflow: hidden;
    text-align: center;
    min-width: 700px;
}

.wrapper {
    display: inline-flex;
    justify-content: center;
    margin: 1vh 0;
    padding: 1% 1% .5% 1%;
    background: $transBlack;
    box-shadow: -1px 5px 5px rgba(0, 0, 0, .75);;
}

.modal {
    margin-top: 20vh !important;
    border: solid .05em $white;
    box-shadow: -15px 20px 20px rgba(0, 0, 0, .75) !important;
}

.modal-content {
    background: $darkBlue;
}

.modal-content .btn {
    font-size: 18px !important;
}

.modal-content input {
    color: white;
    font-size: 24px !important;
    width: 50% !important;
    text-align: center;
}

.modal-content label {
    font-size: 16px !important;
}

.btn:focus {
    background-color: #00bfa5 !important;
}

.btn {
    background-color: #009688 !important;
}

.yourScore {
	padding-bottom: 0px; 
}

.detailsLeft {
	width: 130px;
	position: relative;
	height: 90vh;
	margin: 0% 2%;
	text-align: right;
	font-size: 16px;
 }

.highScores {
	position: absolute;
	bottom: 35px;
	right: 0px;
	line-height: 10px;
	font-size: 14px;
 }

.detailsRight {
	position: relative;
	height: 90vh;
	margin: 2% 2% 0% 2%;
    text-align: left;
}

.next {
	height: 15vh;
	border: solid .1em $white;
}

.controls {
	position: absolute;
	bottom: 50px;
	left: 0px;
    font-size: 14px;
	line-height: 8px;
}

.tetris {
	height: 90vh;
  border: solid .25em $white;
}

.footer {
	position: absolute;
	bottom: 0;
	font-size: 12px;
    color: rgba(255, 255, 255, .85);
	line-height: 0px;
}

.footer a:link, a:visited, a:active {
	color: rgba(255, 255, 255, .85);
	text-decoration: none;
}

.footer a:link:hover {
	color: white;
	text-decoration: none;
}

@media (max-width: 920px), (max-height: 800px){
    body, html {
    font-size: 16px;
    margin: 0px !important;
    }
    
	.modal {
        width: 25vw !important;
        margin-top: 20vh !important;
        border: solid .05em $white;
        box-shadow: -15px 20px 20px rgba(0, 0, 0, .75) !important;
        min-width: 500px;
    }
    
    .modal-content {
        background: $darkBlue;
    }
    
    .modal-content .btn {
        font-size: 14px !important;
    }
    
    .modal-content input {
        color: white;
        font-size: 12px !important;
        width: 50% !important;
        text-align: center;
    }
    
    .modal-content label {
        font-size: 14px !important;
    }
	
    .wrapper {
        display: inline-flex;
        justify-content: center;
        background: rgba(0, 0, 0, .5) !important;
        padding: 0% 0%;
        background: $transBlack;
        margin: 0px !important;
        height: 100%;
        width: 100%;
    }
    
    .detailsLeft {
			height: 80vh;
			width: 110px;
      margin: 5% 1% 0% 0%;
			font-size: 14px;
      }
	
	.score-title {
		font-size: 14px;
	}
	
		.highScores {
			line-height: 8px;
			font-size: 12px;
  }
    
    .detailsRight {
			height: 80vh;
			width: 120px;
			margin: 5% 0% 0% 1%;
			text-align: left;
    }
	
	  .next {
      border: solid .1em $white;
			height: 12vh;
    }

    .controls {
			line-height: 8px;
			font-size: 12px;
    }
    
    .tetris {
	    height: 85vh;
			border: solid .25em $white;
			margin-bottom: 2%;
			margin-top: 2%;
    }
		.footer {
			font-size: 12px;
		}
}
$(document).ready(function(){
  $('#newGame').modal(
    {'dismissible': false});
  $('#newGame').modal('open');
  $("#newGameBtn").focus() 
  });
    
  let highScoreMin;

	function loadHighScores() {
		$.ajax({
			url: 'https://api.mlab.com/api/1/databases/tetrishighscores/collections/scores?s={"score":-1}&apiKey=E8dx03lqLdc5pG_K002t_lJrPOwDi1vG',
			type: "GET",
			success: (data) => {
        let scoreLog = `<p class="score-title"><u>High Scores:</u></p>`;
        highScoreMin = data[10].score;
				for(var i = 0; i <= 10; i++){
					scoreLog += `<p>${data[i].name.slice(0, 7)}: ${data[i].score}</p>`;
				}
				$('.highScores').html(scoreLog);
			},
			error: (xhr, status, err) => {
				console.log(err);
			}
		});
  }
  
let pause = true;

const canvas = document.querySelector('.tetris');
const context = canvas.getContext('2d');

const nextCanvas = document.querySelector('.next');
const nextContext = nextCanvas.getContext('2d');

context.scale(20, 20);
nextContext.scale(30, 30);

const arena = createMatrix(12, 20);
const nextArena = createMatrix(6, 6);

const player = {
  pos: {x: 0, y: 0},
  matrix: null,
  score: 0,
  level: 1,
  dropInterval: 1000,
  DROP_SLOW: 100,
  next: null,
};

let dropCounter = 0;
let DROP_FAST = 50;

function arenaSweep(){
  let rowCount = 1;
  outer: for(y=arena.length - 1; y > 0; y--){
    for(x=0; x < arena[y].length; x++){
      if(arena[y][x] === 0) {
        continue outer;
      }
    }
    const row = arena.splice(y, 1)[0].fill(0);
    arena.unshift(row);
    y++;

    player.score += rowCount * 100;
    rowCount *= 2;
    let scoreStr = player.score.toString();
    if(scoreStr.length > 3){
      let num = Number(scoreStr.slice(0, scoreStr.length - 3));
      player.level = num + 1;
      player.dropInterval = 1000 - (num * 50);
      player.DROP_SLOW = 1000 - (num * 50);
    }
  }
}

function collide(arena, player){
  const [m, o] = [player.matrix, player.pos];
  for(y=0; y<m.length; y++){
    for(x=0; x < m[y].length; x++){
      if(m[y][x] !== 0 && ( arena[y + o.y] && arena[y + o.y][x + o.x]) !== 0){
        return true;
      }
    }
  }
  return false;
}

function createMatrix(w, h){
  const matrix = [];
  while(h--){
    matrix.push(new Array(w).fill(0));
  }
  return matrix;
}

function createPiece(type){
  if (type === 'I'){
    return [
      [0, 1, 0, 0],
      [0, 1, 0, 0],
      [0, 1, 0, 0],
      [0, 1, 0, 0]
    ];
  } else if (type === 'J'){
    return [
      [0, 2, 0],
      [0, 2, 0],
      [2, 2, 0]
    ];
  } else if (type === 'L'){
    return [
      [0, 3, 0],
      [0, 3, 0],
      [0, 3, 3]
    ];
  } else if (type === 'O'){
    return [
      [4,4],
      [4,4]
    ];
  } else if (type === 'S'){
    return [
      [0, 5, 5],
      [5, 5, 0],
      [0, 0, 0]
    ];
    } else if (type === 'T'){
      return [
        [0, 0, 0],
        [6, 6, 6],
        [0, 6, 0]
      ];
  } else if (type === 'Z'){
    return [
      [7, 7, 0],
      [0, 7, 7],
      [0, 0, 0]
    ];
  }
}

function drawNext(){
  nextContext.fillStyle = '#000';
  nextContext.fillRect(0, 0, nextCanvas.width, nextCanvas.height); 

  drawMatrix(nextArena, {x: 0, y:0}, nextContext);
  drawMatrix(player.next, {x: 1, y: 1}, nextContext);
}

function draw(){
  context.fillStyle = '#000';
  context.fillRect(0, 0, canvas.width, canvas.height);

  drawMatrix(arena, {x: 0, y: 0}, context);
  drawMatrix(player.matrix, player.pos, context);
}

function drawMatrix(mat, offset, cont){
  mat.forEach((row, y) => {
    row.forEach((value, x) =>{
      if(value !== 0){
        cont.fillStyle = colors[value];
        cont.fillRect(x + offset.x, y + offset.y, 1, 1);
      }
    });
  });
}

function merge(arena, player){
  player.matrix.forEach((row, y) => {
    row.forEach((value, x) => {
      if(value !== 0){
        arena[y + player.pos.y][x + player.pos.x] = value;
      }
    });
  });
}

function playerDrop(){
  player.pos.y++;
  if(collide(arena, player)){
    player.pos.y--;
    merge(arena, player);
    playerReset();
    arenaSweep();
    updateScore();
  }
  dropCounter = 0;
}

function playerMove(dir){
  player.pos.x += dir;
  if(collide(arena, player)){
    player.pos.x -= dir;
  }
}

function playerReset(){
  const pieces = 'IJLOSTZ';
  if(player.next === null){
    player.matrix = createPiece(pieces[pieces.length * Math.random() | 0]);
    player.next = createPiece(pieces[pieces.length * Math.random() | 0]);
  } else {
    player.matrix = player.next;
    player.next = createPiece(pieces[pieces.length * Math.random() | 0]);
  }
  drawNext();
  player.pos.y = 0;
  player.pos.x = (arena[0].length / 2 | 0) - (player.matrix[0].length / 2 | 0);
  if(collide(arena, player)){
    pauseGame();
    document.removeEventListener('keydown', keyListener);
    document.removeEventListener('keyup', keyListener);
    // clearPlayer();
  }
}

function clearPlayer(){
  player.dropInterval = 1000;
    player.DROP_SLOW = 1000;
    player.score = 0;
    player.level = 1;
    arena.forEach(row => row.fill(0));
    updateScore();
}

function playerRotate(dir){
  const pos = player.pos.x
  let offset = 1;
  rotate(player.matrix, dir);

  while(collide(arena, player)){
    player.pos.x += offset;
    offset = -(offset + (offset > 0 ? 1 : -1));
    if(offset > player.matrix[0].length) {
      rotate(player.matrix, -dir);
      player.pos.x = pos;
      return;
    }
  }
}

function rotate(matrix, dir){
  for(y=0; y < matrix.length; y++){
    for(x=0; x < y; x++){
      [ matrix[x][y], matrix[y][x], ] = [ matrix[y][x], matrix[x][y], ];
    }
  }
  if(dir > 0){
    matrix.forEach(row => row.reverse());
  } else {
    matrix.reverse();
  }
}

let lastTime = 0;
function update(time = 0){
  $('#pause').off();
  if(!pause){
    const deltaTime = time - lastTime;
    lastTime = time;
    dropCounter += deltaTime;
    if(dropCounter > player.dropInterval) {
      playerDrop();
    }
    draw();
    requestAnimationFrame(update);
    } else {
      draw();
    }
}

function updateScore(){
  document.querySelector('.score').innerHTML = `<p><b><u>Score:</u> ${player.score}</b></p>`;
  document.querySelector('.level').innerHTML = `<p><b><u>Level:</u> ${player.level}</b></p>`;
}

const colors = [
  null, 
  '#03A9F4',//I
  '#9C27B0',//J
  '#FFC107',//L
  '#E91E63',//O
  '#00BCD4',//S 
  '#8BC34A',//T
  '#3F51B5'//Z
];

function keyListener(e){
  if(e.type === 'keydown'){
    if(e.keyCode === 37){
      playerMove(-1)
    } else if(e.keyCode === 39){
      playerMove(1);
    } else if(e.keyCode === 81){
      playerRotate(-1);
    } else if(e.keyCode === 87 || e.keyCode === 38){
      playerRotate(1);
    } else if(e.keyCode === 27){
      pauseGame();
    }
  }

  if (e.keyCode === 40) {
    if (e.type === 'keydown') {
        if (player.dropInterval !== DROP_FAST) {
            playerDrop();
            player.dropInterval = DROP_FAST;
        }
    } else {
        player.dropInterval = player.DROP_SLOW;
    }
  }
};

function pauseGame(){
  if(pause === true){	
    pause = false;	
    $('#pause').modal({"onCloseStart": update() });
    $('#pause').modal('close');
  } else {
    if(collide(arena, player)){
      pause = true;
      if(player.score > 0){
      $('#gameOver').modal({
				'dismissible': false,
				"onOpenEnd": function(){ $('#name').focus(); } 
      });
      $('#gameOver').modal('open');
      $('.yourScore').html(`<p>Your Score: ${player.score}`)
    } else {
      $('#newGame').modal({'dismissible': false});
      $('#newGame').modal('open'); 
    }
    } else {
      pause = true;
      document.createEventListener
    $('#pause').modal({
      "dismissible": false,
      "onCloseStart": update() });
    $('#pause').modal('open'); 
    $("#pauseBtn").focus(); 
    $('body').on('keydown', (e)=>{
      if(e.keyCode === 39){
        $('#StartNewBtn').focus();
      }
      if(e.keyCode === 37){
        $("#pauseBtn").focus(); 
      }
    })
    }
  }
}

function newGame(){
	loadHighScores();
  clearPlayer();
  pause = false;
  playerReset();
  update();
  updateScore();  
  document.addEventListener('keydown', keyListener);
  document.addEventListener('keyup', keyListener);
}

$('#highScore').on('submit', (e) => {
  e.preventDefault();
  let name = $('#name').val();

  $.ajax({
    url: 'https://api.mlab.com/api/1/databases/tetrishighscores/collections/scores?apiKey=E8dx03lqLdc5pG_K002t_lJrPOwDi1vG',
    data: JSON.stringify({
      "date": new Date,
      "name": name,
      "score": player.score,
      "level": player.level
    }),
    type: "POST",
    contentType: "application/json",
    success: (data) => {
      $('#highScore').html( '<h4>Thank You!</h4>' );
    },
    error: (xhr, status, err) => {
      console.log(err);
    }
  });
});    

update();
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Tetris</title>
  <link rel="stylesheet" href="css/style.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-rc.2/css/materialize.min.css">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">

</head>
<body>
  <div class="wrapper">

    <div id="newGame" class="modal">
        <div class="modal-content">
          <h4>Tetris</h4>
          <button onclick="newGame()" id="newGameBtn" class="modal-close waves-effect waves-light btn" style="width:250px">New Game</button>
          </div>
        </div>

    <div id="pause" class="modal">
        <div class="modal-content">
          <h4>Game Paused</h4>
          <button onclick="pauseGame()" id="pauseBtn" class="modal-close waves-effect waves-light btn">Resume Game</button>
          <button onclick="newGame()" id="StartNewBtn" class="modal-close waves-effect waves-light btn">Start New Game</button>
          </div>
        </div>

    <div id="gameOver" class="modal">
        <div class="modal-content">
          <h4>Game Over</h4>
              <div class="yourScore"></div>
              <label for="name">Submit Your Score</label>
              <br><br>
              <form id="highScore">
              <input type="text" id="name" maxlength="7" placeholder="name..." onfocus="this.placeholder = ''" autocomplete="off" required/>
              <button type="submit" id="submit" class="waves-effect waves-light btn">Submit</button>
              </form>
					<br>
              <a onclick="newGame()" class="modal-close waves-effect waves-light btn">Start New Game</a>
          </div>
        </div>

    <div class="detailsLeft">
      <div class="score"></div>
      <div class="level"></div>
      <div class="highScores"></div>
    </div>

    <canvas class="tetris" width="240" height="400"></canvas>

    <div class="detailsRight">
        <canvas class="next" width="160" height="160"></canvas>
        <br>
        <div class="controls">
          <p><i class="fas fa-arrow-left"></i></span> Move Left</p>
          <p><i class="fas fa-arrow-right"></i></span> Move Right</p>
          <p><i class="fas fa-arrow-down"></i></span> Move Down</p>
          <p><i class="fas fa-arrow-up"></i></span> Rotate Right</p>
          <p><span style="font-size : 18px">Q</span> Rotate Left</p>
          <p><span style="font-size : 18px">W</span> Rotate Right</p>
          <p><span style="font-size: 18px">Esc</span> Pause Game</p>
        </div>
      </div>  
			<div class="footer"><p>by <a href="https://github.com/harunpehlivan" target="_blank"><i class="fab fa-github"></i> HARUN PEHLİVAN</a></p></div>
  </div>


  <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-rc.2/js/materialize.min.js"></script>
  <script src="js/main.js"></script>

</body>
</html>

以上是关于html 俄罗斯方块w /高分跟踪的主要内容,如果未能解决你的问题,请参考以下文章

Linux下c语言实现有色界面俄罗斯方块

矩形的碰撞检测(模仿俄罗斯方块)

俄罗斯方块

qt5实现俄罗斯方块(详细注释)

Python_俄罗斯方块

x01.Tetris: 俄罗斯方块