城市漫游特效
代码语言:html
所属分类:背景
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Procedural Canvas cityscape (profile header)</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
background: black;
margin: 0;
padding: 0;
overflow: hidden;
}
canvas {
background: transparent;
background-image: linear-gradient(black 20%, #101 30%, #211 40%, #070702 52%, #000 90%, #000 100%);
background-repeat: no-repeat;
display: block;
margin: 0 auto;
width: 100%;
max-width: 1800px;
height: 300px;
}
#vignette {
background-image: linear-gradient(right, black 0%, transparent 10%, transparent 90%, black 100%);
position: absolute;
top: 0;
left: 50%;
width: 100%;
height: 300px;
max-width: 1800px;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
z-index: 50;
}
</style>
</head>
<body translate="no">
<script>
// OVERENGINEERED UNOPTIMIZED CANVAS BULLSH*T
// BUT IT'S OKAY SINCE IT'S BLADE RUNNER INNIT
// Some stuff left unoptimized / verbose to show the work.
// TODO:
// - optimize render loop, avoid overdraws, etc
// - smoothly fade rows in on the horizon
// Constants. Change at own risk
const CANVAS_WIDTH = 900;
const CANVAS_HEIGHT = 300;
const FRAME_TIME = 1000 / 16;
const LIGHT_ROWS = 20;
const LIGHT_ROW_DEPTH = 2;
const LIGHT_SPACING = 0.6;
const LIGHT_SIZE = 0.1;
const LIGHT_SCATTER = 0.4;
const BUILDING_ROWS = 38;
const BUILDING_ROW_DEPTH = 1;
const BUILDING_ROW_WIDTH = 60;
const BUILDING_MIN_HEIGHT = 1.5;
const BUILDING_MAX_HEIGHT = 3;
const STACK_HEIGHT = 9;
const STACK_THRESHOLD = 0.87;
const STACK_LIGHT_CHANCE = 0.95;
const STACK_LIGHT_SIZE = 0.13;
const FADE_GRAY_VALUE = 25;
const FADE_OFFSET = 0.35;
// Virtual camera. Used in perspective calculations
const CAMERA = {
x: 0,
y: 10,
z: 0,
fov: 170,
dist: 30,
zSpeed: 0.005
// Virtual vanishing point XY. Used in perspective calculations
};const VP_OFS = {
x: 0.5,
y: 0.27
// Global hoisted vars for rendering contexts and timers
};let c, ctx, output_c, output_ctx;
let _t, _dt, _ft;
// Seedable random number generator.
// Not particularly well-distributed, but fine for this case.
// Allows us to emit the same set of random numbers on every frame
// so we can consistently re-render the scene.
const RNG = {
seed: 1,
random() {
const x = Math.sin(RNG.seed++) * 10000;
return x - (x << 0);
},
randomInRange(min, max) {
return (RNG.random() * (max - min + 1) << 0) + min;
} };
// Module to get a random colour from a predefined list.
// Uses the seedable RNG
const Palette = (() => {
const PAL = ['black', '#111', '#113', 'white', 'sliver', '#f88', 'orange', 'oldlace', '#569'];
const lastIndex = PAL.length - 1;
function getRandomFromPalette() {
return PAL[RNG.randomInRange(0, lastIndex)];
}
return {
getRandom: getRandomFromPalette };
})();
function ceil(n) {
var f = n << 0,f = f == n ? f : f + 1;
return f;
}
// Update method of main loop
function update() {
// Update our global timestamp (used in rendering)
_t = Date.now() * 0.001;
// Move the camera slowly 'forward'
CAMERA.z += CAMERA.zSpeed;
}
// Draw a frame of the scene.
// Uses the current timestamp and the seeded RNG to render a
// pseudorandom cityscape with lights and buildings.
// We always generate and draw a set amount of city in front of
// the camera, so it appears to be endless as we 'fly over' it.
//
// 1. Clear the whole scene
// 2. Render random rows of lights
// 3. Render random rows of buildings
// 4. Blit scene to onscreen canvas
let _$ = {
vPointX: 0,
vPointY: 0,
rowScreenX: 0,
MAX_LIGHTS: 0,
closestLightRow: 0,
rowZ: 0,
rowRelativeZ: 0,
scalingFactor: 0,
rowScreenWidth: 0,
rowScreenHeight: 0,
rowScreenY: 0,
rowScreenLightSpacing: 0,
rowLightCount: 0,
lightSize: 0,
lightHalfSize: 0,
lightScreenX: 0,
lightScreenY: 0,
closestBuildingRow: 0,
rowBuildingCount: 0,
rowBuildingScreenWidth: 0,
rowShade: 0,
rowStyleString: '',
lightData: [],
isStack: false,
buildingHeight: 0,
buildingScreenHeight: 0,
buildingScreenX: 0,
buildingScreenY: 0,
lightSize: 0,
lightHalfSize: 0,
lightColor: 0 };
function render() {
// Calculate the pixel XY of the vanishing point
// (could be done on init, but useful if we ever want to
// dynamically move the camera)
_$.vPointX = c.width * VP_.........完整代码请登录后点击上方下载按钮下载查看
网友评论0