html游戏源码|HTML5超级玛丽简易版(有源码)

在线体验地址(电脑键盘控制):超级玛丽简易版游戏体验
更多html游戏源码可以看我的专栏:html游戏源码

目录

  • 如何使用
  • 效果
  • 完整源码

如何使用 文章末尾是该游戏的完整代码(基于html+css+js),没学过前端或者没有编辑器的朋友不要着急,只要有电脑就可以完整运行此项目。
【html游戏源码|HTML5超级玛丽简易版(有源码)】步骤:首先在桌面新建一个文本文档(txt文件),然后把完整代码复制进去,保存并关闭。接着把文件的后缀改为html,双击即可看到游戏界面(如果看不到效果,说明没有修改后缀成功)。
不会修改文件后缀或者文件显示不了后缀的朋友可以看看教程:https://www.windowszj.com/news/4884.html
界面出现中文乱码的可以看看如何解决:https://zhuanlan.zhihu.com/p/149128500
效果 html游戏源码|HTML5超级玛丽简易版(有源码)
文章图片

使用键盘上下左右控制,一共三条命。
完整源码
超级玛丽简易版 type="text/css"> *body{margin:0 auto; } #status{ position: absolute; left: 50%; top: 170px; margin-left: 60px; } .background { background: rgb(52, 166, 251); table-layout: fixed; border-spacing: 0; } .background td { padding: 0; } .lava { background: rgb(255, 100, 100); } .wall { background: white; } .actor { position: absolute; } .coin { background: rgb(241, 229, 89); } .player { background: rgb(64, 64, 64); } .lost .player { background: rgb(160, 64, 64); } .won .player { box-shadow: -4px -7px 8px white, 4px -7px 8px white; } .game { overflow: hidden; max-width: 600px; max-height: 450px; position: relative; }
How many lives you have left: id="lives">
type="text/javascript">/* Based on Dark Blue by Thomas Palef.Plans are submitted as an array of strings that forms a grid.@ = Player start position o = Coins x = Solid surfaces ! = Non-moving lava = = Vertical moving lava v = Dripping lava | = Horizontal moving lava*/ var simpleLevelPlan = [ "", "", "x= x", "xo ox", "x @xxxxxx", "xxxxxx", "x!!!!!!!!!!!!x", "xxxxxxxxxxxxxx", "" ]; var GAME_LEVELS = [ ["", "", "", "", "", "", "xxx", "xxxxxx!xx", "o oxxx!!!x", "xx!xx", "xxxxxxxx", "xx", "xxo ox", "xox", "xxxxxxo x", "xxxxxox", "x@xxxxxxxx", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "xxxx", "x!!!xxooooox", "xoooxxooooox", "xxxxxxxxxxxx", "", ""], ["x!!xxxxxxxxx!x", "x!!xxxxxxxxxx!x", "x!!xxxxxxxxxxxxxxx!x", "xx!!!!!!!!!!xxxxxxx!x", "xxxxxxxxxx!!xxooox!x", "xx!xxooxx!x", "x!xxxxxxxxxxxxxxxxx!!x", "xvxxxx!!!!!!!!!!!!!!xx", "xx|||xxxxxxxxxxxxxxxxxxxxxxx", "xx!!!!!!!!!!!xxv", "xxxx!!!!!xxxx", "xxxxxxxxxxxxxxx", "xxx xx x", "xxxx", "xxxxx", "xxxxx", "xxooxxxx", "xxxxxxxxxxxxxxxxxxx", "xxxxxxxxxxxxxxxxxxxxxxxxxx", "xxxxx o xxxxxxxx", "@xxxxxxxxxx", "xxxxxxxxxxxxxxxxxxxxxx", "x xxxxx o xxxxxox xx", "!!!!x x!!!!!!xx!!!!!!xxxx!!!!!!!!xxx!!!!!!!!!!x=x xx", "!!!!x x!!!!!!xx!!!!!xxxxxxxxxxxxx!!!!!!!xx!xxxxxxxxxxxxx xxo oxx", "!!!!x x!!!!!!xx!!!!!xoxx!!!!!!xx !xxxx", "!!!!x x!!!!!!xx!!!!!xxx!!!!!!xx!xxxxxxx", "!!!!x x!!!!!!xx!!!!!xxxxxxxxxxxxxxxx!!!!!!xx!", "!!!!x x!!!!!!xx!!!!!!xxxxxxxxx!!!!!!!!!!!!!!!!!!xx!", "!!!!x x!!!!!!xx!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!xx!"], ["", "", "", "", "", "o", "", "x", "x", "x", "x", "xxx", "x x!!!!!!xxx", "x x!x!!x!", "xxx xxxxx", "xxxooooxxxx", "xxxxx!!!x", "xxxxxxxxxxxxxxxxx", "xxxxxxx", "xxxxxxxxxxxxxxxxxxx x", "xxxx!!!x", "xxxxxx", "xxxxx", "xx= = = =xxxx", "xxxx!!!x", "xx= = = =xoxxxxxx", "xxxxxx!!!x", "ooxxxxxxvxxx", "xxxxx!!!x", "xxx xxx xxx xxxo ox!!!!!!!!!!!!!!xvx", "x xxx x x xxx xx!!!!!!!!!!!!!!x", "xxxxxxxxxxxxxxxxxxxxxxxxx", "xxxxxxx", "xxxxxxx!!!xxxx", "x xxxxxxxxxx x", "xxxxxxxxxxxxxxxxxx", "xxxxxx", "xxxxx x xx", "xx|xxxx||xxxx|xxx xxxx", "xxxxo oxxxxxx", "xxxxxxxxxxxxx!!!xxx", "xoxxxoxxxxxx xxxxxxxx", "xxxxxxxxxxxxxxxxxx oo xx oo xx ooxx xxxxxx", "x@xxx!!xx!!!!xx!!!!xxxxxxx", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "", ""], ["xxx x", "x", "xxxxx", "x", "x xxx", "ox x x", "o o oxxx x", "xxxx", "!o!xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx", "xxxx xx xx xx xx xx x", "x= oxxxxx x xxx x xxx x xxx x xxx x xxx x xxxxx", "xxx xx xx xx xx xx xx", "!o!oxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxxxx", "", "oxxxxx", "", "", "xx", "xxxxxx", "", "oxx", "xxxx", "xxxxxxxxxxx", "", "||", "xxxxxxxxxxx", "xx o xxxxxxxxx o xxxxxxxxx o xxx", "xxxxxxx||xx", "x@xxxxxoxxxxxoxxxxx", "xxxxxxxxxxxxxxxxxxx", "x===xxxxx", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx!!!!!!!!!!!!!!!!!!!!!xxx!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", ""] ]; // Assumes the plan is valid (add validation for production) function Level(plan) { this.width = plan[0].length; this.height = plan.length; // Array of arrays, each position containing null or a character this.grid = []; // Contains all of the dynamic objects (lava, coin or player), // along with their position and state this.actors = []; for (var y = 0; y < this.height; y++) { var line = plan[y], gridLine = []; for (var x = 0; x < this.width; x++) { var ch = line[x], fieldType = null; var Actor = actorChars[ch]; if (Actor) // This constructs the referenced moving object in // actorChars and pushes it to the actors array this.actors.push(new Actor(new Vector(x, y), ch)); else if (ch == 'x') // Wall fieldType = 'wall'; else if (ch == '!') // Stationary lava fieldType = 'lava'; gridLine.push(fieldType); } this.grid.push(gridLine); } // Find the Player actor this.player = this.actors.filter(function(actor) { return actor.type == 'player'; })[0]; // Track whether the player has won or lost; // finishDelay keeps the level active for a brief period of time this.status = this.finishDelay = null; } // Figure out if the level is finished Level.prototype.isFinished = function() { return this.status != null && this.finishDelay < 0; }; // Figure out the collision area of an actor Level.prototype.obstacleAt = function(pos, size) { var xStart = Math.floor(pos.x); var xEnd = Math.ceil(pos.x + size.x); var yStart = Math.floor(pos.y); var yEnd = Math.ceil(pos.y + size.y); // The upper and side bounds of the level return a wall if (xStart < 0 || xEnd > this.width || yStart < 0) return 'wall'; // The bottom bound returns lava if (yEnd > this.height) return 'lava'; // Check what's on the grid around the collision box for (var y = yStart; y < yEnd; y++) { for (var x = xStart; x < xEnd; x++) { var fieldType = this.grid[y][x]; // returns 'wall' or 'lava' if (fieldType) return fieldType; } } }; // Track what actors overlap a given actor Level.prototype.actorAt = function(actor) { for (var i = 0; i < this.actors.length; i++) { var other = this.actors[i]; if (other != actor && actor.pos.x + actor.size.x > other.pos.x && actor.pos.x < other.pos.x + other.size.x && actor.pos.y + actor.size.y > other.pos.y && actor.pos.y < other.pos.y + other.size.y) return other; } }; // Time increment for Level.animate() var maxStep = 0.05; // Animate the level // step will be given in seconds, keys is an object that // contains info about the arrow keys the player has pressed. Level.prototype.animate = function(step, keys) { // Used for the delay at the end of a game if (this.status != null) this.finishDelay -= step; while (step > 0) { var thisStep = Math.min(step, maxStep); this.actors.forEach(function(actor) { actor.act(thisStep, this, keys); }, this); step -= thisStep; } }; // Handle collisions between actors Level.prototype.playerTouched = function(type, actor) { // Lava's been touched if (type == 'lava' && this.status == null) { this.status = 'lost'; this.finishDelay = 1; } else if (type == 'coin') { // a coin's been touched // Remove the coin that's been collected from actors array this.actors = this.actors.filter(function(other) { return other != actor; }); // No more coins = you've won if (!this.actors.some(function(actor) { return actor.type == 'coin'; })) { this.status = 'won'; this.finishDelay = 1; } } }var actorChars = { '@': Player, 'o': Coin, '=': Lava, '|': Lava, 'v': Lava }; // Vector stores the position and size of an actor function Vector(x, y) { this.x = x; this.y = y; } Vector.prototype.plus = function(other) { return new Vector(this.x + other.x, this.y + other.y); } Vector.prototype.times = function(factor) { return new Vector(this.x * factor, this.y * factor); }// Player constructor function Player(pos) { // This properly aligns the bottom of the player // to the square below (adjusts for player height) this.pos = pos.plus(new Vector(0, -0.5)); this.size = new Vector(0.8, 1.5); this.speed = new Vector(0, 0); } Player.prototype.type = 'player'; // X and Y movement are handled independently because // a wall shouldn't stop the up and down motion of jumping // and a floor shouldn't stop side to side movement var playerXSpeed = 7; Player.prototype.moveX = function(step, level, keys) { this.speed.x = 0; if (keys.left) this.speed.x -= playerXSpeed; if (keys.right) this.speed.x += playerXSpeed; var motion = new Vector(this.speed.x * step, 0); var newPos = this.pos.plus(motion); var obstacle = level.obstacleAt(newPos, this.size); if (obstacle) level.playerTouched(obstacle); else this.pos = newPos; }; var gravity = 30; var jumpSpeed = 17; Player.prototype.moveY = function(step, level, keys) { this.speed.y += step * gravity; var motion = new Vector(0, this.speed.y * step); var newPos = this.pos.plus(motion); var obstacle = level.obstacleAt(newPos, this.size); if (obstacle) { level.playerTouched(obstacle); if (keys.up && this.speed.y > 0) this.speed.y = -jumpSpeed; else this.speed.y = 0; } else { this.pos = newPos; } }; Player.prototype.act = function(step, level, keys) { this.moveX(step, level, keys); this.moveY(step, level, keys); var otherActor = level.actorAt(this); if (otherActor) level.playerTouched(otherActor.type, otherActor); // Losing animation if (level.status == 'lost') { this.pos.y += step; this.size.y -=step; } }; // Lava constructor function Lava(pos, ch) { this.pos = pos; this.size = new Vector(1, 1); if (ch == "=") { // I'm guessing that speed will be added to this.pos // in a moving method added later this.speed = new Vector(2, 0); } else if (ch == '|') { this.speed = new Vector(0, 2); } else if (ch == 'v') { this.speed = new Vector(0, 3); this.repeatPos = pos; } } Lava.prototype.type = 'lava'; // Action Lava.prototype.act = function(step, level) { var newPos = this.pos.plus(this.speed.times(step)); if (!level.obstacleAt(newPos, this.size)) this.pos = newPos; else if (this.repeatPos) this.pos = this.repeatPos; else this.speed = this.speed.times(-1); }; // Coin constructor function Coin(pos) { this.basePos = this.pos = pos.plus(new Vector(0.2, 0.1)); this.size = new Vector(0.6, 0.6); this.wobble = Math.random() * Math.PI * 2; } Coin.prototype.type = 'coin'; var wobbleSpeed = 8, wobbleDist = 0.07; // Action Coin.prototype.act = function(step) { this.wobble += step * wobbleSpeed; var wobblePos = Math.sin(this.wobble) * wobbleDist; this.pos = this.basePos.plus(new Vector(0, wobblePos)); }; // Helper function that creates an element // and gives it a class function elt(name, className) { var elt = document.createElement(name); if (className) elt.className = className; return elt; }// Tracking keypresses for player movement var arrowCodes = {37: 'left', 38: 'up', 39: 'right'}; function trackKeys(codes) { var pressed = Object.create(null); function handler(event) { if (codes.hasOwnProperty(event.keyCode)) { var down = event.type == 'keydown'; pressed[codes[event.keyCode]] = down; event.preventDefault(); } } addEventListener('keydown', handler); addEventListener('keyup', handler); pressed.unregister = function() { removeEventListener('keydown', handler); removeEventListener('keyup', handler); }; return pressed; }// Run the animation function runAnimation(frameFunc) { var lastTime = null; function frame(time) { var stop = false; if (lastTime != null) { var timeStep = Math.min(time - lastTime, 100) / 1000; stop = frameFunc(timeStep) === false; } lastTime = time; if (!stop) requestAnimationFrame(frame); } requestAnimationFrame(frame); }// Run the level var arrows = trackKeys(arrowCodes); function runLevel(level, Display, andThen) { var display = new Display(document.body, level); // Used for storing pause state of the game var running = 'yes'; function handleKey(event) { if (event.keyCode == 27) { if (running == 'no') { running = 'yes'; runAnimation(animation); } else if (running == 'pausing') { running = 'yes'; } else if (running == 'yes') { running = 'pausing'; } } } addEventListener('keydown', handleKey); function animation(step) { if (running == 'pausing') { running = 'no'; return false; }level.animate(step, arrows); display.drawFrame(step); if (level.isFinished()) { display.clear(); // Remove the watch on the esc key //removeEventListener('keydown', handleKey); // Unregister the arrow key listeners //arrows.unregister(); if (andThen) andThen(level.status); return false; } }runAnimation(animation); }// Run the game function runGame(plans, Display) { var lives = 3; var livesSpan = document.getElementById('lives'); var gameStatus = document.getElementById('status'); function startLevel(n) { livesSpan.textContent = lives; runLevel(new Level(plans[n]), Display, function(status) { if (status == 'lost') { lives--; if (lives == 0) { gameStatus.textContent = 'Game Over'; console.log('Game over'); } else startLevel(n); } else if (n < plans.length - 1) startLevel(n + 1); else console.log('You win!'); }); } startLevel(0); }// DOMDisplay uses the DOM to draw the program out function DOMDisplay(parent, level) { this.wrap = parent.appendChild(elt('div', 'game')); this.level = level; // Background is drawn only once this.wrap.appendChild(this.drawBackground()); // The actorLayer is animated in the drawFrame() method this.actorLayer = null; this.drawFrame(); } // Set the scale of 1 grid unit var scale = 20; // Draw the background DOMDisplay.prototype.drawBackground = function() { var table = elt('table', 'background'); table.style.width = this.level.width * scale + 'px'; this.level.grid.forEach(function(row) { var rowElt = table.appendChild(elt('tr')); rowElt.style.height = scale + 'px'; row.forEach(function(type) { rowElt.appendChild(elt('td', type)); }); }); return table; }; // Draw the actors DOMDisplay.prototype.drawActors = function() { var wrap = elt('div'); this.level.actors.forEach(function(actor) { var rect = wrap.appendChild(elt('div', 'actor ' + actor.type)); rect.style.width= actor.size.x * scale + 'px'; rect.style.height = actor.size.y * scale + 'px'; rect.style.left= actor.pos.x * scale + 'px'; rect.style.top= actor.pos.y * scale + 'px'; }); return wrap; }; // Redraw the actors DOMDisplay.prototype.drawFrame = function() { if (this.actorLayer) this.wrap.removeChild(this.actorLayer); this.actorLayer = this.wrap.appendChild(this.drawActors()); // The status class is used to style the player based on // the state of the game (won or lost) this.wrap.className = 'game ' + (this.level.status || ''); this.scrollPlayerIntoView(); }; // Make sure the player's always on screen DOMDisplay.prototype.scrollPlayerIntoView = function() { var width = this.wrap.clientWidth; var height = this.wrap.clientHeight; var margin = width / 3; // The viewport var left = this.wrap.scrollLeft, right = left + width; var top = this.wrap.scrollTop, bottom = top + height; // center makes use of the Vector methods defined earlier var player = this.level.player; var center = player.pos.plus(player.size.times(0.5)) .times(scale); if (center.x < left + margin) this.wrap.scrollLeft = center.x - margin; else if (center.x > right - margin) this.wrap.scrollLeft = center.x + margin - width; if (center.y < top + margin) this.wrap.scrollTop = center.y - margin; else if (center.y > bottom - margin) this.wrap.scrollTop = center.y + margin - height; } // Clear the level DOMDisplay.prototype.clear = function() { this.wrap.parentNode.removeChild(this.wrap); }; // Canvas API helper function function flipHorizontally(context, around) { context.translate(around, 0); context.scale(-1, 1); context.translate(-around, 0); } // Use Canvas API to draw game function CanvasDisplay(parent, level) { // Set up the canvas element this.canvas = document.createElement('canvas'); this.canvas.width = Math.min(1000, level.width * scale); this.canvas.height = Math.min(1000, level.height * scale); this.canvas.style.display = 'block'; this.canvas.style.margin = '200px auto 0'; parent.appendChild(this.canvas); this.cx = this.canvas.getContext('2d'); this.level = level; // Uses the step size passed to drawFrame() this.animationTime = 0; this.flipPlayer = false; this.viewport = { left: 0, top: 0, width: this.canvas.width / scale, height: this.canvas.height / scale }; this.drawFrame(0); } CanvasDisplay.prototype.clear = function() { this.canvas.parentNode.removeChild(this.canvas); }; // Draw the frame CanvasDisplay.prototype.drawFrame = function(step) { this.animationTime += step; // Update the current player position for the viewport this.updateViewport(); // Clear current frame this.clearDisplay(); // Draw the background this.drawBackground(); // Draw the actors this.drawActors(); }; // Scrolls the viewport depending on the player position CanvasDisplay.prototype.updateViewport = function() { var view = this.viewport, margin = view.width / 3; var player = this.level.player; var center = player.pos.plus(player.size.times(0.5)); // Compare the center.x of player to the viewport // Player is less than the left of the viewport plus margin if (center.x < view.left + margin) // Scroll left until less than 0 view.left = Math.max(center.x - margin, 0); // Player is further right than the right of the viewport plus margin else if (center.x > view.left + view.width - margin) // Scroll right until greater than the edge of the level view.left = Math.min(center.x + margin - view.width, this.level.width - view.width); if (center.y < view.top + margin) view.top = Math.max(center.y - margin, 0); else if (center.y > view.top + view.height - margin) view.top = Math.min(center.y + margin - view.height, this.level.height - view.height); }; CanvasDisplay.prototype.clearDisplay = function() { if (this.level.status == 'won') this.cx.fillStyle = 'rgb(68, 191, 255)'; else if (this.level.status == 'lost') this.cx.fillStyle = 'rgb(44, 136, 214)'; else this.cx.fillStyle = 'rgb(52, 166, 251)'; this.cx.fillRect(0, 0, this.canvas.width, this.canvas.height); }; var otherSprites = document.createElement('img'); otherSprites.src = 'http://eloquentjavascript.net/img/sprites.png'; // Draw the background CanvasDisplay.prototype.drawBackground = function() { var view = this.viewport; var xStart = Math.floor(view.left); var xEnd = Math.ceil(view.left + view.width); var yStart = Math.floor(view.top); var yEnd = Math.ceil(view.top + view.height); for (var y = yStart; y < yEnd; y++) { for (var x = xStart; x < xEnd; x++) { var tile = this.level.grid[y][x]; if (tile == null) continue; var screenX = (x - view.left) * scale; var screenY = (y - view.top) * scale; var tileX = tile == 'lava' ? scale : 0; this.cx.drawImage(otherSprites, tileX,0,scale, scale, screenX, screenY, scale, scale); } } }; // Draw the player (called by drawActors()) var playerSprites = document.createElement('img'); playerSprites.src = 'http://eloquentjavascript.net/img/player.png'; var playerXOverlap = 4; CanvasDisplay.prototype.drawPlayer = function(x, y, width, height) { var sprite = 8, player = this.level.player; width += playerXOverlap * 2; x -= playerXOverlap; if (player.speed.x != 0) this.flipPlayer = player.speed.x < 0; if (player.speed.y != 0) sprite = 9; else if (player.speed.x != 0) sprite = Math.floor(this.animationTime * 12) % 8; this.cx.save(); if (this.flipPlayer) flipHorizontally(this.cx, x + width / 2); this.cx.drawImage(playerSprites, sprite * width, 0, width, height, x,y, width, height); this.cx.restore(); } // Draw the actors CanvasDisplay.prototype.drawActors = function() { this.level.actors.forEach(function(actor) { var width = actor.size.x * scale; var height = actor.size.y * scale; var x = (actor.pos.x - this.viewport.left) * scale; var y = (actor.pos.y - this.viewport.top) * scale; if (actor.type == 'player') { this.drawPlayer(x, y, width, height); } else { var tileX = (actor.type == 'coin' ? 2 : 1) * scale; this.cx.drawImage(otherSprites, tileX, 0, width, height, x,y, width, height); } }, this); }; // Run game with DOMDisplay // runGame(GAME_LEVELS, DOMDisplay); // Run game with CanvasDisplay runGame(GAME_LEVELS, CanvasDisplay);

    推荐阅读