UNPKG

littlejsengine

Version:

LittleJS - Tiny and Fast HTML5 Game Engine

176 lines (146 loc) 5.67 kB
/* Little JS Breakout Game - A simple breakout game - Includes sound and particles - Uses a post processing effect - Control with mouse, touch, or gamepad */ 'use strict'; // import LittleJS module import * as LJS from '../../dist/littlejs.esm.js'; import * as GameObjects from './gameObjects.js'; const {vec2, hsl} = LJS; /////////////////////////////////////////////////////////////////////////////// // game objects export let ball, score, brickCount, paddle; export const levelSize = vec2(38, 20); export function changeBrickCount(delta) { brickCount += delta; // increase score when brick is destroyed if (delta < 0) score -= delta; } /////////////////////////////////////////////////////////////////////////////// function gameReset() { // reset game objects LJS.engineObjectsDestroy(); score = 0; brickCount = 0; // spawn bricks const pos = vec2(); for (pos.x = 4; pos.x <= levelSize.x-4; pos.x += 2) for (pos.y = 12; pos.y <= levelSize.y-2; pos.y += 1) new GameObjects.Brick(pos); // create walls new GameObjects.Wall(vec2(-.5,levelSize.y/2), vec2(1,100)); // top new GameObjects.Wall(vec2(levelSize.x+.5,levelSize.y/2), vec2(1,100)); // left new GameObjects.Wall(vec2(levelSize.x/2,levelSize.y+.5), vec2(100,1)); // right // spawn player paddle paddle = new GameObjects.Paddle(vec2(levelSize.x/2-12, 1)); // reset ball ball = 0; } /////////////////////////////////////////////////////////////////////////////// function gameInit() { LJS.setCanvasFixedSize(vec2(1920, 1080)); // 1080p LJS.setCameraPos(levelSize.scale(.5)); // center camera LJS.setCameraScale(48); // set up a post processing shader setupPostProcess(); // start a new game gameReset(); } /////////////////////////////////////////////////////////////////////////////// function gameUpdate() { // spawn ball if (!ball && (LJS.mouseWasPressed(0) || LJS.gamepadWasPressed(0))) ball = new GameObjects.Ball(vec2(levelSize.x/2, levelSize.y/2)); if (ball && ball.pos.y < -1) { // destroy ball if it goes below the level ball.destroy(); ball = 0; } if (LJS.keyWasPressed('KeyR')) gameReset(); } /////////////////////////////////////////////////////////////////////////////// function gameUpdatePost() { } /////////////////////////////////////////////////////////////////////////////// function gameRender() { // draw a the background LJS.drawRect(LJS.cameraPos, levelSize.scale(2), hsl(0,0,.5)); LJS.drawRect(LJS.cameraPos, levelSize, hsl(0,0,.02)); } /////////////////////////////////////////////////////////////////////////////// function gameRenderPost() { // use built in image font for text const font = new LJS.FontImage; font.drawTextOverlay('Score: ' + score, LJS.cameraPos.add(vec2(0,9.7)), .15, true); if (!brickCount) font.drawTextOverlay('You Win!', LJS.cameraPos.add(vec2(0,-5)), .2, true); else if (!ball) font.drawTextOverlay('Click to Play', LJS.cameraPos.add(vec2(0,-5)), .2, true); } /////////////////////////////////////////////////////////////////////////////// // an example shader that can be used to apply a post processing effect function setupPostProcess() { const televisionShader = ` // Simple TV Shader Code float hash(vec2 p) { p=fract(p*.3197); return fract(1.+sin(51.*p.x+73.*p.y)*13753.3); } void mainImage(out vec4 c, vec2 p) { // setup the shader vec2 uv = p; p /= iResolution.xy; c = texture(iChannel0, p); // static noise const float staticAlpha = .1; const float staticScale = .002; c += staticAlpha * hash(floor(p/staticScale) + mod(iTime*500., 1e3)); // scan lines const float scanlineScale = 2.; const float scanlineAlpha = .3; c *= 1. - scanlineAlpha*cos(p.y*2.*iResolution.y/scanlineScale); { // bloom effect const float blurSize = .002; const float bloomIntensity = .2; // 5-tap Gaussian blur vec4 bloom = vec4(0); bloom += texture(iChannel0, p + vec2(-2.*blurSize, 0)) * .12; bloom += texture(iChannel0, p + vec2( -blurSize, 0)) * .24; bloom += texture(iChannel0, p) * .28; bloom += texture(iChannel0, p + vec2( blurSize, 0)) * .24; bloom += texture(iChannel0, p + vec2( 2.*blurSize, 0)) * .12; bloom += texture(iChannel0, p + vec2(0, -2.*blurSize)) * .12; bloom += texture(iChannel0, p + vec2(0, -blurSize)) * .24; bloom += texture(iChannel0, p) * .28; bloom += texture(iChannel0, p + vec2(0, blurSize)) * .24; bloom += texture(iChannel0, p + vec2(0, 2.*blurSize)) * .12; c += bloom * bloomIntensity; } // black vignette around edges const float vignette = 2.; const float vignettePow = 6.; float dx = 2.*p.x-1., dy = 2.*p.y-1.; c *= 1.-pow((dx*dx + dy*dy)/vignette, vignettePow); }`; new LJS.PostProcessPlugin(televisionShader); } /////////////////////////////////////////////////////////////////////////////// // Startup LittleJS Engine LJS.engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);