From a1b2da5fae42406135cb2d28d9d8f8a577d4e9e8 Mon Sep 17 00:00:00 2001 From: Erik Onarheim Date: Thu, 10 Aug 2023 19:32:22 -0500 Subject: [PATCH] chore: Update sandbox --- sandbox/tests/input-mapper/index.html | 12 +++ sandbox/tests/input-mapper/main.ts | 64 +++++++++++++ sandbox/tests/postprocessor/index.html | 12 +++ sandbox/tests/postprocessor/main.ts | 115 ++++++++++++++++++++++++ sandbox/tests/raycast/index.html | 12 +++ sandbox/tests/raycast/main.ts | 74 +++++++++++++++ sandbox/tests/spritesampling/index.html | 13 +++ sandbox/tests/spritesampling/main.ts | 62 +++++++++++++ sandbox/tests/text-wrapping/index.html | 12 +++ sandbox/tests/text-wrapping/main.ts | 39 ++++++++ 10 files changed, 415 insertions(+) create mode 100644 sandbox/tests/input-mapper/index.html create mode 100644 sandbox/tests/input-mapper/main.ts create mode 100644 sandbox/tests/postprocessor/index.html create mode 100644 sandbox/tests/postprocessor/main.ts create mode 100644 sandbox/tests/raycast/index.html create mode 100644 sandbox/tests/raycast/main.ts create mode 100644 sandbox/tests/spritesampling/index.html create mode 100644 sandbox/tests/spritesampling/main.ts create mode 100644 sandbox/tests/text-wrapping/index.html create mode 100644 sandbox/tests/text-wrapping/main.ts diff --git a/sandbox/tests/input-mapper/index.html b/sandbox/tests/input-mapper/index.html new file mode 100644 index 000000000..39752728b --- /dev/null +++ b/sandbox/tests/input-mapper/index.html @@ -0,0 +1,12 @@ + + + + + + Input Mapping + + + + + + \ No newline at end of file diff --git a/sandbox/tests/input-mapper/main.ts b/sandbox/tests/input-mapper/main.ts new file mode 100644 index 000000000..da6baf1fe --- /dev/null +++ b/sandbox/tests/input-mapper/main.ts @@ -0,0 +1,64 @@ + +var game = new ex.Engine({ + width: 600, + height: 400, + displayMode: ex.DisplayMode.FitScreenAndFill +}); + +var actor = new ex.Actor({ + pos: ex.vec(100, 100), + width: 100, + height: 100, + color: ex.Color.Red +}); +var moveRight = (amount: number) => { + actor.vel.x = 100 * amount; +} +var moveLeft = (amount: number) => { + actor.vel.x = -100 * amount; +} +var moveUp = (amount: number) => { + actor.vel.y = -100 * amount; +} +var moveDown = (amount: number) => { + actor.vel.y = 100 * amount; +} +var getLeftStickX = (gamepad: ex.Gamepad) => { + return gamepad.getAxes(ex.Axes.LeftStickX) +} +var getLeftStickY = (gamepad: ex.Gamepad) => { + return gamepad.getAxes(ex.Axes.LeftStickY) +} +actor.onInitialize = (engine) => { + const mapper = engine.inputMapper; + ex.Gamepads.MinAxisMoveThreshold = .10; + // Move right + mapper.on(({keyboard}) => keyboard.isHeld(ex.Keys.Right) ? 1 : 0, moveRight); + mapper.on(({gamepads}) => gamepads.at(0).getButton(ex.Buttons.DpadRight) ? 1 : 0, moveRight); + mapper.on(({gamepads}) => getLeftStickX(gamepads.at(0)) > 0 ? Math.abs(getLeftStickX(gamepads.at(0))) : 0, moveRight); + mapper.on(({keyboard, pointers}) => keyboard.isHeld(ex.Keys.Enter) && pointers.primary.lastWorldPos.x > actor.pos.x ? 1 : 0, moveRight); + + // Move left + mapper.on(({keyboard}) => keyboard.isHeld(ex.Keys.Left) ? 1 : 0, moveLeft); + mapper.on(({gamepads}) => gamepads.at(0).getButton(ex.Buttons.DpadLeft) ? 1 : 0, moveLeft); + mapper.on(({gamepads}) => getLeftStickX(gamepads.at(0)) < 0 ? Math.abs(getLeftStickX(gamepads.at(0))): 0, moveLeft); + mapper.on(({keyboard, pointers}) => keyboard.isHeld(ex.Keys.Enter) && pointers.primary.lastWorldPos.x < actor.pos.x ? 1 : 0, moveLeft); + + // Move up + mapper.on(({keyboard}) => keyboard.isHeld(ex.Keys.Up) ? 1 : 0, moveUp); + mapper.on(({gamepads}) => gamepads.at(0).getButton(ex.Buttons.DpadUp) ? 1 : 0, moveUp); + mapper.on(({gamepads}) => getLeftStickY(gamepads.at(0)) < 0 ? Math.abs(getLeftStickY(gamepads.at(0))) : 0, moveUp); + mapper.on(({keyboard, pointers}) => keyboard.isHeld(ex.Keys.Enter) && pointers.primary.lastWorldPos.y < actor.pos.y ? 1 : 0, moveUp); + + // Move down + mapper.on(({keyboard}) => keyboard.isHeld(ex.Keys.Down) ? 1 : 0, moveDown); + mapper.on(({gamepads}) => gamepads.at(0).getButton(ex.Buttons.DpadDown) ? 1 : 0, moveDown); + mapper.on(({gamepads}) => getLeftStickY(gamepads.at(0)) > 0 ? Math.abs(getLeftStickY(gamepads.at(0))) : 0, moveDown); + mapper.on(({keyboard, pointers}) => keyboard.isHeld(ex.Keys.Enter) && pointers.primary.lastWorldPos.y > actor.pos.y ? 1 : 0, moveDown); +} +game.onPostUpdate = () => { + actor.vel = ex.vec(0, 0); +} +game.currentScene.add(actor); + +game.start(); \ No newline at end of file diff --git a/sandbox/tests/postprocessor/index.html b/sandbox/tests/postprocessor/index.html new file mode 100644 index 000000000..308c6b82f --- /dev/null +++ b/sandbox/tests/postprocessor/index.html @@ -0,0 +1,12 @@ + + + + + + Post-processing + + + + + + \ No newline at end of file diff --git a/sandbox/tests/postprocessor/main.ts b/sandbox/tests/postprocessor/main.ts new file mode 100644 index 000000000..5068aaa67 --- /dev/null +++ b/sandbox/tests/postprocessor/main.ts @@ -0,0 +1,115 @@ +var crtFragmentSource = `#version 300 es +precision mediump float; +// Sourced from https://www.shadertoy.com/view/Ms23DR +// Loosely based on postprocessing shader by inigo quilez, License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. +uniform sampler2D u_image; + +uniform vec2 u_resolution; + +uniform float u_time_ms; + +uniform float u_elapsed_ms; + +out vec4 fragColor; + +vec2 curve(vec2 uv) +{ + uv = (uv - 0.5) * 2.0; + uv *= 1.1; + uv.x *= 1.0 + pow((abs(uv.y) / 5.0), 2.0); + uv.y *= 1.0 + pow((abs(uv.x) / 4.0), 2.0); + uv = (uv / 2.0) + 0.5; + uv = uv *0.92 + 0.04; + return uv; +} +void main() +{ + vec2 q = gl_FragCoord.xy / u_resolution; + vec2 uv = q; + uv = curve( uv ); + // vec3 oricol = texture( iChannel0, vec2(q.x,q.y) ).xyz; + // vec4 o = texture(u_image, v_texcoord).xyz; + vec3 col; + float iTime = u_time_ms / 1000.0; + float x = sin(0.3*iTime+uv.y*21.0)*sin(0.7*iTime+uv.y*29.0)*sin(0.3+0.33*iTime+uv.y*31.0)*0.0017; + + col.r = texture(u_image,vec2(x+uv.x+0.001,uv.y+0.001)).x+0.05; + col.g = texture(u_image,vec2(x+uv.x+0.000,uv.y-0.002)).y+0.05; + col.b = texture(u_image,vec2(x+uv.x-0.002,uv.y+0.000)).z+0.05; + col.r += 0.08*texture(u_image,0.75*vec2(x+0.025, -0.027)+vec2(uv.x+0.001,uv.y+0.001)).x; + col.g += 0.05*texture(u_image,0.75*vec2(x+-0.022, -0.02)+vec2(uv.x+0.000,uv.y-0.002)).y; + col.b += 0.08*texture(u_image,0.75*vec2(x+-0.02, -0.018)+vec2(uv.x-0.002,uv.y+0.000)).z; + + col = clamp(col*0.6+0.4*col*col*1.0,0.0,1.0); + + float vig = (0.0 + 1.0*16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y)); + col *= vec3(pow(vig,0.3)); + + col *= vec3(0.95,1.05,0.95); + col *= 2.8; + + float scans = clamp( 0.35+0.35*sin(3.5*iTime+uv.y*u_resolution.y*1.5), 0.0, 1.0); + + float s = pow(scans,1.7); + col = col*vec3( 0.4+0.7*s) ; + + col *= 1.0+0.01*sin(110.0*iTime); + if (uv.x < 0.0 || uv.x > 1.0) + col *= 0.0; + if (uv.y < 0.0 || uv.y > 1.0) + col *= 0.0; + + col*=1.0-0.65*vec3(clamp((mod(gl_FragCoord.x, 2.0)-1.0)*2.0,0.0,1.0)); + + float comp = smoothstep( 0.1, 0.9, sin(iTime) ); + + // Remove the next line to stop cross-fade between original and postprocess +// col = mix( col, oricol, comp ); + + fragColor = vec4(col,1.0); +}` + +class CRTPostProcessors implements ex.PostProcessor { + private _shader: ex.ScreenShader; + constructor() {} + initialize(gl: WebGL2RenderingContext): void { + this._shader = new ex.ScreenShader(gl, crtFragmentSource); + } + getShader(): ex.Shader { + return this._shader.getShader(); + } + getLayout(): ex.VertexLayout { + return this._shader.getLayout(); + } + onUpdate(delta: number): void { + // set your own uniforms here + const shader = this.getShader(); + shader.trySetUniformBoolean('u_some_uniform', true); + } +} + +var game = new ex.Engine({ + width: 600, + height: 400, + displayMode: ex.DisplayMode.FitScreenAndFill +}); + +var actor = new ex.Actor({ + width: 100, + height: 100, + color: ex.Color.Red +}); +actor.angularVelocity = .2; +actor.actions + .repeatForever((ctx) => { + ctx.moveTo(ex.vec(600, 0), 200); + ctx.moveTo(ex.vec(0, 400), 200); + ctx.moveTo(ex.vec(600, 400), 200); + ctx.moveTo(ex.vec(0, 0), 200); + }); +game.currentScene.add(actor); + +var ctx = game.graphicsContext as ex.ExcaliburGraphicsContextWebGL; +ctx.addPostProcessor(new CRTPostProcessors()); + +game.start(); \ No newline at end of file diff --git a/sandbox/tests/raycast/index.html b/sandbox/tests/raycast/index.html new file mode 100644 index 000000000..453486d40 --- /dev/null +++ b/sandbox/tests/raycast/index.html @@ -0,0 +1,12 @@ + + + + + + Scene Raycasting + + + + + + \ No newline at end of file diff --git a/sandbox/tests/raycast/main.ts b/sandbox/tests/raycast/main.ts new file mode 100644 index 000000000..ddf2644aa --- /dev/null +++ b/sandbox/tests/raycast/main.ts @@ -0,0 +1,74 @@ + +var game = new ex.Engine({ + width: 600, + height: 400, + displayMode: ex.DisplayMode.FitScreenAndFill +}); +var random = new ex.Random(1337); +var blockGroup = ex.CollisionGroupManager.create('blockGroup'); + +var player = new ex.Actor({ + name: 'player', + pos: ex.vec(100, 100), + width: 40, + height: 40, + color: ex.Color.Red, + z: 10 +}); +var playerDir = ex.Vector.Right; +var playerSightDistance = 100; +var playerSpeed = 100; +var rotationAmount = Math.PI / 32; +player.onPostUpdate = (engine) => { + player.vel = ex.Vector.Zero; + const keyboard = engine.input.keyboard; + if (keyboard.isHeld(ex.Keys.ArrowLeft)) { + playerDir = playerDir.rotate(-rotationAmount) + player.rotation -= rotationAmount; + } + if (keyboard.isHeld(ex.Keys.ArrowRight)){ + playerDir = playerDir.rotate(+rotationAmount) + player.rotation += rotationAmount; + } + if (keyboard.isHeld(ex.Keys.ArrowUp)) { + player.vel = playerDir.scale(100); + } + + // raycast + var hits = engine.currentScene.physics.rayCast( + new ex.Ray(player.pos, playerDir), + { + maxDistance: playerSightDistance, + collisionGroup: blockGroup, + searchAllColliders: false + }); + + for (let hit of hits) { + const hitActor = hit.collider.owner as ex.Actor; + hitActor.graphics.use(new ex.Rectangle({ + color: ex.Color.Violet, + width: 20, + height: 20 + })); + } +} +player.graphics.onPostDraw = (ctx) => { + ctx.drawLine(ex.Vector.Zero, ex.Vector.Right.scale(playerSightDistance), ex.Color.Red, 2); +}; +game.currentScene.add(player); + +// environment + +for (let i = 0; i < 10; i++) { + var block = new ex.Actor({ + pos: ex.vec(random.floating(0, 600), random.floating(0, 400)), + width: 20, + height: 20, + color: ex.Color.Black, + collisionType: ex.CollisionType.Fixed, + collisionGroup: blockGroup + }); + game.currentScene.add(block); +} + +game.start(); \ No newline at end of file diff --git a/sandbox/tests/spritesampling/index.html b/sandbox/tests/spritesampling/index.html new file mode 100644 index 000000000..200d01b7b --- /dev/null +++ b/sandbox/tests/spritesampling/index.html @@ -0,0 +1,13 @@ + + + + + + + Sprite Sampling + + + + + + \ No newline at end of file diff --git a/sandbox/tests/spritesampling/main.ts b/sandbox/tests/spritesampling/main.ts new file mode 100644 index 000000000..f3bef837e --- /dev/null +++ b/sandbox/tests/spritesampling/main.ts @@ -0,0 +1,62 @@ +var game = new ex.Engine({ + displayMode: ex.DisplayMode.Fixed, + resolution: { + height: 16 * 20, + width: 16 * 20, + }, + viewport: { + width: 16 * 20, + height: 16 * 20 + }, + antialiasing: false, + snapToPixel: true +}) + +var heroSpriteImage = new ex.ImageSource('../../images/Hero 01.png', false, ex.ImageFiltering.Pixel); + +var loader = new ex.Loader([ + heroSpriteImage +]); + + +class PlayerSample extends ex.Actor { + constructor(pos: ex.Vector) { + super({ + pos, + width: 16, + height: 16, + collisionType: ex.CollisionType.Active + }) + } + + onInitialize(engine: ex.Engine): void { + const playerSpriteSheet = ex.SpriteSheet.fromImageSource({ + image: heroSpriteImage, + grid: { + spriteWidth: 16, + spriteHeight: 16, + rows: 8, + columns: 8 + } + }); + + const downIdle = new ex.Animation({ + frames: [ + { graphic: playerSpriteSheet.getSprite(0, 0) as ex.Sprite, duration: 200 }, + { graphic: playerSpriteSheet.getSprite(1, 0) as ex.Sprite, duration: 200 }, + { graphic: playerSpriteSheet.getSprite(2, 0) as ex.Sprite, duration: 200 }, + { graphic: playerSpriteSheet.getSprite(3, 0) as ex.Sprite, duration: 200 }, + ] + }) + this.graphics.add('down-idle', downIdle); + + this.graphics.use('down-idle'); + } +} + + + +game.start(loader).then(() => { + game.currentScene.camera.pos = ex.vec(16, 16); + game.add(new PlayerSample(ex.vec(16, 16))); +}); diff --git a/sandbox/tests/text-wrapping/index.html b/sandbox/tests/text-wrapping/index.html new file mode 100644 index 000000000..9c816f0e4 --- /dev/null +++ b/sandbox/tests/text-wrapping/index.html @@ -0,0 +1,12 @@ + + + + + + Text Wrapping + + + + + + \ No newline at end of file diff --git a/sandbox/tests/text-wrapping/main.ts b/sandbox/tests/text-wrapping/main.ts new file mode 100644 index 000000000..edf9ee14c --- /dev/null +++ b/sandbox/tests/text-wrapping/main.ts @@ -0,0 +1,39 @@ +var game = new ex.Engine({ + width: 600, + height: 400, + displayMode: ex.DisplayMode.FitScreenAndFill +}); + +var text = new ex.Text({ + text: '😻', + maxWidth: 200, + font: new ex.Font({ + family: 'Consolas', + size: 30, + unit: ex.FontUnit.Px, + color: ex.Color.Black + }) +}); + +var textActor = new ex.Actor({ + pos: game.screen.center, +}); +textActor.graphics.use(text); +game.currentScene.add(textActor); + +game.input.keyboard.on('release', ev => { + if (ev.key !== ex.Keys.ShiftLeft && + ev.key !== ex.Keys.ShiftRight && + ev.key !== ex.Keys.Enter && + ev.key !== ex.Keys.Backspace) { + text.text += ev.value; + } + if (ev.key === ex.Keys.Enter) { + text.text += '\n'; + } + if (ev.key === ex.Keys.Backspace) { + text.text = text.text.slice(0, text.text.length - 1); + } +}); + +game.start(); \ No newline at end of file