html--滚滚

html 复制代码
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
 <HEAD>
  <TITLE> New Document </TITLE>
  <META NAME="Generator" CONTENT="EditPlus">
  <META NAME="Author" CONTENT="">
  <META NAME="Keywords" CONTENT="">
  <META NAME="Description" CONTENT="">
  <style>
  body {
  background: #242424;
	color: #666;
	font-size: 8pt;
	font-family: sans-serif;
	padding: 0;
	margin: 0;
}
  </style>
 </HEAD>

 <BODY>
 <canvas width="860" height="480" id="canvas"></canvas>
<ul>
  <li>Right - Accelerate</li>
	<li>Left - Brake</li>
	<li>Up - Jump</li>
	<li>Down (while jumping or falling) - Swap Tracks</li>
	<li>1 - Disable forward movement</li>
	<li>2 - Enable forward movement</li>
</ul>
  <script>
  var _debug = {
  lockPlayerMovement: false,
  showPlayerInfo: false
};

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

var Shape = {};

Shape.line = function() {
  this.x1 = 0;
	this.y1 = 0;
	this.x2 = 0;
	this.y2 = 0;
	this.lineWidth = 2;
	this.strokeStyle = "#000000";
	
	this.draw = function() {
		context.beginPath();
		context.moveTo(this.x1, this.y1);
		context.lineTo(this.x2, this.y2);
		context.lineWidth = this.lineWidth;
		context.strokeStyle = this.strokeStyle;
		context.stroke();
	};
};

Shape.circle = function() {
	this.x = 0;
	this.y = 0;
	this.radius = 0;
	this.lineWidth = 2;
	this.strokeStyle = "#000000";
	this.fillStyle = "transparent";
	
	this.draw = function() {
		context.beginPath();
		context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
		context.fillStyle = this.fillStyle;
		context.fill();
		context.lineWidth = this.lineWidth;
		context.strokeStyle = this.strokeStyle;
		context.stroke();
	};
};

Shape.text = function() {
	this.x = 0;
	this.y = 0;
	this.font = "10pt sans-serif";
	this.textAlign = "center";
	this.textBaseline = "middle";
	this.fillStyle = "black";
	this.fillText = "";
	
	this.draw = function() {
		context.font = this.font;
		context.textAlign = this.center;
		context.textBaseline = this.textBaseline;
		context.fillStyle = this.fillStyle;
		context.fillText(this.fillText, this.x, this.y);
	};
};

Shape.rectangle = function() {
	this.x = 0;
	this.y = 0;
	this.width = 0;
	this.height = 0;
	this.lineWidth = 2;
	this.strokeStyle = "#000000";
	this.fillStyle = "transparent";
	
	this.draw = function() {
		context.rect(this.x, this.y, this.width, this.height);
		context.fillStyle = this.fillStyle;
		context.fill();
	};
};

var Key = {
	_pressed: {},

	LEFT: 37,
	UP: 38,
	RIGHT: 39,
	DOWN: 40,
	SPACE: 32,
	SHIFT: 16,
	CTRL: 17,
	CAM_LEFT: 190,
	CAM_RIGHT: 188,
	
	DB_1: 49,
	DB_2: 50,
	DB_3: 51,
	DB_4: 52,
	DB_5: 53,
	DB_6: 54,
	DB_7: 55,
	DB_8: 56,
	DB_9: 57,

	isDown: function(keyCode) {
		return this._pressed[keyCode];
	},

	onKeydown: function(event) {
		this._pressed[event.keyCode] = true;
	},

	onKeyup: function(event) {
		delete this._pressed[event.keyCode];
	}
};
window.addEventListener('keyup', function(event) { Key.onKeyup(event); }, false);
window.addEventListener('keydown', function(event) { Key.onKeydown(event); }, false);

var Camera = function(x, y) {
	this.x = x;
	this.y = y;
	this.radius = 4;
	this.velocity = {};
	this.velocity.x = 0;
	this.velocity.y = 0;
	
	this.addVelocity = function(x, y) {
		this.velocity.x += x;
		this.velocity.y += y;
	};
	
	this.update = function(lines, player) {
		this.x = player.x - (canvas.width / 2);
	};
};

var Player = function(x, y, r) {
	this.shapes = {};
	this.shapes.circle = new Shape.circle();
	this.shapes.radius = new Shape.line();
	
	this.x = x;
	this.y = y;
	this.radius = r;
	this.velocity = {};
	this.velocity.x = 0;
	this.velocity.y = 0;
	this.angle = 0;
	this.level = 1;
	
	var maxJumpDist = 12;
	var jumpDist = 0;
	
	var lasty = y;
	var lastx = 0;
	
	// States
	this.isJumping = false;
	this.isFalling = false;
	this.isSwappingLevels = false;
	this.isAlive = true;
	
	// Adds velocity to the player
	this.addVelocity = function(x, y) {
		this.velocity.x += x;
		this.velocity.y += y;
	};
	
	// Collides with the world
	this.collide = function(line, adjx, adjy) {
		var run = line.x2 - line.x1;
		var rise = line.y2 - line.y1;
		
		var slope = rise / run;
		var intersect = (line.y1) - (line.x1 * slope);
		var col = (slope * adjx) + intersect;
		
		var angle = radToDeg(Math.atan(rise / run));
		this.angle = angle;
		var normal = angle + 90;
		
		// Collide with track
		if(lasty < col && adjy > col) {
			this.y = col + (this.y - adjy);
			this.isFalling = false;
			this.isSwappingLevels = false;
			jumpDist = 0;
		} else {
			if(!this.isJumping) {
				this.isFalling = true;
			}
		}
	};
	
	this.update = function(lines) {	
		if(this.isAlive) {
			// Accelerate
			if(Key.isDown(Key.RIGHT))
				this.addVelocity(_debug.lockPlayerMovement ? 0.2 : 0.1, 0, 0);
			
			// Brake
			if(Key.isDown(Key.LEFT))
				this.addVelocity(_debug.lockPlayerMovement ? -0.2 : -0.1, 0);
				
			// Jump
			if(Key.isDown(Key.UP)) {
				if(!this.isFalling && !this.isJumping) {
					this.isJumping = true;
				}
			// Stop jumping
			} else {
				if(this.isJumping) {
					this.isJumping = false;
					jumpDist = 0;
				}
			}
		}
	
		this.y += 7.5; // gravity
		if(this.isAlive) this.velocity.x += _debug.lockPlayerMovement ? 0 : 0.2; // automatic accelerate
		this.x += this.velocity.x;
		this.y += this.velocity.y;
		
		// Decay velocity
		this.velocity.x *= 0.985;
		this.velocity.y *= 0.95;

		// Collision point
		var adjx = (this.radius * Math.cos((this.angle + 90) * Math.PI / 180)) + this.x;
        var adjy = (this.radius * Math.sin((this.angle + 90) * Math.PI / 180)) + (this.y + 2); // 2px padding for stroke width
		
		// Finds the line the player is going to collide with
		var playerPos;
		if(lines[0].level === 2) // background track
			playerPos = adjx / levelPrefs.width >> 0;
		else // foreground track
			playerPos = adjx / levelPrefs.width >> 0;
		
		// Loop through the lines and collide with the player
		for(var i = 0; i < lines.length; i++) {
			if(i === playerPos)
				this.collide(lines[i], adjx, adjy);
		}

		// Swap tracks
		if(!this.isSwappingLevels && !this.isJumping && this.isFalling && Key.isDown(Key.DOWN)) {
			if(this.level === 1) {
				this.level = 2;
				this.isSwappingLevels = true;
			} else {
				this.level = 1;
				this.isSwappingLevels = true;
			}
		}
		
		// Find the y direction the player is moving
		var yvel;
		var yfixed = this.y.toFixed(1);
		if(yfixed < lasty) yvel = 1;
		if(yfixed > lasty) yvel = -1;
		if(yfixed == lasty) yvel = 0;
		
		// Apply extra gravity to keep player on slope during downward movement
		// This prevents a bug where the player cannot jump while moving quickly
		// downwards due to being in a "falling" state.
		if(this.angle) {
			if(yvel < 0 && (this.angle < -33 || this.angle > 33) && !this.isJumping) 
				this.y += 2;
		}
		
		// Jumping logic
		if(this.isJumping) {
			var jumpVel = -15;
			jumpDist += 1;
			
			if(jumpDist > maxJumpDist) {
				this.isJumping = false;
				this.isFalling = true;
				jumpDist = 0;
			} else {
				this.velocity.y = jumpVel;
			}	
		}
		
		// Die when falling off the edge of the world
		if( adjy > canvas.height + (this.radius * 2) ||
			adjx < 0 ||
			adjx > lines.length * levelPrefs.width) {
			this.isAlive = false;
		}
		
		// Reset when the player dies
		if(!this.isAlive) {
			this.x = levelStart.x;
			this.y = levelStart.y;
			this.velocity = {x: 0, y: 0};
			this.isAlive = true;
		}
		
		lasty = this.y.toFixed(1); // last known y position
	};
	
	this.draw = function(camera) {
		this.shapes.circle.radius = this.radius;
		this.shapes.circle.strokeStyle = "#218ae0";
		this.shapes.circle.x = this.x - camera.x;
		this.shapes.circle.y = this.y;
		this.shapes.circle.draw();
		
		var x = (this.radius * Math.cos((this.angle + 90) * Math.PI / 180)) + this.x;
        var y = (this.radius * Math.sin((this.angle + 90) * Math.PI / 180)) + this.y;
		this.shapes.radius.x1 = this.x - camera.x;
		this.shapes.radius.y1 = this.y;
		this.shapes.radius.x2 = x - camera.x;
		this.shapes.radius.y2 = y;
		this.shapes.radius.strokeStyle = "#a7c6e0";
		this.shapes.radius.draw();
	};
};

var Line = function(x1, y1, x2, y2) {
	this.shapes = {};
	this.shapes.line = new Shape.line();

	this.x1 = x1;
	this.y1 = y1;
	this.x2 = x2;
	this.y2 = y2;
	this.strokeStyle = "#ffffff";
	this.level = 1;
	
	var lineClass = "line";
	
	this.setLevel = function(level) {
		this.level = level;
		lineClass = "line" + level;
	};
	
	this.draw = function(camera) {
		this.shapes.line.x1 = this.x1 - camera.x;
		this.shapes.line.y1 = this.y1;
		this.shapes.line.x2 = this.x2 - camera.x;
		this.shapes.line.y2 = this.y2;
		this.shapes.line.strokeStyle = this.strokeStyle;
		this.shapes.line.draw();
	};
};

function getNextPoint(frequency, offset, step, width, center) {
	return (Math.sin(frequency * step + offset) * width + center) >> 0;
}

function radToDeg(rad) {
	return rad * (180 / Math.PI);
}

var levelStart = {};
levelStart.x = canvas.width / 2;
levelStart.y = 100;

var camera = new Camera(levelStart.x, levelStart.y);
var background = new Shape.rectangle();
	background.x = 0;
	background.y = 0;
	background.width = canvas.width;
	background.height = canvas.height;
	background.lineWidth = 0;
	background.fillStyle = "#121212";
var player = new Player(levelStart.x, levelStart.y, 20);
	player.level = 2;
var lines = [];
var lines2 = [];

var levelPrefs = {
    width: 30,
    length: 600,
	frequency: 0.1,
	wavelength: 32,
	offset: 380,
	numLines: 50
};

var levelPrefs2 = {
    width: 30,
    length: 600,
	frequency: 0.2,
	wavelength: 48,
	offset: 260,
	numLines: 50
};

for(var i = 0; i < levelPrefs2.length; i ++) {
	var y = getNextPoint(levelPrefs2.frequency, levelPrefs2.frequency * Math.PI / 3, i, levelPrefs2.wavelength, levelPrefs2.offset);
	var y2 = getNextPoint(levelPrefs2.frequency, levelPrefs2.frequency * Math.PI / 3, i + 1, levelPrefs2.wavelength, levelPrefs2.offset);
	var line = new Line(i * levelPrefs2.width, y, i * levelPrefs2.width + levelPrefs2.width, y2);
	line.setLevel(2);
	line.strokeStyle = "#402712";
	lines2.push(line);
}

for(var i = 0; i < levelPrefs.length; i ++) {
	var y, y2;
	if(i % 100 > 90 && i % 100 < 100 ) {
		y = 800;
		y2 = 800;
	} else {
		y = getNextPoint(levelPrefs.frequency, levelPrefs.frequency * Math.PI / 3, i, levelPrefs.wavelength, levelPrefs.offset);
		y2 = getNextPoint(levelPrefs.frequency, levelPrefs.frequency * Math.PI / 3, i + 1, levelPrefs.wavelength, levelPrefs.offset);
	}
	var line = new Line(i * levelPrefs.width, y, i * levelPrefs.width + levelPrefs.width, y2);
	line.setLevel(1);
	line.strokeStyle = "#734720";
	lines.push(line);
}

var update = function() {
	context.save();

	// Use the identity matrix while clearing the canvas
	context.setTransform(1, 0, 0, 1, 0, 0);
	context.clearRect(0, 0, canvas.width, canvas.height);

	// Restore the transform
	context.restore();
	
	camera.update(lines, player);
	player.update(player.level === 2 ? lines2 : lines);
	
	if(Key.isDown(Key.DB_1)) _debug.lockPlayerMovement = true;
	if(Key.isDown(Key.DB_2)) _debug.lockPlayerMovement = false;
};

var draw = function() {
	background.draw();
	
	for(var i = 0; i < lines2.length; i++) {
		lines2[i].draw(camera, true);
	}
	
	player.draw(camera);
		
	for(var i = 0; i < lines.length; i++) {
		lines[i].draw(camera, false);
	}
};

var gameloop = function() {
	update();
	draw();
};

var animationFrame = window.requestAnimationFrame ||
	window.webkitRequestAnimationFrame ||
	window.mozRequestAnimationFrame    ||
	window.oRequestAnimationFrame      ||
	window.msRequestAnimationFrame     ||
	null;

if (animationFrame !== null) {
	var recursiveAnim = function() {
		gameloop();
		animationFrame(recursiveAnim);
	};

	// start the gameloop
	animationFrame(recursiveAnim);
} else {
	setInterval(gameloop, 1000.0 / 60.0);
}
  </script>
 </BODY>
</HTML>
相关推荐
Your易元2 小时前
设计模式-状态模式
java·前端·算法·设计模式
网络点点滴4 小时前
将项目推到Github
javascript·github
HaanLen4 小时前
React19源码系列之 Hooks (useState、useReducer、useOptimistic)
服务器·前端
yuanyxh7 小时前
《精通正则表达式》精华摘要
前端·javascript·正则表达式
小飞大王6667 小时前
简单实现HTML在线编辑器
前端·编辑器·html
Jimmy8 小时前
CSS 实现卡牌翻转
前端·css·html
百万蹄蹄向前冲8 小时前
大学期末考,AI定制个性化考试体验
前端·人工智能·面试
向明天乄8 小时前
在 Vue 3 项目中集成高德地图(附 Key 与安全密钥申请全流程)
前端·vue.js·安全
sunshine_程序媛8 小时前
vue3中的watch和watchEffect区别以及demo示例
前端·javascript·vue.js·vue3
电商数据girl9 小时前
【经验分享】浅谈京东商品SKU接口的技术实现原理
java·开发语言·前端·数据库·经验分享·eclipse·json