迷宫
效果图:
序幕:
迷宫渲染:定义一个二维数组、根据定义二维数组中的数字来标识不同的东西(障碍物、人物、终点、草地),然后两重循环将其渲染到页面
移动人物:给人物定义position: relative;,然后根据left,bottom来移动
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>幼儿迷宫</title>
</head>
<style>
table {
border-collapse: collapse;
padding: 0;
background: url("./gass.jpg");
width: 64%;
height: 100%;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
}
td {
width: 80px;
height: 80px;
}
tr {
display: block;
margin: -5px;
}
</style>
<body onload="init()" onkeypress="keypress(event)">
<table id="map">
</table>
<script>
var empty = 0; //空地或草坪
var stone = 1; //石头的标记是1
var panda = 9; //熊猫的标记是9
var point = 6; //终点
var stepNumber = 0 //步数
var mapData = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 6, 1],
[1, 0, 0, 0, 1, 0, 1, 0, 1, 1],
[1, 1, 1, 1, 1, 0, 1, 0, 0, 1],
[1, 1, 1, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 1, 1, 1, 1, 0, 1],
[1, 0, 1, 1, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 1, 1, 1, 0, 1, 0, 1],
[1, 1, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]
var initPoint = [1, 1]; //初始化熊猫的位置
var row = mapData.length; //地图的行
var column = mapData[0].length; //地图的列
function init() {
//二维数组里,去初始化熊猫的位置
mapData[initPoint[0]][initPoint[1]] = panda
loadData(mapData);
}
/**
* 渲染地图
*/
function loadData(mapData) {
// 获取地图对象
var map = document.getElementById("map");
//渲染一行八列的数据
var mapHTML = "";
for (var i = 0; i < row; i++) {
mapHTML += "<tr>";
for (var j = 0; j < column; j++) {
if (mapData[i][j] == 0) {
mapHTML += "<td></td>";
} else if (mapData[i][j] == 1) {
mapHTML += '<td><img src="./qualityControl.png" style="height: 80px; height: 80px; border-radius: 50%;" ></td>';
} else if (mapData[i][j] == 9) {
mapHTML += '<td><img src="./location.png" id="panda" style="height: 80px; height: 80px; border-radius: 50%;position: relative;" ></td>';
}else if (mapData[i][j] == 6) {
mapHTML += '<td><img src="./endPoint.png" id="panda" style="height: 80px; height: 80px; border-radius: 50%;position: relative;" ></td>';
}
}
mapHTML += "</tr>";
}
map.innerHTML = mapHTML;
}
/**
* 障碍检测(可加多个障碍条件)
* @param yPoint
* @param xPoint
* @returns {boolean}
*/
function checkStone(yPoint, xPoint) {
return mapData[yPoint][xPoint] == stone;
}
// 移动方法
function move(keynum, Value) {
stepNumber++
var pandaPos = document.getElementById("panda")
if (119 == keynum) {
const result = Value + 80;
pandaPos.style.bottom = result + "px";
} else if (100 == keynum) {
const result = Value + 80;
pandaPos.style.left = result + "px";
} else if (115 == keynum) {
const result = Value - 80;
pandaPos.style.bottom = result + "px";
} else if (97 == keynum) {
const result = Value - 80;
pandaPos.style.left = result + "px";
}
}
/**
* 监听wasd按键事件:w(上) s(下) a(左) d(右)
* @param e
*/
var keypress = function keypress(e) {
var pandaPos = document.getElementById("panda")
var keynum = window.event ? e.keyCode : e.which;
if (119 == keynum) {
var point = initPoint;
if (point[0] < row - 1) {
var xPoint = initPoint[1];
var yPoint = initPoint[0] - 1;
if (checkStone(yPoint, xPoint)) {
console.log("碰撞到石头了,停止动作")
return
}
// console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint)
initPoint = [yPoint, xPoint]
// operatePanda(point);
const style = window.getComputedStyle(pandaPos);
const ValueStr = style.bottom;
const Value = parseInt(ValueStr, 10);
move(119, Value)
console.log("向上")
} else {
console.log("超出地图范围了,停止动作")
}
} else if (97 == keynum) {
var point = initPoint;
if (point[1] > 0) {
var xPoint = initPoint[1] - 1;
var yPoint = initPoint[0];
if (checkStone(yPoint, xPoint)) {
console.log("碰撞到石头了,停止动作")
return
}
// console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint)
initPoint = [yPoint, xPoint]
// operatePanda(point);
const style = window.getComputedStyle(pandaPos);
const ValueStr = style.left;
const Value = parseInt(ValueStr, 10);
move(97, Value)
console.log("向左")
} else {
console.log("超出地图范围了,停止动作")
}
} else if (115 == keynum) {
var point = initPoint;
if (point[0] < row - 1) {
var xPoint = initPoint[1];
var yPoint = initPoint[0] + 1;
if (checkStone(yPoint, xPoint)) {
console.log("碰撞到石头了,停止动作")
return
}
// console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint)
initPoint = [yPoint, xPoint]
// operatePanda(point);
const style = window.getComputedStyle(pandaPos);
const ValueStr = style.bottom;
const Value = parseInt(ValueStr, 10);
move(115, Value)
console.log("向下")
} else {
console.log("超出地图范围了,停止动作")
}
} else if (100 == keynum) {
var point = initPoint;
if (point[1] < column - 1) {
var xPoint = initPoint[1] + 1;
var yPoint = initPoint[0];
if (checkStone(yPoint, xPoint)) {
console.log("碰撞到石头了,停止动作")
return
}
// console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint)
initPoint = [yPoint, xPoint]
// operatePanda(point);
const style = window.getComputedStyle(pandaPos);
const ValueStr = style.left;
const Value = parseInt(ValueStr, 10);
move(100, Value)
console.log("向右")
} else {
console.log("超出地图范围了,停止动作")
}
}
// console.log(initPoint)
if(initPoint[0] == 1 && initPoint[1] == 8){
console.log(`总共${stepNumber},到达终点`)
}
}
</script>
</body>
</html>
迷宫2.0
在上面用js开发固定迷宫时就想,这样的死迷宫不能称之为迷宫,如何让这个迷宫动起来呢?
让浏览器每次刷新时,通过计算重新生成一个迷宫,但这样有个问题,每次动态生成的迷宫必须保证它是通路的,通过思考以及借鉴,决定使用深度优先算法来实现
保证渲染迷宫为通路后,然后将其中一个固定为终点,随机初始化一点为起点,这样说可能比较难懂放上一张图,接着描述
实现:
首先定义一个二维数组,初始化全都为1,然后随机一个位置作为初始通路,设置为0,效果如下:
然后通过上下左右加减一,来判断下一步的四周边是什么情况(是通路还是墙壁)。如果加减一的下一步在二维数组范围内且位置是墙壁,我们就再来一次上下左右加减下一步,再次了解下下一步四周的情况,如果四周有且只有一条通路,就可以将这个点设置为通路,意思如下如:
因为是递归循环,如果碰到墙壁无法走通时,某一循环就结束,继续某一循环的上一级循环开始
代码大致如下:
// 深度优先搜索算法
function generatePath(maze, row, col) {
const directions = [[-1, 0], [0, 1], [1, 0], [0, -1]]; // 上、右、下、左
// 解构赋值,遍历随机化后的方向数组
for (const [dx, dy] of directions) {
const newRow = row + dx; // 计算新位置的行号
const newCol = col + dy; // 计算新位置的列号
// 检查新位置是否在迷宫范围内且为墙壁
if (
newRow >= 0 && newRow < maze.length &&
newCol >= 0 && newCol < maze[0].length &&
maze[newRow][newCol] === 1
) {
// 检查新位置的上、下、左、右四个方向的邻居是否是通路
let count = 0; // 记录有多少个邻居是通路
for (const [dirX, dirY] of directions) {
const neighborRow = newRow + dirX; // 计算邻居位置的行号
const neighborCol = newCol + dirY; // 计算邻居位置的列号
// 检查邻居是否在迷宫范围内且为通路
if (
neighborRow >= 0 && neighborRow < maze.length &&
neighborCol >= 0 && neighborCol < maze[0].length &&
maze[neighborRow][neighborCol] === 0
) {
count++; // 如果是通路,计数加一
}
}
// 如果有且仅有一个邻居是通路,则将新位置设为通路
if (count === 1) {
// console.log(newRow,newCol)
maze[newRow][newCol] = 0; // 将新位置设为通路
generatePath(maze, newRow, newCol); // 递归调用生成路径,继续向新位置探索
}
}
}
}
但是directions = [[-1, 0], [0, 1], [1, 0], [0, -1]]规定死的,这样生成的迷宫大致图形就相差不大,如果每次递归时,将这个数据打乱,效果就很棒了,如下代码:
// 洗牌算法
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
2.0完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>幼儿迷宫</title>
</head>
<style>
body {
padding: 0;
margin: 0;
}
table {
border-collapse: collapse;
padding: 0;
background: url("./gass.jpg");
height: 100%;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
}
td {
display: inline-block;
padding: 0;
width: 80px;
height: 80px;
}
tr {
display: block;
}
</style>
<body onload="init()" onkeypress="keypress(event)">
<table id="map">
</table>
<script>
var initPoint = null
// var mapPoint = null
function generateMaze(rows, cols) {
// 创建一个空的二维数组
const maze = [];
for (let i = 0; i < rows; i++) {
maze[i] = [];
for (let j = 0; j < cols; j++) {
maze[i][j] = 1; // 初始化为墙壁(1)
}
}
// 随机选择一个起始位置
const startRow = Math.floor(Math.random() * rows);
const startCol = Math.floor(Math.random() * cols);
maze[startRow][startCol] = 0; // 起始位置设为通路(0)
initPoint = [startRow, startCol]
// 使用递归函数来生成迷宫
generatePath(maze, startRow, startCol);
return maze;
}
// 深度优先搜索算法
function generatePath(maze, row, col) {
const directions = [[-1, 0], [0, 1], [1, 0], [0, -1]]; // 上、右、下、左
shuffleArray(directions)
// 解构赋值,遍历随机化后的方向数组
for (const [dx, dy] of directions) {
const newRow = row + dx; // 计算新位置的行号
const newCol = col + dy; // 计算新位置的列号
// 检查新位置是否在迷宫范围内且为墙壁
if (
newRow >= 0 && newRow < maze.length &&
newCol >= 0 && newCol < maze[0].length &&
maze[newRow][newCol] === 1
) {
// 检查新位置的上、下、左、右四个方向的邻居是否是通路
let count = 0; // 记录有多少个邻居是通路
for (const [dirX, dirY] of directions) {
const neighborRow = newRow + dirX; // 计算邻居位置的行号
const neighborCol = newCol + dirY; // 计算邻居位置的列号
// 检查邻居是否在迷宫范围内且为通路
if (
neighborRow >= 0 && neighborRow < maze.length &&
neighborCol >= 0 && neighborCol < maze[0].length &&
maze[neighborRow][neighborCol] === 0
) {
count++; // 如果是通路,计数加一
}
}
// 如果有且仅有一个邻居是通路,则将新位置设为通路
if (count === 1) {
// console.log(newRow,newCol)
maze[newRow][newCol] = 0; // 将新位置设为通路
generatePath(maze, newRow, newCol); // 递归调用生成路径,继续向新位置探索
}
}
}
}
// 洗牌算法
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
// 使用示例
const rows = 10;
const cols = 10;
const maze = generateMaze(rows, cols);
var empty = 0; //空地或草坪
var stone = 1; //石头的标记是1
var panda = 8; //熊猫的标记是9
var point = 6; //终点
var stepNumber = 0 //步数
var mapData = maze
var mapPoint = [9, 9]; //初始化终点的位置
var row = mapData.length; //地图的行
var column = mapData[0].length; //地图的列
function init() {
//二维数组里,去初始化熊猫的位置
mapData[initPoint[0]][initPoint[1]] = panda
mapData[mapPoint[0]][mapPoint[1]] = point
loadData(mapData);
}
/**
* 渲染地图
*/
function loadData(mapData) {
// 获取地图对象
var map = document.getElementById("map");
//渲染一行八列的数据
var mapHTML = "";
for (var i = 0; i < row; i++) {
mapHTML += "<tr>";
for (var j = 0; j < column; j++) {
if (mapData[i][j] == 0) {
mapHTML += "<td></td>";
} else if (mapData[i][j] == 1) {
mapHTML += '<td><img src="./qualityControl.png" style="height: 80px; height: 80px; border-radius: 50%;" ></td>';
} else if (mapData[i][j] == 8) {
mapHTML += '<td><img src="./location.png" id="panda" style="height: 80px; height: 80px; border-radius: 50%;position: relative;" ></td>';
} else if (mapData[i][j] == 6) {
mapHTML += '<td><img src="./endPoint.png" id="panda" style="height: 80px; height: 80px; border-radius: 50%;position: relative;" ></td>';
}
}
mapHTML += "</tr>";
}
map.innerHTML = mapHTML;
}
/**
* 障碍检测(可加多个障碍条件)
* @param yPoint
* @param xPoint
* @returns {boolean}
*/
function checkStone(yPoint, xPoint) {
if (yPoint < 0 || xPoint < 0 || yPoint >= mapData.length || xPoint >= mapData[0].length) {
return 2
} else if (mapData[yPoint][xPoint] == stone) {
return 1
}
}
// 移动方法
function move(keynum, Value) {
stepNumber++
var pandaPos = document.getElementById("panda")
if (119 == keynum) {
const result = Value + 80;
pandaPos.style.bottom = result + "px";
} else if (100 == keynum) {
const result = Value + 80;
pandaPos.style.left = result + "px";
} else if (115 == keynum) {
const result = Value - 80;
pandaPos.style.bottom = result + "px";
} else if (97 == keynum) {
const result = Value - 80;
pandaPos.style.left = result + "px";
}
}
/**
* 监听wasd按键事件:w(上) s(下) a(左) d(右)
* @param e
*/
var keypress = function keypress(e) {
var pandaPos = document.getElementById("panda")
var keynum = window.event ? e.keyCode : e.which;
if (119 == keynum) {
var point = initPoint;
if (point[0] < row) {
var xPoint = initPoint[1];
var yPoint = initPoint[0] - 1;
if (checkStone(yPoint, xPoint) == 1) {
console.log("碰撞到石头了,停止动作")
return
} else if (checkStone(yPoint, xPoint) == 2) {
console.log("超出边界了,停止动作")
return
}
initPoint = [yPoint, xPoint]
const style = window.getComputedStyle(pandaPos);
const ValueStr = style.bottom;
const Value = parseInt(ValueStr, 10);
move(119, Value)
console.log("向上")
} else {
console.log("超出地图范围了,停止动作")
}
} else if (97 == keynum) {
var point = initPoint;
if (point[1] > 0) {
var xPoint = initPoint[1] - 1;
var yPoint = initPoint[0];
if (checkStone(yPoint, xPoint) == 1) {
console.log("碰撞到石头了,停止动作")
return
} else if (checkStone(yPoint, xPoint) == 2) {
console.log("超出边界了,停止动作")
return
}
initPoint = [yPoint, xPoint]
const style = window.getComputedStyle(pandaPos);
const ValueStr = style.left;
const Value = parseInt(ValueStr, 10);
move(97, Value)
console.log("向左")
} else {
console.log("超出地图范围了,停止动作")
}
} else if (115 == keynum) {
var point = initPoint;
if (point[0] < row) {
var xPoint = initPoint[1];
var yPoint = initPoint[0] + 1;
if (checkStone(yPoint, xPoint) == 1) {
console.log("碰撞到石头了,停止动作")
return
} else if (checkStone(yPoint, xPoint) == 2) {
console.log("超出边界了,停止动作")
return
}
initPoint = [yPoint, xPoint]
const style = window.getComputedStyle(pandaPos);
const ValueStr = style.bottom;
const Value = parseInt(ValueStr, 10);
move(115, Value)
console.log("向下")
} else {
console.log("超出地图范围了,停止动作")
}
} else if (100 == keynum) {
var point = initPoint;
if (point[1] < column - 1) {
var xPoint = initPoint[1] + 1;
var yPoint = initPoint[0];
if (checkStone(yPoint, xPoint) == 1) {
console.log("碰撞到石头了,停止动作")
return
} else if (checkStone(yPoint, xPoint) == 2) {
console.log("超出边界了,停止动作")
return
}
initPoint = [yPoint, xPoint]
const style = window.getComputedStyle(pandaPos);
const ValueStr = style.left;
const Value = parseInt(ValueStr, 10);
move(100, Value)
console.log("向右")
} else {
console.log("超出地图范围了,停止动作")
}
}
if (initPoint[0] == 9 && initPoint[1] == 9) {
console.log()
alert(`总共${stepNumber},到达终点`);
location.reload();
}
}
</script>
</body>
</html>
上述如何表达错误或者不明白的,可以评论留言一起讨论
飞机大战
技能:
html js css
需求:
我军飞机左右移动,并且按空格 可以发射炮弹,敌方飞机从上往下飞,接触到我方炮弹 飞机被歼灭,我军接触到敌军飞机也将会被歼灭,我方飞机吃到道具可以增加弹道
思路:
初始化:初始创建我方飞机,用定时器定时创建敌方飞机,敌方飞机位置由random()随机生成
移动:飞机样式使用position: absolute,然后监听键盘被按事件 用left位置来移动我方飞机,敌军飞机也有定时器 定时向下移动
发射炮弹:创建炮弹跟创建敌军类似,区别是炮弹的位置是根据我方飞机的位置进行初始化的,而敌军飞机位置是随机的
敌军歼灭:通过getBoundingClientRect()获取位置信息 来判断是否接触到;我军歼灭类似
能量小球:产生小球跟敌军类似,休改下样式就好了
效果图:
全部代码:
<!DOCTYPE html>
<html>
<head>
<title>飞机大战</title>
<style>
html,
body {
margin: 0;
padding: 0;
}
/* 游戏边框 */
.game-board {
width: 400px;
height: 600px;
border: 1px solid black;
position: relative;
overflow: hidden;
}
/* 我方飞机 */
.player {
width: 50px;
height: 50px;
background-color: blue;
position: absolute;
bottom: 0;
}
/* 敌方飞机 */
.enemy {
width: 30px;
height: 30px;
background-color: red;
position: absolute;
top: 0;
}
/* 子弹 */
.bullet {
width: 2px;
height: 10px;
background-color: black;
position: absolute;
}
/* 分数 */
.score {
font-size: 18px;
position: absolute;
top: 10px;
right: 10px;
}
/* 能量小球 */
.power-up {
width: 20px;
height: 20px;
background-color: green;
position: absolute;
}
</style>
</head>
<body>
<div class="game-board" id="game-board">
<div class="score">分数: <span id="score">0</span></div>
</div>
<script>
const gameBoard = document.getElementById('game-board');
// 创建我方飞机
const player = document.createElement('div');
// 我军飞机初始位置
let playerLeft = 175;
player.style.left = `${playerLeft}px`;
// 游戏是否结束
let isGameOver = false;
// 是否在发射子弹的状态
let isShooting = false;
// 初始化分数
let score = 0;
const scoreElement = document.getElementById('score');
// 初始化我军飞机样式
player.classList.add('player');
gameBoard.appendChild(player);
// 创造敌军飞机
function createEnemy() {
const enemy = document.createElement('div');
// 随机位置
let enemyLeft = Math.floor(Math.random() * 350);
enemy.classList.add('enemy');
enemy.style.left = `${enemyLeft}px`;
gameBoard.appendChild(enemy);
moveEnemy(enemy);
}
// 每30ms敌军就会向下移动五像素,如果到达边界就会取消移动 并且移除样式
function moveEnemy(enemy) {
let enemyTop = 0;
let enemyInterval = setInterval(() => {
if (enemyTop > 600 || isGameOver) {
clearInterval(enemyInterval);
// 出界 清除dom
gameBoard.removeChild(enemy);
}
enemy.style.top = `${enemyTop}px`;
enemyTop += 5;
// 如果两个接触到 就结束游戏
if (checkCollision(player, enemy)) {
gameOver();
}
}, 30);
}
// 创建能量小球
function createPowerUp() {
const powerUp = document.createElement('div');
// 随机水平位置
let powerUpLeft = Math.floor(Math.random() * 350);
powerUp.classList.add('power-up');
powerUp.style.left = `${powerUpLeft}px`;
gameBoard.appendChild(powerUp);
movePowerUp(powerUp);
}
// 移动绿色小球
// 每30ms绿色小球就会向下移动五像素,如果到达边界就会取消移动 并且移除样式
function movePowerUp(powerUp) {
let powerUpTop = 0;
let powerUpInterval = setInterval(() => {
if (powerUpTop > 600 || isGameOver) {
clearInterval(powerUpInterval);
// 出界 清除dom
gameBoard.removeChild(powerUp);
}
powerUp.style.top = `${powerUpTop}px`;
powerUpTop += 5;
// 我方飞机吃到绿色小球
if (checkCollision(player, powerUp)) {
gameBoard.removeChild(powerUp);
powerUpEffect();
}
}, 30);
}
let isDoubleBullet = false;
let numBullets = 1;
// 新增函数,处理绿色小球效果
function powerUpEffect() {
isDoubleBullet = true;
numBullets++;
}
// 创造子弹
function createBullet(left, bottom) {
// console.log(left, bottom)
const bullet = document.createElement('div');
bullet.classList.add('bullet');
bullet.style.left = `${left + 25}px`;
bullet.style.bottom = `50px`;
gameBoard.appendChild(bullet);
moveBullet(bullet);
}
// 子弹移动
function moveBullet(bullet) {
let bulletBottom = 50;
let bulletInterval = setInterval(() => {
if (bulletBottom > 600 || isGameOver) {
clearInterval(bulletInterval);
gameBoard.removeChild(bullet);
}
bullet.style.bottom = `${bulletBottom}px`;
bulletBottom += 10;
const enemies = document.querySelectorAll('.enemy');
// 判断子弹是否接触到敌军飞机
enemies.forEach(enemy => {
if (checkCollision(bullet, enemy)) {
clearInterval(bulletInterval);
gameBoard.removeChild(bullet);
gameBoard.removeChild(enemy);
increaseScore();
}
});
}, 30);
}
// 检测是否接触
function checkCollision(a, b) {
// getBoundingClientRect()是一个DOM元素对象的方法,用于获取该元素相对于视口(viewport)的位置和尺寸信息
// 从而进行碰撞检测、位置计算等操作
const aRect = a.getBoundingClientRect();
const bRect = b.getBoundingClientRect();
return !(
// 我军飞机的top如果小于敌军的bottom 说明已经两机已经接触了
aRect.top > bRect.bottom ||
aRect.bottom < bRect.top ||
aRect.right < bRect.left ||
aRect.left > bRect.right
);
}
// 游戏结束
function gameOver() {
isGameOver = true;
// 移除gameBoard元素的所有子元素,即清空游戏面板
while (gameBoard.firstChild) {
gameBoard.removeChild(gameBoard.firstChild);
}
// 停止创造敌军飞机
clearInterval(enemyInterval)
gameBoard.innerHTML = '游戏结束!最终分数为: ' + score;
}
// 分数增加
function increaseScore() {
score++;
scoreElement.textContent = score;
if (score % 8 === 0) { // 每射杀十个敌方飞机,创建绿色小球
createPowerUp();
}
}
document.addEventListener('keydown', function (event) {
// 空格键
if (event.keyCode === 32 && !isGameOver) {
// 发射与停止发射子弹
if (!isShooting) {
isShooting = true;
shoot();
}
} else if (event.keyCode === 37) { // 左箭头键
if (playerLeft > 0) playerLeft -= 10;
} else if (event.keyCode === 39) { // 右箭头键
if (playerLeft < 350) playerLeft += 10;
}
player.style.left = playerLeft + 'px';
});
// 控制发射子弹
function shoot() {
if (isShooting) {
const plane = document.querySelector('.player');
const planeLeft = parseInt(plane.style.left);
const planeBottom = parseInt(plane.style.bottom);
console.log(plane.style.left)
// 增加子弹
for (let i = 0; i < numBullets; i++) {
if (isDoubleBullet) {
createBullet(planeLeft - 5 + 10 * i , planeBottom);
} else {
createBullet(planeLeft, planeBottom);
}
}
// 设置发射子弹的频率,这里是每隔200毫秒发射一颗子弹
setTimeout(shoot, 200);
}
}
document.addEventListener('keyup', function (event) {
if (event.keyCode === 32) { // 当松开空格键时,关闭发射状态
isShooting = false;
}
});
let enemyInterval = setInterval(createEnemy, 1000); // 每隔1秒创建一个敌方飞机
</script>
</body>
</html>
有其他问题 欢迎大家评论留言
贪吃蛇
效果图:
完整代码展示:
index.html
<!DOCTYPE html>
<html>
<head>
<title>贪吃蛇游戏</title>
<style>
#game-board {
width: 400px;
height: 400px;
border: 1px solid #000;
position: relative;
}
.snake-dot,
.food-dot {
width: 20px;
height: 20px;
background-color: #000;
position: absolute;
}
.food-dot {
background-color: red;
}
</style>
</head>
<body>
<div id="score">得分: 0</div>
<div id="game-board"></div>
<script src="./js/snake.js"></script>
</body>
</html>
snake.js
// 游戏设置
var tileSize = 20; // 单个方块的大小
var initialSpeed = 200; // 初始速度(毫秒)
var speedMultiplier = 1; // 加速倍数
var direction = "right"; // 初始方向
// 初始化贪吃蛇
var snake = [
{ top: 0, left: 0 },
];
// 当前食物的位置
var food = {};
// 游戏循环计时器
var gameLoop;
// 游戏是否结束
var gameOver = false;
// 游戏板元素
var gameBoard = document.getElementById("game-board");
// 监听方向键按下事件
document.addEventListener("keydown", function (event) {
if (event.key === "ArrowUp" && direction !== "down") {
direction = "up";
} else if (event.key === "ArrowDown" && direction !== "up") {
direction = "down";
} else if (event.key === "ArrowLeft" && direction !== "right") {
direction = "left";
} else if (event.key === "ArrowRight" && direction !== "left") {
direction = "right";
}
});
// 开始游戏
function startGame() {
createFood();
document.getElementById("score").innerText = "得分: " + (snake.length - 1);
gameLoop = setInterval(moveSnake, initialSpeed);
}
// 创建食物
function createFood() {
// 随机食物的位置
// gameBoard.offsetHeight 规定的宽高
var top = Math.floor(Math.random() * (gameBoard.offsetHeight / tileSize)) * tileSize;
var left = Math.floor(Math.random() * (gameBoard.offsetWidth / tileSize)) * tileSize;
food = { top: top, left: left };
// 创建
var foodElement = document.createElement("div");
foodElement.className = "food-dot";
foodElement.style.top = food.top + "px";
foodElement.style.left = food.left + "px";
gameBoard.appendChild(foodElement);
}
// 移动贪吃蛇
function moveSnake() {
// Object.assign() 用于将一个或多个源对象的属性复制到目标对象中
var head = Object.assign({}, snake[0]);
// 移动,通过定时器移动
if (direction === "up") {
head.top -= tileSize;
} else if (direction === "down") {
head.top += tileSize;
} else if (direction === "left") {
head.left -= tileSize;
} else if (direction === "right") {
head.left += tileSize;
}
if (checkCollision(head)) {
gameOver = true;
clearInterval(gameLoop);
if (gameOver) {
var restart = confirm("游戏结束!你的分数为:" + (snake.length - 1) + "。是否重新开始?");
if (restart) {
snake = [
{ top: 0, left: 0 }
];
direction = "right";
initialSpeed = 200;
gameOver = false;
// 清除食物
let foodElement = document.querySelector(".food-dot");
gameBoard.removeChild(foodElement);
startGame()
return
}
}
}
//元素插入到数组的开头
snake.unshift(head);
if (head.top === food.top && head.left === food.left) {
// 删除已经被吃掉的食物
var foodElement = document.querySelector(".food-dot");
gameBoard.removeChild(foodElement);
// 创建新的食物
createFood();
} else {
// 移除数组的最后一个元素
snake.pop();
}
updateSnake();
}
// 更新贪吃蛇的显示
function updateSnake() {
// 清除之前的位置
var snakeDots = document.getElementsByClassName("snake-dot");
while (snakeDots.length > 0) {
snakeDots[0].parentNode.removeChild(snakeDots[0]);
}
// 绘制当前位置
for (var i = 0; i < snake.length; i++) {
var snakeElement = document.createElement("div");
snakeElement.className = "snake-dot";
snakeElement.style.top = snake[i].top + "px";
snakeElement.style.left = snake[i].left + "px";
gameBoard.appendChild(snakeElement);
}
document.getElementById("score").innerText = "得分: " + (snake.length - 1);
}
// 检查是否与边界或自身碰撞
function checkCollision(position) {
// 是否与边界碰撞
if (
position.top < 0 ||
position.top >= gameBoard.offsetHeight ||
position.left < 0 ||
position.left >= gameBoard.offsetWidth
) {
return true;
}
// 自身碰撞
for (var i = 1; i < snake.length; i++) {
if (position.top === snake[i].top && position.left === snake[i].left) {
return true;
}
}
return false;
}
// 启动游戏
startGame();