当前位置:   article > 正文

贪吃蛇web小游戏

贪吃蛇web小游戏

蛇的移动:通过定时器实现蛇的自动移动,并通过监听用户的键盘输入来改变蛇的移动方向。

食物的生成:随机在地图上生成食物,并在蛇吃到食物时更新得分和食物的位置。

墙和边界的碰撞判断

        监测蛇是否撞墙(遍历获取墙的位置,检查蛇的边界框是否与当前墙的边界框相交)

        有四种情况:

            蛇的左边界 小于 墙的右边界,蛇在墙的右侧(蛇从右往左撞墙)

            蛇的右边界 大于 墙的左边界,蛇在墙的左侧(蛇从左往右撞墙)

            蛇上边界的 小于 墙的下边界,蛇在墙的上侧(蛇从下往上撞墙)

            蛇下边界的 大于 墙的上边界,蛇在墙的上侧(蛇从上往下撞墙)

完整源代码如下:

  1. // snake.html
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>snake</title>
  8. <style>
  9. * {
  10. margin: 0;
  11. padding: 0;
  12. }
  13. /* 地图 */
  14. .map {
  15. width: 400px;
  16. height: 400px;
  17. background-color: black;
  18. margin: 0 auto;
  19. margin-top: 50px;
  20. position: relative;
  21. }
  22. /**/
  23. .snake {
  24. /* 蛇的宽高 */
  25. width: 20px;
  26. height: 20px;
  27. background-color: red;
  28. /* 确保蛇在地图内 */
  29. position: absolute;
  30. }
  31. /* 食物 */
  32. .food {
  33. /* 食物的宽高 */
  34. width: 20px;
  35. height: 20px;
  36. background-color: green;
  37. /* 确保食物在地图内 */
  38. position: absolute;
  39. }
  40. /* 得分 */
  41. .score {
  42. position: absolute;
  43. bottom: 10px;
  44. /* 距离底部10px */
  45. left: 10px;
  46. /* 距离左侧10px */
  47. color: white;
  48. /* 设置分数颜色为白色 */
  49. }
  50. /**/
  51. .wall1 {
  52. width: 20px;
  53. height: 80px;
  54. background-color: gray;
  55. position: absolute;
  56. top: 40px;
  57. left: 140px;
  58. }
  59. .wall2 {
  60. width: 20px;
  61. height: 80px;
  62. background-color: gray;
  63. position: absolute;
  64. top: 180px;
  65. left: 40px;
  66. }
  67. .wall3 {
  68. width: 140px;
  69. height: 20px;
  70. background-color: gray;
  71. position: absolute;
  72. top: 300px;
  73. left: 140px;
  74. }
  75. .wall4 {
  76. width: 140px;
  77. height: 20px;
  78. background-color: gray;
  79. position: absolute;
  80. top: 200px;
  81. left: 200px;
  82. }
  83. .wall5 {
  84. width: 140px;
  85. height: 20px;
  86. background-color: gray;
  87. position: absolute;
  88. top: 120px;
  89. left: 140px;
  90. }
  91. .wall6 {
  92. width: 20px;
  93. height: 120px;
  94. background-color: gray;
  95. position: absolute;
  96. top: 240px;
  97. left: 120px;
  98. }
  99. </style>
  100. </head>
  101. <body>
  102. <div class="map">
  103. <div class="food"></div>
  104. <div class="snake"></div>
  105. <div class="score">Score: 0</div>
  106. <div class="wall1">1</div>
  107. <div class="wall2">2</div>
  108. <div class="wall3">3</div>
  109. <div class="wall4">4</div>
  110. <div class="wall5">5</div>
  111. <div class="wall6">6</div>
  112. </div>
  113. <script src="./snake.js"></script>
  114. </body>
  115. </html>
  116. <!--
  117. 重点在于:遍历墙数组,检查蛇是否与墙发生碰撞(在snake.js最后)
  118. -->
  1. // snake.js
  2. document.addEventListener('DOMContentLoaded', function () {
  3. // 获取食物,地图,蛇,得分显示,墙
  4. var food = document.querySelector('.food');
  5. var map = document.querySelector('.map');
  6. var snake = document.querySelector('.snake');
  7. var scoredisplay = document.querySelector('.score');
  8. var walls = document.querySelectorAll('.wall1, .wall2, .wall3, .wall4, .wall5, .wall6');
  9. // 声明变量
  10. let snakeX; // 蛇的x坐标
  11. let snakeY; // 蛇的y坐标
  12. let snakeDirection; // 蛇运动方向
  13. let score; // 得分
  14. // 重新开始游戏
  15. function resetGame() {
  16. clearInterval(snakeMoveInterval); // 清除移动定时器
  17. snakeX = 160;
  18. snakeY = 160;
  19. snakeDirection = 'right';
  20. score = 0;
  21. updateScore();
  22. generateFood();
  23. startGame();
  24. }
  25. resetGame();
  26. // 更新分数显示
  27. function updateScore() {
  28. scoredisplay.textContent = '得分: ' + score;
  29. }
  30. // 生成随机位置的食物
  31. var foodX, foodY; // 声明全局变量
  32. function generateFood() {
  33. foodX = Math.floor(Math.random() * (map.offsetWidth / 20)) * 20;
  34. foodY = Math.floor(Math.random() * (map.offsetHeight / 20)) * 20;
  35. //虽然/20*20看似没变化,但实际上,如果删掉了这里,食物的位置不会严丝合缝在“格子”上,而是会有所偏移
  36. food.style.left = foodX + 'px';
  37. food.style.top = foodY + 'px';
  38. food.style.display = 'block'; // 让食物作为一个块级元素显示
  39. // 一定要让食物显示,因为蛇碰到食物后,食物被隐藏了
  40. }
  41. // 定时器,持续地让蛇向当前移动方向移动
  42. var snakeMoveInterval;
  43. // 开始游戏
  44. function startGame() {
  45. snakeMoveInterval = setInterval(function () {
  46. // 根据蛇的移动方向移动蛇的位置
  47. // 左上角是原点,向右是 X 轴正方向,向下是 Y 轴正方向
  48. if (snakeDirection === 'left' && snakeX > 0) {
  49. snakeX -= 20; // 向左移动20px
  50. } else if (snakeDirection === 'up' && snakeY > 0) {
  51. snakeY -= 20; // 向上移动20px
  52. } else if (snakeDirection === 'right' && snakeX < map.offsetWidth - 20) {
  53. snakeX += 20; // 向右移动20px
  54. } else if (snakeDirection === 'down' && snakeY < map.offsetHeight - 20) {
  55. snakeY += 20; // 向下移动20px
  56. } else {
  57. // 蛇撞到了地图边界,游戏失败
  58. var restart = confirm('游戏失败!你的得分是: ' + score + ' 是否重新开始?');
  59. if (restart) {
  60. resetGame();
  61. }
  62. return; // 结束函数
  63. }
  64. // 更新蛇的位置
  65. snake.style.left = snakeX + 'px';
  66. snake.style.top = snakeY + 'px';
  67. // 检查是否吃到了食物
  68. if (snakeX === foodX && snakeY === foodY) {
  69. food.style.display = 'none'; // 食物消失
  70. generateFood(); // 生成新的食物
  71. score += 5; // 增加分数
  72. updateScore(); // 更新分数显示
  73. }
  74. // 检查是否撞墙
  75. if (isSnakeCollidingWithWall(snakeX, snakeY)) {
  76. var restart = confirm('游戏失败!你的得分是: ' + score + ' 是否重新开始?');
  77. if (restart) { // 重新开始
  78. resetGame();
  79. }
  80. return; // 不重新开始,则结束函数
  81. }
  82. }, 500); // 每隔500ms移动一次
  83. }
  84. // 开始游戏
  85. startGame();
  86. // 键盘事件监听器,控制蛇的移动方向
  87. document.addEventListener('keydown', function (event) {
  88. if (event.keyCode === 37 && snakeDirection !== 'right') { // 左箭头键
  89. snakeDirection = 'left';
  90. } else if (event.keyCode === 38 && snakeDirection !== 'down') { // 上箭头键
  91. snakeDirection = 'up';
  92. } else if (event.keyCode === 39 && snakeDirection !== 'left') { // 右箭头键
  93. snakeDirection = 'right';
  94. } else if (event.keyCode === 40 && snakeDirection !== 'up') { // 下箭头键
  95. snakeDirection = 'down';
  96. }
  97. });
  98. // 检查是否撞墙
  99. function isSnakeCollidingWithWall(snakeX, snakeY) {
  100. // 定义蛇的矩形边界框对象,包含蛇头的位置 (x, y) 和蛇的宽度和高度
  101. var snakeRect = {
  102. x: snakeX, // 蛇的横坐标
  103. y: snakeY, // 蛇的纵坐标
  104. width: 20, // 蛇的宽度
  105. height: 20 // 蛇的高度
  106. };
  107. // !!!重点!!!
  108. // 遍历墙数组,检查蛇是否与墙发生碰撞
  109. for (var i = 0; i < walls.length; i++) {
  110. // 获取当前墙
  111. var wall = walls[i];
  112. var wallRect = {
  113. // 墙的位置 (x, y)
  114. x: wall.offsetLeft,
  115. // 墙体元素左侧边缘相对于其最近的定位祖先元素的偏移量,并将其作为墙体的 x 坐标
  116. y: wall.offsetTop,
  117. // 墙体元素顶部边缘相对于其最近的定位祖先元素的偏移量,并将其作为墙体的 y 坐标
  118. // 墙的宽高
  119. width: wall.offsetWidth,
  120. height: wall.offsetHeight
  121. };
  122. // 检查蛇的边界框是否与当前墙的边界框相交
  123. if (snakeRect.x < wallRect.x + wallRect.width &&
  124. snakeRect.x + snakeRect.width > wallRect.x &&
  125. snakeRect.y < wallRect.y + wallRect.height &&
  126. snakeRect.y + snakeRect.height > wallRect.y) {
  127. return true; // 发生碰撞
  128. }
  129. // 蛇的左边界 小于 墙的右边界,蛇在墙的右侧(蛇从右往左撞墙)
  130. // 蛇的右边界 大于 墙的左边界,蛇在墙的左侧(蛇从左往右撞墙)
  131. // 蛇上边界的 小于 墙的下边界,蛇在墙的上侧(蛇从下往上撞墙)
  132. // 蛇下边界的 大于 墙的上边界,蛇在墙的上侧(蛇从上往下撞墙)
  133. }
  134. return false; // 未发生碰撞
  135. }
  136. });

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/436899
推荐阅读
相关标签
  

闽ICP备14008679号