21xrx.com
2025-03-24 05:01:56 Monday
文章检索 我的文章 写文章
Javascript游戏源码分享及实例演练
2023-06-15 17:49:28 深夜i     9     0
Javascript游戏开发 Canvas 游戏源码

近年来Javascript游戏开发越来越热门,大量的游戏工具和框架涌现,吸引了越来越多的游戏爱好者和开发者。本文将分享一些常用的Javascript游戏源码,并结合实例演练,为大家展现Javascript游戏开发的魅力。

1. 翻转拼图游戏源码

这是一款经典的翻转拼图游戏,适合初学者练手,也能培养玩家分析和思考能力。

const game = document.querySelector('#game');
const rows = 4;
const cols = 4;
const pieces = rows * cols;
let empty;
let prevEmpty;
let moves = 0;
const board = Array(rows)
 .fill()
 .map((_, row) =>
  Array(cols)
   .fill()
   .map((_, col) => {
    const piece = row * cols + col + 1;
    const tile = document.createElement('div');
    tile.id = `piece-${piece}`;
    tile.className = 'tile';
    tile.style.backgroundImage = `url('images/nature.jpg')`;
    tile.style.backgroundPosition = `${-col * 100}% ${-row * 100}%`;
    tile.style.top = `${row * 100}px`;
    tile.style.left = `${col * 100}px`;
    tile.dataset.row = row;
    tile.dataset.col = col;
    tile.addEventListener('click', e => movePiece(e.target));
    tile.addEventListener('mousemove', e => swapPrevEmpty(e.target));
    game.appendChild(tile);
    return tile;
   })
 );
board[rows - 1][cols - 1].remove();
function movePiece(tile) {
 const row = tile.dataset;
 const distance = Math.abs(parseInt(row) - empty.row) + Math.abs(parseInt(col) - empty.col);
 if (distance === 1) {
  const tmp = tile.style.top;
  tile.style.top = empty.top;
  empty.top = tmp;
  const tmp2 = tile.style.left;
  tile.style.left = empty.left;
  empty.left = tmp2;
  [empty.row, tile.dataset.row] = [tile.dataset.row, empty.row];
  [empty.col, tile.dataset.col] = [tile.dataset.col, empty.col];
  moves++;
  checkWin();
 }
}
function swapPrevEmpty(tile) {
 const col = tile.dataset;
 const distance = Math.abs(parseInt(row) - empty.row) + Math.abs(parseInt(col) - empty.col);
 if (distance === 1 && tile !== prevEmpty)
  prevEmpty.style.borderStyle = 'solid';
  prevEmpty = tile;
  tile.style.borderStyle = 'dotted';
 
}
function checkWin() {
 const positions = board.flat().map(tile => `${tile.dataset.row},${tile.dataset.col}`).join('|');
 const pattern = new RegExp(`0,0|(${pieces - 1}),(${pieces - 1})|-1`);
 if (positions.match(pattern)) return;
 alert(`Congratulations! You solved the puzzle in ${moves} moves!`);
}
function random(start, end) {
 return Math.floor(Math.random() * (end - start + 1) + start);
}
function shuffle() {
 for (let i = 0; i < pieces - 1; i++) {
  const row = Math.floor(i / cols);
  const col = i % cols;
  const row: emptyRow = empty;
  const distance = Math.abs(row - emptyRow) + Math.abs(col - emptyCol);
  if (distance > 1) continue;
  const piece = document.querySelector(`#piece-${i + 1}`);
  piece.style.top = `${emptyRow * 100}px`;
  piece.style.left = `${emptyCol * 100}px`;
  piece.dataset.row = emptyRow;
  piece.dataset.col = emptyCol;
  [empty.pos, piece.pos] = [piece.pos, empty.pos];
  [empty.row, piece.dataset.row] = [piece.dataset.row, empty.row];
  [empty.col, piece.dataset.col] = [piece.dataset.col, empty.col];
 }
 moves = 0;
 prevEmpty = empty;
}
function newGame() {
 empty = { pos: pieces, row: rows - 1, col: cols - 1, top: `${(rows - 1) * 100}px`, left: `${(cols - 1) * 100}px` };
 shuffle();
}
newGame();

2. 经典飞行射击游戏源码

这是一款经典的飞行射击游戏,使用HTML5 Canvas实现,适合中高级开发者练习。

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
canvas.height = 400;
canvas.width = 800;
const ship =
 height: 20;
const bullets = [];
const enemies = [];
const deaths = [];
class Bullet {
 constructor(x, y)
  this.x = x;
  this.y = y;
  this.height = 5;
  this.width = 5;
  this.speed = 10;
 
 move()
  this.y -= this.speed;
 
}
class Enemy {
 constructor(x, y)
  this.x = x;
  this.y = y;
  this.speed = 4;
  this.height = 20;
  this.width = 40;
 
 move() {
  this.y += this.speed;
 }
}
function fire() {
 const bullet = new Bullet(ship.x + ship.width / 2, ship.y - ship.height / 2);
 bullets.push(bullet);
}
function spawnEnemy() {
 const margin = 50;
 const minWidth = 60;
 const maxWidth = canvas.width - minWidth - margin;
 const x = Math.floor(Math.random() * (maxWidth - minWidth + 1) + minWidth);
 const enemy = new Enemy(x, -20);
 enemies.push(enemy);
}
function detectCollisions() {
 bullets.forEach(bullet => {
  enemies.forEach(enemy => {
   if (
    bullet.x < enemy.x + enemy.width &&
    bullet.x + bullet.width > enemy.x &&
    bullet.y < enemy.y + enemy.height &&
    bullet.y + bullet.height > enemy.y
   ) {
    deaths.push(enemy);
    deaths.push(bullet);
   }
  });
 });
 deaths.forEach(death => {
  enemies.splice(enemies.indexOf(death), 1);
  bullets.splice(bullets.indexOf(death), 1);
 });
 deaths.length = 0;
}
function gameOver() {
 clearInterval(interval);
 ctx.fillStyle = 'black';
 ctx.font = 'bold 64px Arial';
 ctx.fillText('GAME OVER', canvas.width / 2 - 180, canvas.height / 2);
}
function draw() {
 ctx.clearRect(0, 0, canvas.width, canvas.height);
 ctx.fillStyle = 'white';
 ctx.fillRect(ship.x, ship.y, ship.width, ship.height);
 bullets.forEach(bullet => {
  ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
  bullet.move();
 });
 enemies.forEach(enemy => {
  ctx.fillStyle = 'red';
  ctx.fillRect(enemy.x, enemy.y, enemy.width, enemy.height);
  enemy.move();
 });
 if (enemies.length < 10) spawnEnemy();
 detectCollisions();
 if (ship.x + ship.vx >= 0 && ship.x + ship.vx <= canvas.width - ship.width) ship.x += ship.vx;
 requestAnimationFrame(draw);
}
document.addEventListener('keydown', e => {
 if (e.keyCode === 37) ship.vx = -ship.speed;
 if (e.keyCode === 39) ship.vx = ship.speed;
 if (e.keyCode === 32) fire();
});
document.addEventListener('keyup', e => {
 if (e.keyCode === 37 || e.keyCode === 39) ship.vx = 0;
});
let interval = setInterval(function() {
 let direction = 1;
 if (enemies.length > 0) {
  if (enemies[0].y > canvas.height - 60) gameOver();
  enemies.forEach(enemy => {
   if (enemy.x + enemy.width > canvas.width || enemy.x < 0) direction = -1;
   enemy.x += enemy.speed * direction;
  });
 }
}, 1000 / 60);
draw();

3. 伪3D赛车游戏源码

这是一款炫酷的伪3D赛车游戏,使用Canvas动态绘制道路和赛车,适合高级开发者练习。

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
canvas.height = 400;
canvas.width = 800;
const road =
 lanes: 4;
const car = {
 x: road.x + road.width / 2 - 10,
 y: road.height - 20,
 width: 20,
 height: 40,
 speed: 0,
 rotation: 0,
 maxSpeed: 8,
 minSpeed: -4,
 acceleration: 0.2,
 braking: 0.5,
 steerAngle: 0.1,
 steerLimit: 0.15
};
const coefs =
 curve: 0.5;
let trackLength = 2000;
let segments = [];
for (let i = 0; i < trackLength; i++) {
 let segment = {
  x: 0,
  y: 0,
  z: i * road.width / trackLength,
  curve: 0,
  hill: 0
 };
 if (i % 9 === 0) segment.curve = random(-1, 2);
 if (i % 18 === 0) segment.hill = random(-1, 2);
 segments.push(segment);
}
function random(start, end) {
 return Math.floor(Math.random() * (end - start + 1) + start);
}
function updateSpeed() {
 if (car.speed < car.maxSpeed && car.acceleration > 0) car.speed += car.acceleration;
 if (car.speed > car.minSpeed && car.acceleration < 0) car.speed += car.acceleration;
 if (car.speed > 0 && car.braking > 0) car.speed -= car.braking;
 if (car.speed < 0 && car.braking < 0) car.speed -= car.braking;
 if (Math.abs(car.speed) < 0.1) car.speed = 0;
}
function updatePosition() {
 let segmentIndex = Math.floor(car.y / road.laneWidth) % segments.length;
 let currentSegment = segments[segmentIndex];
 let nextSegment = segments[(segmentIndex + 1) % segments.length];
 let distance = currentSegment.z + car.speed;
 let height = interpolate(currentSegment.hill, nextSegment.hill, distance, road.length);
 let curve = interpolate(currentSegment.curve, nextSegment.curve, distance, road.length);
 let x = road.x + curve;
 let y = car.y + car.speed;
 let rotation = car.steerAngle * car.speed * curve * 100;
 car.x = x - rotation;
 car.rotation = rotation;
 car.y = y;
}
function interpolate(a, b, distance, roadLength) {
 let result = a + (b - a) * distance / roadLength;
 return result;
}
function newSegment(segment) {
 if (segment.z < -road.width) {
  let index = segments.indexOf(segment);
  let count = segments.length - index;
  let slope = random(1, 4) === 1 ? random(1, 3) * 1.5 : 0;
  let curve = random(-1, 2);
  let hill = random(-1, 3);
  for (let i = 0; i < count; i++) {
   segments.push({
    x: 0,
    y: 0,
    z: segments.length * road.width / trackLength,
    slope: slope,
    curve: curve,
    hill: hill
   });
  }
  trackLength += count;
  segments.splice(0, count);
 }
}
function draw() {
 ctx.clearRect(0, 0, canvas.width, canvas.height);
 updateSpeed();
 updatePosition();
 for (let i = 0; i < segments.length; i++) {
  let segment = segments[i];
  segment.x = road.x + segment.curve;
  segment.y = i * road.laneWidth - car.y % road.laneWidth + height;
  segment.height = road.laneWidth;
  segment.width = road.width;
  segment.color = i % 2 === 0 ? 'lightgray' : 'darkgray';
  newSegment(segment);
  drawSegment(segment);
 }
 drawCar();
 requestAnimationFrame(draw);
}
function drawSegment(segment) {
 ctx.fillStyle = segment.color;
 ctx.fillRect(segment.x, segment.y, segment.width, segment.height);
}
function drawCar() {
 ctx.fillStyle = 'red';
 ctx.translate(car.x + car.width / 2, car.y + car.height / 2);
 ctx.rotate(car.rotation);
 ctx.fillRect(-car.width / 2, -car.height / 2, car.width, car.height);
 ctx.rotate(-car.rotation);
 ctx.translate(-car.x - car.width / 2, -car.y - car.height / 2);
}
document.addEventListener('keydown', e => {
 if (e.keyCode === 38)
  car.acceleration = 0.2;
  car.braking = 0;
 
 if (e.keyCode === 40)
  car.braking = 0.2;
  car.acceleration = 0;
 
 if (e.keyCode === 37) car.steerAngle = -car.steerLimit;
 if (e.keyCode === 39) car.steerAngle = car.steerLimit;
});
document.addEventListener('keyup', e => {
 if (e.keyCode === 38)
  car.acceleration = 0;
  car.braking = 0.05;
 
 if (e.keyCode === 40)
  car.braking = 0;
  car.acceleration = -0.1;
 
 if (e.keyCode === 37 || e.keyCode === 39) car.steerAngle = 0;
});
draw();

  
  

评论区

    相似文章