'use strict'; const canvas = document.getElementsByTagName('canvas')[0]; canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; const params = { alpha: false, depth: false, stencil: false, antialias: false }; let gl = canvas.getContext('webgl2', params); const isWebGL2 = !!gl; if (!isWebGL2) { gl = canvas.getContext('webgl', params) || canvas.getContext('experimental-webgl', params); } gl.clearColor(0.0, 0.0, 0.0, 1.0); const halfFloat = gl.getExtension('OES_texture_half_float'); let support_linear_float = gl.getExtension('OES_texture_half_float_linear'); if (isWebGL2) { gl.getExtension('EXT_color_buffer_float'); support_linear_float = gl.getExtension('OES_texture_float_linear'); } const TEXTURE_DOWNSAMPLE = 1; const DENSITY_DISSIPATION = 0.98; const VELOCITY_DISSIPATION = 0.99; const SPLAT_RADIUS = 0.005; const CURL = 30; const PRESSURE_ITERATIONS = 25; class GLProgram { constructor (vertexShader, fragmentShader) { this.uniforms = {}; this.program = gl.createProgram(); gl.attachShader(this.program, vertexShader); gl.attachShader(this.program, fragmentShader); gl.linkProgram(this.program); if (!gl.getProgramParameter(this.program, gl.LINK_STATUS)) throw gl.getProgramInfoLog(this.program); const uniformCount = gl.getProgramParameter(this.program, gl.ACTIVE_UNIFORMS); for (let i = 0; i < uniformCount; i++) { const uniformName = gl.getActiveUniform(this.program, i).name; this.uniforms[uniformName] = gl.getUniformLocation(this.program, uniformName); } } bind () { gl.useProgram(this.program); } } function compileShader (type, source) { const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) throw gl.getShaderInfoLog(shader); return shader; }; const baseVertexShader = compileShader(gl.VERTEX_SHADER, ` precision highp float; precision mediump sampler2D; attribute vec2 aPosition; varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; varying vec2 vB; uniform vec2 texelSize; void main () { vUv = aPosition * 0.5 + 0.5; vL = vUv - vec2(texelSize.x, 0.0); vR = vUv + vec2(texelSize.x, 0.0); vT = vUv + vec2(0.0, texelSize.y); vB = vUv - vec2(0.0, texelSize.y); gl_Position = vec4(aPosition, 0.0, 1.0); } `); const displayShader = compileShader(gl.FRAGMENT_SHADER, ` precision highp float; precision mediump sampler2D; varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; varying vec2 vB; uniform sampler2D uTexture; void main () { gl_FragColor = texture2D(uTexture, vUv); } `); const splatShader = compileShader(gl.FRAGMENT_SHADER, ` precision highp float; precision mediump sampler2D; varying vec2 vUv; uniform sampler2D uTarget; uniform float aspectRatio; uniform vec3 color; uniform vec2 point; uniform float radius; void main () { vec2 p = vUv - point.xy; p.x *= aspectRatio; vec3 splat = exp(-dot(p, p) / radius) * color; vec3 base = texture2D(uTarget, vUv).xyz; gl_FragColor = vec4(base + splat, 1.0); } `); const advectionManualFilteringShader = compileShader(gl.FRAGMENT_SHADER, ` precision highp float; precision mediump sampler2D; varying vec2 vUv; uniform sampler2D uVelocity; uniform sampler2D uSource; uniform vec2 texelSize; uniform float dt; uniform float dissipation; vec4 bilerp (in sampler2D sam, in vec2 p) { vec4 st; st.xy = floor(p - 0.5) + 0.5; st.zw = st.xy + 1.0; vec4 uv = st * texelSize.xyxy; vec4 a = texture2D(sam, uv.xy); vec4 b = texture2D(sam, uv.zy); vec4 c = texture2D(sam, uv.xw); vec4 d = texture2D(sam, uv.zw); vec2 f = p - st.xy; return mix(mix(a, b, f.x), mix(c, d, f.x), f.y); } void main () { vec2 coord = gl_FragCoord.xy - dt * texture2D(uVelocity, vUv).xy; gl_FragColor = dissipation * bilerp(uSource, coord); gl_FragColor.a = 1.0; } `); const advectionShader = compileShader(gl.FRAGMENT_SHADER, ` precision highp float; precision mediump sampler2D; varying vec2 vUv; uniform sampler2D uVelocity; uniform sampler2D uSource; uniform vec2 texelSize; uniform float dt; uniform float dissipation; void main () { vec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize; gl_FragColor = dissipation * texture2D(uSource, coord); } `); const divergenceShader = compileShader(gl.FRAGMENT_SHADER, ` precision highp float; precision mediump sampler2D; varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; varying vec2 vB; uniform sampler2D uVelocity; vec2 sampleVelocity (in vec2 uv) { vec2 multiplier = vec2(1.0, 1.0); if (uv.x < 0.0) { uv.x = 0.0; multiplier.x = -1.0; } if (uv.x > 1.0) { uv.x = 1.0; multiplier.x = -1.0; } if (uv.y < 0.0) { uv.y = 0.0; multiplier.y = -1.0; } if (uv.y > 1.0) { uv.y = 1.0; multiplier.y = -1.0; } return multiplier * texture2D(uVelocity, uv).xy; } void main () { float L = sampleVelocity(vL).x; float R = sampleVelocity(vR).x; float T = sampleVelocity(vT).y; float B = sampleVelocity(vB).y; float div = 0.5 * (R - L + T - B); gl_FragColor = vec4(div, 0.0, 0.0, 1.0); } `); const curlShader = compileShader(gl.FRAGMENT_SHADER, ` precision highp float; precision mediump sampler2D; varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; varying vec2 vB; uniform sampler2D uVelocity; void main () { float L = texture2D(uVelocity, vL).y; float R = texture2D(uVelocity, vR).y; float T = texture2D(uVelocity, vT).x; float B = texture2D(uVelocity, vB).x; float vorticity = R - L - T + B; gl_FragColor = vec4(vorticity, 0.0, 0.0, 1.0); } `); const vorticityShader = compileShader(gl.FRAGMENT_SHADER, ` precision highp float; precision mediump sampler2D; varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; varying vec2 vB; uniform sampler2D uVelocity; uniform sampler2D uCurl; uniform float curl; uniform float dt; void main () { float L = texture2D(uCurl, vL).y; float R = texture2D(uCurl, vR).y; float T = texture2D(uCurl, vT).x; float B = texture2D(uCurl, vB).x; float C = texture2D(uCurl, vUv).x; vec2 force = vec2(abs(T) - abs(B), abs(R) - abs(L)); force *= 1.0 / length(force + 0.00001) * curl * C; vec2 vel = texture2D(uVelocity, vUv).xy; gl_FragColor = vec4(vel + force * dt, 0.0, 1.0); } `); const pressureShader = compileShader(gl.FRAGMENT_SHADER, ` precision highp float; precision mediump sampler2D; varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; varying vec2 vB; uniform sampler2D uPressure; uniform sampler2D uDivergence; vec2 boundary (in vec2 uv) { uv = min(max(uv, 0.0), 1.0); return uv; } void main () { float L = texture2D(uPressure, boundary(vL)).x; float R = texture2D(uPressure, boundary(vR)).x; float T = texture2D(uPressure, boundary(vT)).x; float B = texture2D(uPressure, boundary(vB)).x; float C = texture2D(uPressure, vUv).x; float divergence = texture2D(uDivergence, vUv).x; float pressure = (L + R + B + T - divergence) * 0.25; gl_FragColor = vec4(pressure, 0.0, 0.0, 1.0); } `); const gradientSubtractShader = compileShader(gl.FRAGMENT_SHADER, ` precision highp float; precision mediump sampler2D; varying vec2 vUv; varying vec2 vL; varying vec2 vR; varying vec2 vT; varying vec2 vB; uniform sampler2D uPressure; uniform sampler2D uVelocity; vec2 boundary (in vec2 uv) { uv = min(max(uv, 0.0), 1.0); return uv; } void main () { float L = texture2D(uPressure, boundary(vL)).x; float R = texture2D(uPressure, boundary(vR)).x; float T = texture2D(uPressure, boundary(vT)).x; float B = texture2D(uPressure, boundary(vB)).x; vec2 velocity = texture2D(uVelocity, vUv).xy; velocity.xy -= vec2(R - L, T - B); gl_FragColor = vec4(velocity, 0.0, 1.0); } `); const blit = (() => { gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, -1, 1, 1, 1, 1, -1]), gl.STATIC_DRAW); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer()); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 0, 2, 3]), gl.STATIC_DRAW); gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(0); return (destination) => { gl.bindFramebuffer(gl.FRAMEBUFFER, destination); gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); } })(); function clear (target) { gl.bindFramebuffer(gl.FRAMEBUFFER, target); gl.clear(gl.COLOR_BUFFER_BIT); } function createFBO (texId, w, h, internalFormat, format, type, param) { gl.activeTexture(gl.TEXTURE0 + texId); let texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, param); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, param); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, w, h, 0, format, type, null); let fbo = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); gl.viewport(0, 0, w, h); gl.clear(gl.COLOR_BUFFER_BIT); return [texture, fbo, texId]; } function createDoubleFBO (texId, w, h, internalFormat, format, type, param) { let fbo1 = createFBO(texId , w, h, internalFormat, format, type, param); let fbo2 = createFBO(texId + 1, w, h, internalFormat, format, type, param); return { get first () { return fbo1; }, get second () { return fbo2; }, swap: () => { let temp = fbo1; fbo1 = fbo2; fbo2 = temp; } } } let textureWidth; let textureHeight; let density; let velocity; let divergence; let curl; let pressure; function initFramebuffers () { textureWidth = gl.drawingBufferWidth >> TEXTURE_DOWNSAMPLE; textureHeight = gl.drawingBufferHeight >> TEXTURE_DOWNSAMPLE; const internalFormat = isWebGL2 ? gl.RGBA16F : gl.RGBA; const internalFormatRG = isWebGL2 ? gl.RG16F : gl.RGBA; const formatRG = isWebGL2 ? gl.RG : gl.RGBA; const texType = isWebGL2 ? gl.HALF_FLOAT : halfFloat.HALF_FLOAT_OES; density = createDoubleFBO(0, textureWidth, textureHeight, internalFormat , gl.RGBA , texType, support_linear_float ? gl.LINEAR : gl.NEAREST); velocity = createDoubleFBO(2, textureWidth, textureHeight, internalFormatRG, formatRG, texType, support_linear_float ? gl.LINEAR : gl.NEAREST); divergence = createFBO (4, textureWidth, textureHeight, internalFormatRG, formatRG, texType, gl.NEAREST); curl = createFBO (5, textureWidth, textureHeight, internalFormatRG, formatRG, texType, gl.NEAREST); pressure = createDoubleFBO(6, textureWidth, textureHeight, internalFormatRG, formatRG, texType, gl.NEAREST); } initFramebuffers(); const displayProgram = new GLProgram(baseVertexShader, displayShader); const splatProgram = new GLProgram(baseVertexShader, splatShader); const advectionProgram = new GLProgram(baseVertexShader, support_linear_float ? advectionShader : advectionManualFilteringShader); const divergenceProgram = new GLProgram(baseVertexShader, divergenceShader); const curlProgram = new GLProgram(baseVertexShader, curlShader); const vorticityProgram = new GLProgram(baseVertexShader, vorticityShader); const pressureProgram = new GLProgram(baseVertexShader, pressureShader); const gradienSubtractProgram = new GLProgram(baseVertexShader, gradientSubtractShader); function pointerPrototype () { this.id = -1; this.x = 0; this.y = 0; this.dx = 0; this.dy = 0; this.down = false; this.moved = false; this.color = [30, 0, 300]; } let pointers = []; pointers.push(new pointerPrototype()); for (let i = 0; i < 10; i++) { const color = [Math.random() * 10, Math.random() * 10, Math.random() * 10]; const x = canvas.width * Math.random(); const y = canvas.height * Math.random(); const dx = 1000 * (Math.random() - 0.5); const dy = 1000 * (Math.random() - 0.5); splat(x, y, dx, dy, color); } let lastTime = Date.now(); Update(); function Update () { resizeCanvas(); const dt = Math.min((Date.now() - lastTime) / 1000, 0.016); lastTime = Date.now(); gl.viewport(0, 0, textureWidth, textureHeight); advectionProgram.bind(); gl.uniform2f(advectionProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight); gl.uniform1i(advectionProgram.uniforms.uVelocity, velocity.first[2]); gl.uniform1i(advectionProgram.uniforms.uSource, velocity.first[2]); gl.uniform1f(advectionProgram.uniforms.dt, dt); gl.uniform1f(advectionProgram.uniforms.dissipation, VELOCITY_DISSIPATION); blit(velocity.second[1]); velocity.swap(); gl.uniform1i(advectionProgram.uniforms.uVelocity, velocity.first[2]); gl.uniform1i(advectionProgram.uniforms.uSource, density.first[2]); gl.uniform1f(advectionProgram.uniforms.dissipation, DENSITY_DISSIPATION); blit(density.second[1]); density.swap(); for (let i = 0; i < pointers.length; i++) { const pointer = pointers[i]; if (pointer.moved) { splat(pointer.x, pointer.y, pointer.dx, pointer.dy, pointer.color); pointer.moved = false; } } curlProgram.bind(); gl.uniform2f(curlProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight); gl.uniform1i(curlProgram.uniforms.uVelocity, velocity.first[2]); blit(curl[1]); vorticityProgram.bind(); gl.uniform2f(vorticityProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight); gl.uniform1i(vorticityProgram.uniforms.uVelocity, velocity.first[2]); gl.uniform1i(vorticityProgram.uniforms.uCurl, curl[2]); gl.uniform1f(vorticityProgram.uniforms.curl, CURL); gl.uniform1f(vorticityProgram.uniforms.dt, dt); blit(velocity.second[1]); velocity.swap(); divergenceProgram.bind(); gl.uniform2f(divergenceProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight); gl.uniform1i(divergenceProgram.uniforms.uVelocity, velocity.first[2]); blit(divergence[1]); clear(pressure.first[1]); pressureProgram.bind(); gl.uniform2f(pressureProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight); gl.uniform1i(pressureProgram.uniforms.uDivergence, divergence[2]); for (let i = 0; i < PRESSURE_ITERATIONS; i++) { gl.uniform1i(pressureProgram.uniforms.uPressure, pressure.first[2]); blit(pressure.second[1]); pressure.swap(); } gradienSubtractProgram.bind(); gl.uniform2f(gradienSubtractProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight); gl.uniform1i(gradienSubtractProgram.uniforms.uPressure, pressure.first[2]); gl.uniform1i(gradienSubtractProgram.uniforms.uVelocity, velocity.first[2]); blit(velocity.second[1]); velocity.swap(); gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); displayProgram.bind(); gl.uniform1i(displayProgram.uniforms.uTexture, density.first[2]); blit(null); requestAnimationFrame(Update); } function splat (x, y, dx, dy, color) { splatProgram.bind(); gl.uniform1i(splatProgram.uniforms.uTarget, velocity.first[2]); gl.uniform1f(splatProgram.uniforms.aspectRatio, canvas.width / canvas.height); gl.uniform2f(splatProgram.uniforms.point, x / canvas.width, 1.0 - y / canvas.height); gl.uniform3f(splatProgram.uniforms.color, dx, -dy, 1.0); gl.uniform1f(splatProgram.uniforms.radius, SPLAT_RADIUS); blit(velocity.second[1]); velocity.swap(); gl.uniform1i(splatProgram.uniforms.uTarget, density.first[2]); gl.uniform3f(splatProgram.uniforms.color, color[0] * 0.3, color[1] * 0.3, color[2] * 0.3); blit(density.second[1]); density.swap(); } function resizeCanvas () { if (canvas.width != canvas.clientWidth || canvas.height != canvas.clientHeight) { canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; initFramebuffers(); } } canvas.addEventListener('mousemove', (e) => { pointers[0].moved = pointers[0].down; pointers[0].dx = (e.offsetX - pointers[0].x) * 10.0; pointers[0].dy = (e.offsetY - pointers[0].y) * 10.0; pointers[0].x = e.offsetX; pointers[0].y = e.offsetY; }); canvas.addEventListener('touchmove', (e) => { e.preventDefault(); const touches = e.targetTouches; for (let i = 0; i < e.touches.length; i++) { let pointer = pointers[i]; pointer.moved = pointer.down; pointer.dx = (touches[i].pageX - pointer.x) * 10.0; pointer.dy = (touches[i].pageY - pointer.y) * 10.0; pointer.x = touches[i].pageX; pointer.y = touches[i].pageY; } }, false); canvas.addEventListener('mousedown', () => { pointers[0].down = true; pointers[0].color = [Math.random() + 0.2, Math.random() + 0.2, Math.random() + 0.2]; }); canvas.addEventListener('touchstart', (e) => { const touches = e.targetTouches; for (let i = 0; i < touches.length; i++) { if (i >= pointers.length) pointers.push(new pointerPrototype()); pointers[i].id = touches[i].identifier; pointers[i].down = true; pointers[i].x = touches[i].pageX; pointers[i].y = touches[i].pageY; pointers[i].color = [Math.random() + 0.2, Math.random() + 0.2, Math.random() + 0.2]; } }); window.addEventListener('mouseup', () => { pointers[0].down = false; }); window.addEventListener('touchend', (e) => { const touches = e.changedTouches; for (let i = 0; i < touches.length; i++) for (let j = 0; j
$(window).load(function(){ var body = $("body"), universe = $("#universe"), solarsys = $("#solar-system"); var init = function() { body.removeClass('view-2D opening').addClass("view-3D").delay(2000).queue(function() { $(this).removeClass('hide-UI').addClass("set-speed"); $(this).dequeue(); }); }; var setView = function(view) { universe.removeClass().addClass(view); }; $("#toggle-data").click(function(e) { body.toggleClass("data-open data-close"); e.preventDefault(); }); $("#toggle-controls").click(function(e) { body.toggleClass("controls-open controls-close"); e.preventDefault(); }); $("#data a").click(function(e) { var ref = $(this).attr("class"); solarsys.removeClass().addClass(ref); $(this).parent().find('a').removeClass('active'); $(this).addClass('active'); e.preventDefault(); }); $(".set-view").click(function() { body.toggleClass("view-3D view-2D"); }); $(".set-zoom").click(function() { body.toggleClass("zoom-large zoom-close"); }); $(".set-speed").click(function() { setView("scale-stretched set-speed"); }); $(".set-size").click(function() { setView("scale-s set-size"); }); $(".set-distance").click(function() { setView("scale-d set-distance"); }); init(); });
/* Copyright (c) 2013 dissimulate at codepen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Customisable map data */ var map = { tile_size: 16, /* Key vairables: id [required] - an integer that corresponds with a tile in the data array. colour [required] - any javascript compatible colour variable. solid [optional] - whether the tile is solid or not, defaults to false. bounce [optional] - how much velocity is preserved upon hitting the tile, 0.5 is half. jump [optional] - whether the player can jump while over the tile, defaults to false. friction [optional] - friction of the tile, must have X and Y values (e.g {x:0.5, y:0.5}). gravity [optional] - gravity of the tile, must have X and Y values (e.g {x:0.5, y:0.5}). fore [optional] - whether the tile is drawn in front of the player, defaults to false. script [optional] - refers to a script in the scripts section, executed if it is touched. */ keys: [ {id: 0, colour: '#333', solid: 0}, {id: 1, colour: '#888', solid: 0}, {id: 2,colour: '#555',solid: 1,bounce: 0.35}, {id: 3,colour: 'rgba(121, 220, 242, 0.4)',friction: {x: 0.9,y: 0.9},gravity: {x: 0,y: 0.1},jump: 1,fore: 1}, {id: 4,colour: '#777',jump: 1}, {id: 5,colour: '#E373FA',solid: 1,bounce: 1.1}, {id: 6,colour: '#666',solid: 1,bounce: 0}, {id: 7,colour: '#73C6FA',solid: 0,script: 'change_colour'}, {id: 8,colour: '#FADF73',solid: 0,script: 'next_level'}, {id: 9,colour: '#C93232',solid: 0,script: 'death'}, {id: 10,colour: '#555',solid: 1}, {id: 11,colour: '#0FF',solid: 0,script: 'unlock'} ], /* An array representing the map tiles. Each number corresponds to a key */ data: [ [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 6, 6, 6, 6, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 7, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 4, 2, 2, 2, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 1, 2, 2, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 1, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 2, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2], [2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2], [2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2], [2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 8, 1, 1, 1, 2], [2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2], [2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 9, 9, 9, 2, 10, 10, 10, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 11, 2, 2, 2, 2, 4, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2], [2, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 1, 1, 1, 1, 1, 1, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2], [2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 2, 2, 2, 2, 2, 2, 6, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 5, 5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2], [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] ], /* Default gravity of the map */ gravity: { x: 0, y: 0.3 }, /* Velocity limits */ vel_limit: { x: 2, y: 16 }, /* Movement speed when the key is pressed */ movement_speed: { jump: 6, left: 0.3, right: 0.3 }, /* The coordinates at which the player spawns and the colour of the player */ player: { x: 2, y: 2, colour: '#FF9900' }, /* scripts refered to by the "script" variable in the tile keys */ scripts: { /* you can just use "this" instead of your engine variable ("game"), but Codepen doesn't like it */ change_colour: 'game.player.colour = "#"+(Math.random()*0xFFFFFF<<0).toString(16);', /* you could load a new map variable here */ next_level: 'alert("Yay! You won! Reloading map.");game.load_map(map);', death: 'alert("You died!");game.load_map(map);', unlock: 'game.current_map.keys[10].solid = 0;game.current_map.keys[10].colour = "#888";' } }; /* Clarity engine */ var Clarity = function () { this.alert_errors = false; this.log_info = true; this.tile_size = 16; this.limit_viewport = false; this.jump_switch = 0; this.viewport = { x: 200, y: 200 }; this.camera = { x: 0, y: 0 }; this.key = { left: false, right: false, up: false }; this.player = { loc: { x: 0, y: 0 }, vel: { x: 0, y: 0 }, can_jump: true }; window.onkeydown = this.keydown.bind(this); window.onkeyup = this.keyup.bind(this); }; Clarity.prototype.error = function (message) { if (this.alert_errors) alert(message); if (this.log_info) console.log(message); }; Clarity.prototype.log = function (message) { if (this.log_info) console.log(message); }; Clarity.prototype.set_viewport = function (x, y) { this.viewport.x = x; this.viewport.y = y; }; Clarity.prototype.keydown = function (e) { var _this = this; switch (e.keyCode) { case 37: _this.key.left = true; break; case 38: _this.key.up = true; break; case 39: _this.key.right = true; break; } }; Clarity.prototype.keyup = function (e) { var _this = this; switch (e.keyCode) { case 37: _this.key.left = false; break; case 38: _this.key.up = false; break; case 39: _this.key.right = false; break; } }; Clarity.prototype.load_map = function (map) { if (typeof map === 'undefined' || typeof map.data === 'undefined' || typeof map.keys === 'undefined') { this.error('Error: Invalid map data!'); return false; } this.current_map = map; this.current_map.background = map.background || '#333'; this.current_map.gravity = map.gravity || {x: 0, y: 0.3}; this.tile_size = map.tile_size || 16; var _this = this; this.current_map.width = 0; this.current_map.height = 0; map.keys.forEach(function (key) { map.data.forEach(function (row, y) { _this.current_map.height = Math.max(_this.current_map.height, y); row.forEach(function (tile, x) { _this.current_map.width = Math.max(_this.current_map.width, x); if (tile == key.id) _this.current_map.data[y][x] = key; }); }); }); this.current_map.width_p = this.current_map.width * this.tile_size; this.current_map.height_p = this.current_map.height * this.tile_size; this.player.loc.x = map.player.x * this.tile_size || 0; this.player.loc.y = map.player.y * this.tile_size || 0; this.player.colour = map.player.colour || '#000'; this.key.left = false; this.key.up = false; this.key.right = false; this.camera = { x: 0, y: 0 }; this.player.vel = { x: 0, y: 0 }; this.log('Successfully loaded map data.'); return true; }; Clarity.prototype.get_tile = function (x, y) { return (this.current_map.data[y] && this.current_map.data[y][x]) ? this.current_map.data[y][x] : 0; }; Clarity.prototype.draw_tile = function (x, y, tile, context) { if (!tile || !tile.colour) return; context.fillStyle = tile.colour; context.fillRect( x, y, this.tile_size, this.tile_size ); }; Clarity.prototype.draw_map = function (context, fore) { for (var y = 0; y < this.current_map.data.length; y++) { for (var x = 0; x < this.current_map.data[y].length; x++) { if ((!fore && !this.current_map.data[y][x].fore) || (fore && this.current_map.data[y][x].fore)) { var t_x = (x * this.tile_size) - this.camera.x; var t_y = (y * this.tile_size) - this.camera.y; if(t_x < -this.tile_size || t_y < -this.tile_size || t_x > this.viewport.x || t_y > this.viewport.y) continue; this.draw_tile( t_x, t_y, this.current_map.data[y][x], context ); } } } if (!fore) this.draw_map(context, true); }; Clarity.prototype.move_player = function () { var tX = this.player.loc.x + this.player.vel.x; var tY = this.player.loc.y + this.player.vel.y; var offset = Math.round((this.tile_size / 2) - 1); var tile = this.get_tile( Math.round(this.player.loc.x / this.tile_size), Math.round(this.player.loc.y / this.tile_size) ); if(tile.gravity) { this.player.vel.x += tile.gravity.x; this.player.vel.y += tile.gravity.y; } else { this.player.vel.x += this.current_map.gravity.x; this.player.vel.y += this.current_map.gravity.y; } if (tile.friction) { this.player.vel.x *= tile.friction.x; this.player.vel.y *= tile.friction.y; } var t_y_up = Math.floor(tY / this.tile_size); var t_y_down = Math.ceil(tY / this.tile_size); var y_near1 = Math.round((this.player.loc.y - offset) / this.tile_size); var y_near2 = Math.round((this.player.loc.y + offset) / this.tile_size); var t_x_left = Math.floor(tX / this.tile_size); var t_x_right = Math.ceil(tX / this.tile_size); var x_near1 = Math.round((this.player.loc.x - offset) / this.tile_size); var x_near2 = Math.round((this.player.loc.x + offset) / this.tile_size); var top1 = this.get_tile(x_near1, t_y_up); var top2 = this.get_tile(x_near2, t_y_up); var bottom1 = this.get_tile(x_near1, t_y_down); var bottom2 = this.get_tile(x_near2, t_y_down); var left1 = this.get_tile(t_x_left, y_near1); var left2 = this.get_tile(t_x_left, y_near2); var right1 = this.get_tile(t_x_right, y_near1); var right2 = this.get_tile(t_x_right, y_near2); if (tile.jump && this.jump_switch > 15) { this.player.can_jump = true; this.jump_switch = 0; } else this.jump_switch++; this.player.vel.x = Math.min(Math.max(this.player.vel.x, -this.current_map.vel_limit.x), this.current_map.vel_limit.x); this.player.vel.y = Math.min(Math.max(this.player.vel.y, -this.current_map.vel_limit.y), this.current_map.vel_limit.y); this.player.loc.x += this.player.vel.x; this.player.loc.y += this.player.vel.y; this.player.vel.x *= .9; if (left1.solid || left2.solid || right1.solid || right2.solid) { /* fix overlap */ while (this.get_tile(Math.floor(this.player.loc.x / this.tile_size), y_near1).solid || this.get_tile(Math.floor(this.player.loc.x / this.tile_size), y_near2).solid) this.player.loc.x += 0.1; while (this.get_tile(Math.ceil(this.player.loc.x / this.tile_size), y_near1).solid || this.get_tile(Math.ceil(this.player.loc.x / this.tile_size), y_near2).solid) this.player.loc.x -= 0.1; /* tile bounce */ var bounce = 0; if (left1.solid && left1.bounce > bounce) bounce = left1.bounce; if (left2.solid && left2.bounce > bounce) bounce = left2.bounce; if (right1.solid && right1.bounce > bounce) bounce = right1.bounce; if (right2.solid && right2.bounce > bounce) bounce = right2.bounce; this.player.vel.x *= -bounce || 0; } if (top1.solid || top2.solid || bottom1.solid || bottom2.solid) { /* fix overlap */ while (this.get_tile(x_near1, Math.floor(this.player.loc.y / this.tile_size)).solid || this.get_tile(x_near2, Math.floor(this.player.loc.y / this.tile_size)).solid) this.player.loc.y += 0.1; while (this.get_tile(x_near1, Math.ceil(this.player.loc.y / this.tile_size)).solid || this.get_tile(x_near2, Math.ceil(this.player.loc.y / this.tile_size)).solid) this.player.loc.y -= 0.1; /* tile bounce */ var bounce = 0; if (top1.solid && top1.bounce > bounce) bounce = top1.bounce; if (top2.solid && top2.bounce > bounce) bounce = top2.bounce; if (bottom1.solid && bottom1.bounce > bounce) bounce = bottom1.bounce; if (bottom2.solid && bottom2.bounce > bounce) bounce = bottom2.bounce; this.player.vel.y *= -bounce || 0; if ((bottom1.solid || bottom2.solid) && !tile.jump) { this.player.on_floor = true; this.player.can_jump = true; } } // adjust camera var c_x = Math.round(this.player.loc.x - this.viewport.x/2); var c_y = Math.round(this.player.loc.y - this.viewport.y/2); var x_dif = Math.abs(c_x - this.camera.x); var y_dif = Math.abs(c_y - this.camera.y); if(x_dif > 5) { var mag = Math.round(Math.max(1, x_dif * 0.1)); if(c_x != this.camera.x) { this.camera.x += c_x > this.camera.x ? mag : -mag; if(this.limit_viewport) { this.camera.x = Math.min( this.current_map.width_p - this.viewport.x + this.tile_size, this.camera.x ); this.camera.x = Math.max( 0, this.camera.x ); } } } if(y_dif > 5) { var mag = Math.round(Math.max(1, y_dif * 0.1)); if(c_y != this.camera.y) { this.camera.y += c_y > this.camera.y ? mag : -mag; if(this.limit_viewport) { this.camera.y = Math.min( this.current_map.height_p - this.viewport.y + this.tile_size, this.camera.y ); this.camera.y = Math.max( 0, this.camera.y ); } } } if(this.last_tile != tile.id && tile.script) { eval(this.current_map.scripts[tile.script]); } this.last_tile = tile.id; }; Clarity.prototype.update_player = function () { if (this.key.left) { if (this.player.vel.x > -this.current_map.vel_limit.x) this.player.vel.x -= this.current_map.movement_speed.left; } if (this.key.up) { if (this.player.can_jump && this.player.vel.y > -this.current_map.vel_limit.y) { this.player.vel.y -= this.current_map.movement_speed.jump; this.player.can_jump = false; } } if (this.key.right) { if (this.player.vel.x < this.current_map.vel_limit.x) this.player.vel.x += this.current_map.movement_speed.left; } this.move_player(); }; Clarity.prototype.draw_player = function (context) { context.fillStyle = this.player.colour; context.beginPath(); context.arc( this.player.loc.x + this.tile_size / 2 - this.camera.x, this.player.loc.y + this.tile_size / 2 - this.camera.y, this.tile_size / 2 - 1, 0, Math.PI * 2 ); context.fill(); }; Clarity.prototype.update = function () { this.update_player(); }; Clarity.prototype.draw = function (context) { this.draw_map(context, false); this.draw_player(context); }; /* Setup of the engine */ window.requestAnimFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { return window.setTimeout(callback, 1000 / 60); }; var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'); canvas.width = 400; canvas.height = 400; var game = new Clarity(); game.set_viewport(canvas.width, canvas.height); game.load_map(map); /* Limit the viewport to the confines of the map */ game.limit_viewport = true; var Loop = function() { ctx.fillStyle = '#333'; ctx.fillRect(0, 0, canvas.width, canvas.height); game.update(); game.draw(ctx); window.requestAnimFrame(Loop); }; Loop();
Use the left, right and up arrow keys to move.
//nothing to see here
[ Free Tutorials ]
102人正在观看
106人正在观看
185人正在观看
125人正在观看
98人正在观看
95人正在观看
88人正在观看
195人正在观看
163人正在观看
105人正在观看
99人正在观看
205人正在观看
96人正在观看
85人正在观看
150人正在观看
156人正在观看
95人正在观看
88人正在观看
111人正在观看
教
程
列
表
>
第一节:Cocos2d-JS概述
播放:95040
第二节:开发环境搭建
播放:88716
第三节:Cocos2d-JS安装配置
播放:82598
第四节:实战:游戏消灭寿司
开发-核心API(1)
播放:98486
第五节:实战:游戏消灭寿司
开发-核心API(2)
播放:95815
第六节:实战:游戏消灭寿司
开发-添加内容到场景(1)
播放:90287
第七节:实战:游戏消灭寿司
开发-添加内容到场景(2)
播放:85469
第八节:实战:游戏消灭寿司
开发-action(1)
播放:82586
第九节:实战:游戏消灭寿司
开发-action小结
播放:89521
第十节:实战:游戏消灭寿司
开发-移除屏幕SushiSprite
播放:83547
第十一节:实战:游戏消灭寿司
开发-场景转换
播放:85289
第十二节:实战:游戏消灭寿司
开发-事件管理器创建交互(1)
播放:83558
第十三节:实战:游戏消灭寿司
开发-事件管理器创建交互(2)
播放:88824
第十四节:实战:游戏消灭寿司
开发-SushiSprite消失动画
播放:82250
第十五节:实战:游戏消灭寿司
开发-项目其他工作(1)
播放:81110
第十六节:实战:游戏消灭寿司
开发-项目其他工作(2)
播放:85294
第十七节:实战:游戏消灭寿司
开发-项目其他工作(3)
播放:87123
第十八节:实战:游戏消灭寿司
开发-项目其他工作(4)
播放:82563
第十九节:实战:游戏消灭寿司
开发-项目其他工作(5)
播放:85486
HTML,CSS,JS核心代码全览
流体模拟 59526
3D太阳系 58524
HTML5小游戏 88257
万花筒 62548
目不转睛的狮子 56652
物理仿真 59621
我们不共享单车,我们只共享干货
Web前端基础教程
IT培训网与Web前端
IT培训网简介
IT培训网与Web
HTML5篇
简介
浏览器支持
内联 SVG
拖放(Drag 和 Drop)
CSS3篇
简介
边框
背景
3D转换
JavaScript篇
用法
输出
语法
语句
IT培训网教育集团【美股交易代码:TEDU】(简称IT培训网集团)成立于2002年9月,2014年4月,IT培训网教育集团成功在美国纳斯达克上市,融资1亿3千万美元,是中国在美国上市的职业教育集团,根据IDC的数据,IT培训网教育集团是目前国内领先的职业教育机构,市场份额超过8.3%。 IT培训网集团以中关村为依托,目前已在北京、上海、广州、深圳、大连、南京、武汉、杭州、西安、苏州、成都、沈阳等58个大中城市成立了171家学习中心,拥有员工超过7000人,2016年培训量已达11万人次。IT培训网集团凭借雄厚的技术研发实力、过硬的教学质量、成熟的就业服务体系,在用人企业中树立了良好的口碑,连续3年复合增长率超过50%。 IT培训网的15年,是互联网快速发展的15年。在互联网发展的不同阶段,IT培训网的课程紧跟互联网发展的步伐,15年不断的创新,打造覆盖IT全产业链的职业课程版图。目前开设Java、Java大数据、Android、iOS、PHP、软件测试、嵌入式、C++、C#、UID、UED、产品经理、Linux云计算、Web前端、VR、网络营销、高级电商、主办会计、Python等21大课程体系,为中国企业提供全面的IT互联网人才服务,并为全行业提供高级应用型人才。IT培训网拥有行业内完善的教研团队,200位知名讲师,1500名教研人员,全方位保障学员来自一线企业的知名技术专家团队担纲教学,并且一线的行业专家组合授课,课程更具较强实操性。 IT培训网教育集团确定了”一站式职业人才培训提供商、一站式人才输送提供商、一站式软件开发提供商”的三大定位。把“缔造年轻人的中国梦”作为所有IT培训网人奋斗的企业使命。
IT培训网发展的十五年,就是推动中国高校校企合作、产融结合的十五年,就是推动中国高校职业教育改革的十五年,从IT培训网成立之初,高校一直是IT培训网的亲密合作伙伴,并推出品牌教育品牌“英才添翼”,“英才添翼”始终致力于成为中国职业教育改革一站式解决方案提供商,以合作办学,合作育人,合作就业,合作发展为主线,提出了IT培训网高校教学体系解决方案,IT培训网高校全方位实习解决方案,IT培训网高校大学生就业解决方案、企业级师资培训解决方案四大解决方案。IT培训网“英才添翼”与全国800余家高校深度合作、专业共建,把企业的项目搬到学校,把学校的课堂搬到企业,工程师和高校老师共同协作双师教学,实现了产教共融,协同发展,更好的培养高素质人才。从2016年开始,IT培训网集团成为教育部产学合作协同育人单位。 IT培训网发展离不开与企业的密切合作,IT培训网在全国建立5大软件人才中心600人才顾问每天不断与全国上万家企业保持联系和沟通。通过15年IT培训网不断地探索与尝试,IT培训网与国内外知名企业建立人才推荐,人才定制培养、人才租赁与外包、代理校园招聘、IT猎头、企业内训等多样化的合作方式和一站式的服务体系。截止到2016年12月底,IT培训网与全国数万家知名企业建立合作关系,每个月在IT培训网全国中心有近600场的企业双选会,IT培训网还会定期做专场招聘会,正是与企业的紧密合作关系,IT培训网学员保持行业领先的学员就业率,2016年实现了95%以上的就业率。
IT培训网教育集团以良好的教学及经营模式,近年来荣获了各界专业机构的颁奖
2006、2007、2008、2009连续4年入选德勤评选的“中国高科技高成长50强公司”、“亚太地区高科技高成长500强公司”;
中关村管理委员会指定的“软件人才培养示范基地”;
北京市商务委、北京市教委联合评为“首批服务外包人才培训机构”;
荣获《计算机世界》评选的“就业服务杰出贡献奖”;
荣获《中国计算机报》评选的“最具影响力培训机构奖”;
被搜狐评为“中国22大教育集团”;
被腾讯评为“中国大学生心目中最具影响力的IT品牌”;
2010年与百度、搜狐、中兴电子等著名企业一起被欧美同学会评为中国海外归国人员创业“腾飞奖”中国50强优秀企业;
2011年获得中央电视台评选的中国教育行业“领军企业”;
2012年9月获凤凰网、网易财经、影响力峰会组委会评选的“2012年度最具信赖企业”大奖;
2012、2013年 荣获普华永道和高企协颁发“2011中关村高成长企业TOP100”;
2013年荣获智联招聘中国年度雇主“北京30强”企业等大奖;
百度“2014百度数据资产卓越奖”;
新浪网“2015新浪中国品牌影响力教育集团”;
腾讯“2015年度影响力教育集团”;
中国好教育“广受学员好评的职业教育机构”。
a、双结合: 手写代码加代码工具双结合!
b、功底实: 扎实代码功底,应对企业需求!
c、懂后台: 懂后台的Web,更有效团队配合!
d、擅混编: 混编App 开发,发展前景更广阔!
e、会微信: 微信公众号及小程序开发,更适应市场需求!
“学期内培优”教学模式推出背景 继2016 年IT培训网推出因材施教、分级培优创新教学模式之后,为了扩大因材施教、分级培优的教学范围,让更多的学员能够受益于因材施教、分级培优教学模式。2017 年IT培训网重磅推出基于因材施教、分级培优创新教学模式的“IT培训网学期内培优”。 IT培训网“学期内培优”是什么? IT培训网学期内培优是指,同一个班的学员,可以根据学员学习进度的快慢进行分级培优教学,学习进度快的学员选择学期内培优教学模式进行学习,学习进度慢的可以按照正常的就业班教学进度学习。
王春梅
IT培训网集团Web前端课程总监
经历:哈尔滨工业大学硕士,曾任用友软件股份有限公司前资深项目经理,具备多年的的软件设计和开发经验,作为项目经理和主要设计人员,主持开发过多个产品,具有丰富的产品和项目的实战经验和管理经验。
赵旭
IT培训网集团互联网技术专家
经历:曾工作于吉林省统计局、启明信息技术有限公司、日本インタセクト株式会社等机构担任系统开发工程师、前端开发工程师等工作。具备多年互联网程序开发经验。多年Java EE /.NET / Html + Css /Javascript/ jQuery / Ajax技术的开发及授课经验。
张东
IT培训网集团JavaScript专家
经历:美国PMP 认证高级项目经理,微软认证解决方案开发专家。先后在中软国际、中国搜索、太极计算机担任高级开发工程师,架构师,项目经理。曾担任中央外汇管理中心、中国石油、二炮工程研究院、首都国际机场技术咨询顾问。
杨燕
IT培训网集团Web技术专家
经历:多年互联网领域研发经验,包括商务网站、管理系统、移动应用等研发经验。曾参与研发的项目涉及领域包括航天系统、总参谋部队、华北国家电网等,并在大唐电信任职高级工程师期间积累了丰富的教学实战经验。
张众磊
IT培训网集团JS框架专家
经历:先后就职于国家电网、凌阳科技,并担任研发组长、项目经理,具有6 年Linux 平台、移动APP 的开发经验,具备深厚的开发和培训功底。
魏晓武
IT培训网集团Web技术专家
经历:曾在多家IT 培训公司工作,具备多年互联网项目开发经验,熟练应用HTML5CSS3,js,jq 等前端技术。有预之网,北师大暑期实践网等在线项目,曾经给企业开发过在线购物系统(PHP+ 前端),在线学习系统(java) 等。
程涛
IT培训网集团Web前端技术专家
IT培训网集团JavaScript 技术专家经历:曾工作于神星科技、东方标准等机构,先后任教于东方标准、安博教育、IT培训网科技。具备多年互联网项目开发及管理经验,十年以上JavaEE、PHP、大数据等多方向授课经验。
李文华
IT培训网集团Web前端技术专家
经历:曾工作于中国互联网中心、中软国际等机构,先后任教于华育国际、IBM 产品基地、IT培训网科技等组织。具备多年互联网项目开发及管理经验,十年以上JavaEE、PHP、移动开发等多方向授课经验。
HTML5是HTML最近的修订版本,2014年10月由万维网联盟(W3C)完成标准制定。HTML5的设计目的是为了在移动设备上支持多媒体。同时HTML5 简单易学。
HTML5 是下一代 HTML 标准。现仍处于完善之中。然而,大部分现代浏览器已经具备了某些 HTML5 支持
HTML5 是 W3C 与 WHATWG 合作的结果,WHATWG 指 Web Hypertext Application Technology Working Group。WHATWG 致力于 web 表单和应用程序,而 W3C 专注于 XHTML 2.0。在 2006 年,双方决定进行合作,来创建一个新版本的 HTML。
HTML5 中的一些有趣的新特性:
• 用于绘画的 canvas 元素
• 用于媒介回放的 video 和 audio 元素
• 对本地离线存储的更好的支持
• 新的特殊内容元素,比如article、footer、header、nav、section
• 新的表单控件,比如 calendar、date、time、email、url、search
• 新元素
• 新属性
• 完全支持 CSS3
• Video 和 Audio
• 2D/3D 制图
• 本地存储
• 本地 SQL 数据
• Web 应用
使用 HTML5 你可以简单地开发应用
• 本地数据存储
• 访问本地文件
• 本地 SQL 数据
• 缓存引用
• Javascript 工作者
• XHTMLHttpRequest 2
使用 HTML5 你可以简单的绘制图形:
• 新选择器
• 新属性
• 动画
• 2D/3D 转换
• 圆角
• 阴影效果
• 可下载的字体
新表单元素, 新属性,新输入类型,自动验证。
以下的 HTML 4.01 元素在HTML5中已经被删除:
最近版本的 Safari、Chrome、Firefox 以及 Opera 支持某些 HTML5 特性。Internet Explorer 9 将支持某些 HTML5 特性。
IE9 以下版本浏览器兼容HTML5的方法,使用本站的静态资源的html5shiv包:
现代的浏览器都支持 HTML5。此外,所有浏览器,包括旧的和最近的,对无法识别的元素会作为内联元素自动处理。正因为如此,你可以 "教会" 浏览器处理 "未知" 的 HTML 元素。
HTML5 定了 8 个新的 HTML 语义(semantic) 元素。所有这些元素都是 块级 元素。为了能让旧版本的浏览器正确显示这些元素,你可以设置 CSS 的 display 属性值为 block:
实例:
JavaScript 语句 document.createElement("myHero") 是为 IE 浏览器添加新的元素。
你可以使用以上的方法来为 IE 浏览器添加 HTML5 元素,但是:Internet Explorer 8 及更早 IE 版本的浏览器不支持以上的方式。
我们可以使用 Sjoerd Visscher 创建的 "HTML5 Enabling JavaScript", " shiv" 来解决该问题:
以上代码是一个注释,作用是在 IE 浏览器的版本小于 IE9 时将读取 html5.js 文件,并解析它。 注意:国内用户请使用本站静态资源库(Google 资源库在国内不稳定):
针对IE浏览器html5shiv 是比较好的解决方案。html5shiv主要解决HTML5提出的新的元素不被IE6-8识别,这些新元素不能作为父节点包裹子元素,并且不能应用CSS样式。
实例:
运行结果:
我的第一篇文章
SVG 指可伸缩矢量图形 (Scalable Vector Graphics)
SVG 用于定义用于网络的基于矢量的图形
SVG 使用 XML 格式定义图形
SVG 图像在放大或改变尺寸的情况下其图形质量不会有损失
SVG 是万维网联盟的标准
与其他图像格式相比(比如 JPEG 和 GIF),使用 SVG 的优势在于:
• SVG 图像可通过文本编辑器来创建和修改
• SVG 图像可被搜索、索引、脚本化或压缩
• SVG 是可伸缩的
• SVG 图像可在任何的分辨率下被高质量地打印
• SVG 可在图像质量不下降的情况下被放大
Internet Explorer 9+, Firefox, Opera, Chrome, 和 Safari 支持内联SVG.
在 HTML5 中,您能够将 SVG 元素直接嵌入 HTML 页面中:
实例:
运行结果:
SVG 是一种使用 XML 描述 2D 图形的语言。Canvas 通过 JavaScript 来绘制 2D 图形。
SVG 基于 XML,这意味着 SVG DOM 中的每个元素都是可用的。您可以为某个元素附加JavaScript 事件处理器。在 SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器能够自动重现图形。
Canvas 是逐像素进行渲染的。在 canvas 中,一旦图形被绘制完成,它就不会继续得到浏览器的关注。如果其位置发生变化,那么整个场景也需要重新绘制,包括任何或许已被图形覆盖的对象。
下表列出了 canvas 与 SVG 之间的一些不同之处。
拖放(Drag 和 drop)是 HTML5 标准的组成部分。
拖放是一种常见的特性,即抓取对象以后拖到另一个位置。在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放。
Internet Explorer 9+, Firefox, Opera, Chrome, 和 Safari 支持拖动。注意:Safari 5.1.2不支持拖动。
下面的例子是一个简单的拖放实例:
实例:
运行结果:
它看上去也许有些复杂,不过我们可以分别研究拖放事件的不同部分。
首先,为了使元素可拖动,把 draggable 属性设置为 true :
然后,规定当元素被拖动时,会发生什么。
在上面的例子中,ondragstart 属性调用了一个函数,drag(event),它规定了被拖动的数据。
dataTransfer.setData() 方法设置被拖数据的数据类型和值:
在这个例子中,数据类型是 "Text",值是可拖动元素的 id ("drag1")。
ondragover 事件规定在何处放置被拖动的数据。
默认地,无法将数据/元素放置到其他元素中。如果需要设置允许放置,我们必须阻止对元素的默认处理方式。
这要通过调用 ondragover 事件的 event.preventDefault() 方法:
当放置被拖数据时,会发生 drop 事件。
在上面的例子中,ondrop 属性调用了一个函数,drop(event):
代码解释:
调用 preventDefault() 来避免浏览器对数据的默认处理(drop 事件的默认行为是以链接形式打开)
通过 dataTransfer.getData("Text") 方法获得被拖的数据。该方法将返回在 setData() 方法中设置为相同类型的任何数据。
被拖数据是被拖元素的 id ("drag1")
把被拖元素追加到放置元素(目标元素)中
对CSS3已完全向后兼容,所以你就不必改变现有的设计。浏览器将永远支持CSS2。
CSS3被拆分为"模块"。旧规范已拆分成小块,还增加了新的。
一些最重要CSS3模块如下:
• 选择器
• 盒模型
• 背景和边框
• 文字特效
• 2D/3D转换
• 动画
• 多列布局
• 用户界面
W3C的CSS3规范仍在开发。但是,许多新的CSS3属性已在现代浏览器使用。
用 CSS3,你可以创建圆角边框,添加阴影框,并作为边界的形象而不使用设计程序,如 Photoshop。
在本章中,您将了解以下的边框属性:
• border-radiusbr
• box-shadow
• border-image
用 CSS3,你可以创建圆角边框,添加阴影框,并作为边界的形象而不使用设计程序,如 Photoshop。 在本章中,您将了解以下的边框属性:
在 CSS2 中添加圆角棘手。我们不得不在每个角落使用不同的图像。
在 CSS3 中 border-radius 属性被用于创建圆角:
这是圆角边框!
实例:
在div中添加圆角元素:
运行结果:
CSS3 中的 box-shadow 属性被用来添加阴影:
实例:
在div中添加box-shadow属性
有了 CSS3 的 border-image 属性,你可以使用图像创建一个边框:border-image 属性允许你指定一个图片作为边框! 用于创建上文边框的原始图像:在 div 中使用图片创建边框:
CSS3中包含几个新的背景属性,提供更大背景元素控制。
在本章您将了解以下背景属性:
• background-image
• background-size
• background-origin
• background-clip
您还将学习如何使用多重背景图像。
CSS3中可以通过background-image属性添加背景图片。不同的背景图像和图像用逗号隔开,所有的图片中显示在最顶端的为第一张。
CSS3中可以通过background-image属性添加背景图片。不同的背景图像和图像用逗号隔开,所有的图片中显示在最顶端的为第一张。
实例:
运行结果:
background-size指定背景图像的大小。CSS3以前,背景图像大小由图像的实际大小决定。 CSS3中可以指定背景图片,让我们重新在不同的环境中指定背景图片的大小。您可以指定像素或百分比大小。
你指定的大小是相对于父元素的宽度和高度的百分比的大小。
实例 1:
重置背景图像:
运行结果:
Lorem ipsum,中文又称“乱数假文”, 是指一篇常用于排版设计领域的拉丁文文章 ,主要的目的为测试文章或文字在不同字型、版型下看起来的效果。
实例 2:
伸展背景图像完全填充内容区域:
运行结果:
background-Origin属性指定了背景图像的位置区域。content-box, padding-box,和 border-box区域内可以放置背景图像。
实例:
在 content-box 中定位背景图片:
运行结果:
CSS3 允许你添加多个背景图像。
在 body 元素中设置两个背景图像:
CSS3 允许您使用 3D 转换来对元素进行格式化。
在本章中,您将学到其中的一些 3D 转换方法:
•rotateX()
•rotateY()
rotateX()方法,围绕其在一个给定度数X轴旋转的元素。
实例:
rotateY()方法,围绕其在一个给定度数Y轴旋转的元素。
实例:
下表列出了所有的转换属性:
如需在 HTML 页面中插入 JavaScript,请使用 script 标签。
在本例中,JavaScript 会在页面加载时向 HTML 的 body标签里写文本:
实例:
上面例子中的 JavaScript 语句,会在页面加载时执行。
通常,我们需要在某个事件发生时执行代码,比如当用户点击按钮时。
如果我们把 JavaScript 代码放入函数中,就可以在事件发生时调用该函数。
您将在稍后的章节学到更多有关 JavaScript 函数和事件的知识
您可以在 HTML 文档中放入不限数量的脚本。
脚本可位于 HTML 的 body 标签 或 head 标签中,或者同时存在于两个部分中。
通常的做法是把函数放入
在本例中,我们把一个 JavaScript 函数放置到 HTML 页面的 head 标签部分。
该函数会在点击按钮时被调用:
实例:
在本例中,我们把一个 JavaScript 函数放置到 HTML 页面的 body 标签 部分。
该函数会在点击按钮时被调用:
实例:
也可以把脚本保存到外部文件中。外部文件通常包含被多个网页使用的代码。
外部 JavaScript 文件的文件扩展名是 .js。
如需使用外部文件,请在 script 标签的 "src" 属性中设置该 .js 文件:
实例:
你可以将脚本放置于 head 标签 或者 body 标签中 实际运行效果与您在 script 标签中编写脚本完全一致。
myScript.js 文件代码如下:
外部脚本不能包含 script 标签。
JavaScript 没有任何打印或者输出的函数。
JavaScript 可以通过不同的方式来输出数据:
• 使用 window.alert() 弹出警告框。
• 使用 document.write() 方法将内容写到 HTML 文档中。
• 使用 innerHTML 写入到 HTML 元素。
• 使用 console.log() 写入到浏览器的控制台。
你可以弹出警告框来显示数据:
实例:
如需从 JavaScript 访问某个 HTML 元素,您可以使用 document.getElementById(id) 方法。
请使用 "id" 属性来标识 HTML 元素,并 innerHTML 来获取或插入元素内容:
实例:
以上 JavaScript 语句(在 script 标签中)可以在 web 浏览器中执行:
document.getElementById("demo") 是使用 id 属 性来查找 HTML 元素的 JavaScript 代码 。
innerHTML = "段落已修改。" 是用于修改元素的 HTML 内容(innerHTML)的 JavaScript 代码。
在大多数情况下,在本教程中,我们将使用上面描述的方法来输出:
下面的例子直接把 id="demo" 的
元素写到 HTML 文档输出中:
出于测试目的,您可以将JavaScript直接写在HTML 文档中:
实例:
请使用 document.write() 仅仅向文档输出写内容。
如果在文档已完成加载后执行 document.write,整个 HTML 页面将被覆盖。
实例:
如果您的浏览器支持调试,你可以使用 console.log() 方法在浏览器中显示 JavaScript 值。
浏览器中使用 F12 来启用调试模式, 在调试窗口中点击 "Console" 菜单。
实例:
实例 console 截图:
avaScript 是一个程序语言。语法规则定义了语言结构。
JavaScript 是一个脚本语言。
在编程语言中,变量用于存储数据值。
JavaScript 使用关键字 var 来定义变量, 使用等号来为变量赋值:
运行结果:
6
变量可以通过变量名访问。在指令式语言中,变量通常是可变的。字面量是一个恒定的值。
JavaScript使用 算术运算符来计算值:
运行结果:
110
运行结果:
110
在 HTML 中,JavaScript 语句向浏览器发出的命令。
语句是用分号分隔:
JavaScript 关键字用于标识要执行的操作。
和其他任何编程语言一样,JavaScript 保留了一些关键字为自己所用。
var 关键字告诉浏览器创建一个新的变量:
JavaScript 同样保留了一些关键字,这些关键字在当前的语言版本中并没有使用,但在以后 JavaScript 扩展中会用到。
JavaScript 关键字必须以字母、下划线(_)或美元符($)开始。
后续的字符可以是字母、数字、下划线或美元符(数字是不允许作为首字符出现的,以便 JavaScript 可以轻易区分开关键字和数字)。
以下是 JavaScript 中最重要的保留字(按字母顺序):
不是所有的 JavaScript 语句都是"命令"。双斜杠 // 后的内容将会被浏览器忽略:
JavaScript 有多种数据类型:数字,字符串,数组,对象等等:
编程语言中,数据类型是一个非常重要的内容。
为了可以操作变量,了解数据类型的概念非常重要。
如果没有使用数据类型,以下实例将无法执行:
16 加上 "Volvo" 是如何计算呢? 以上会产生一个错误还是输出以下结果呢?
你可以在浏览器尝试执行以上代码查看效果。
在接下来的章节中你将学到更多关于数据类型的知识。
JavaScript 语句可以写在函数内,函数可以重复引用:
引用一个函数 = 调用函数(执行函数内的语句)。
JavaScript 对大小写是敏感的。
当编写 JavaScript 语句时,请留意是否关闭大小写切换键。
函数 getElementById 与 getElementbyID 是不同的。
同样,变量 myVariable 与 MyVariable 也是不同的。
JavaScript 使用 Unicode 字符集。
Unicode 覆盖了所有的字符,包含标点等字符。
JavaScript 语句向浏览器发出的命令。语句的作用是告诉浏览器该做什么。
JavaScript 语句是发给浏览器的命令。这些命令的作用是告诉浏览器要做的事情。
下面的 JavaScript 语句向 id="demo" 的 HTML 元素输出文本 "你好 Dolly" :
实例:/p>
运行结果:
你好 Dolly
分号用于分隔 JavaScript 语句。通常我们在每条可执行的语句结尾添加分号。使用分号的另一用处是在一行中编写多条语句。
实例:
以上实例也可以这么写:
运行结果:
3
3
您也可能看到不带有分号的案例。 在 JavaScript 中,用分号来结束语句是可选的。
JavaScript 代码是 JavaScript 语句的序列。浏览器按照编写顺序依次执行每条语句。本例向网页输出一个标题和两个段落:
实例:
运行结果:
你好 Dolly
你最近怎么样?
JavaScript 可以分批地组合起来。代码块以左花括号开始,以右花括号结。代码块的作用是一并地执行语句序列。
本例向网页输出一个标题和两个段落:
实例:
运行结果:
我是一个段落。
我是一个div。
当您点击上面的按钮时,两个元素会改变。
JavaScript 语句通常以一个 语句标识符 为开始,并执行该语句。语句标识符是保留关键字不能作为变量名使用。
下表列出了 JavaScript 语句标识符 (关键字) :
JavaScript 会忽略多余的空格。您可以向脚本添加空格,来提高其可读性。下面的两行代码是等效的:
您可以在文本字符串中使用反斜杠对代码行进行换行。下面的例子会正确地显示:
不过,您不能像这样折行:
提示:JavaScript 是脚本语言。浏览器会在读取代码时,逐行地执行脚本代码。而对于传统编程来说,会在执行前对所有代码进行编译。