diff --git a/front/src/Phaser/Items/ActionableItem.ts b/front/src/Phaser/Items/ActionableItem.ts new file mode 100644 index 00000000..e69de29b diff --git a/front/src/Phaser/Items/ActionableSprite.ts b/front/src/Phaser/Items/ActionableSprite.ts new file mode 100644 index 00000000..e69de29b diff --git a/front/src/Phaser/Player/Player.ts b/front/src/Phaser/Player/Player.ts index f912d110..1a3a3a03 100644 --- a/front/src/Phaser/Player/Player.ts +++ b/front/src/Phaser/Player/Player.ts @@ -3,6 +3,7 @@ import {GameScene, Textures} from "../Game/GameScene"; import {MessageUserPositionInterface, PointInterface} from "../../Connection"; import {ActiveEventList, UserInputEvent, UserInputManager} from "../UserInput/UserInputManager"; import {Character} from "../Entity/Character"; +import {OutlinePipeline} from "../Shaders/OutlinePipeline"; export const hasMovedEventName = "hasMoved"; @@ -32,6 +33,10 @@ export class Player extends Character implements CurrentGamerInterface { //the current player model should be push away by other players to prevent conflict this.setImmovable(false); + + this.setPipeline(OutlinePipeline.KEY); + this.pipeline.setFloat2('uTextureSize', + this.texture.getSourceImage().width, this.texture.getSourceImage().height); } moveUser(delta: number): void { diff --git a/front/src/Phaser/Shaders/OutlinePipeline.ts b/front/src/Phaser/Shaders/OutlinePipeline.ts new file mode 100644 index 00000000..f65a66d2 --- /dev/null +++ b/front/src/Phaser/Shaders/OutlinePipeline.ts @@ -0,0 +1,61 @@ +export class OutlinePipeline extends Phaser.Renderer.WebGL.Pipelines.TextureTintPipeline +{ + + // the unique id of this pipeline + public static readonly KEY = 'Outline'; + + /** + * @param {Phaser.Game} game - the controller of the game instance + */ + constructor(game: Phaser.Game) + { + super({ + game: game, + renderer: game.renderer, + fragShader: ` + precision mediump float; + + uniform sampler2D uMainSampler; + uniform vec2 uTextureSize; + + varying vec2 outTexCoord; + varying float outTintEffect; + varying vec4 outTint; + + void main(void) + { + vec4 texture = texture2D(uMainSampler, outTexCoord); + vec4 texel = vec4(outTint.rgb * outTint.a, outTint.a); + vec4 color = texture; + + if (outTintEffect == 0.0) + { + color = texture * texel; + } + else if (outTintEffect == 1.0) + { + color.rgb = mix(texture.rgb, outTint.rgb * outTint.a, texture.a); + color.a = texture.a * texel.a; + } + else if (outTintEffect == 2.0) + { + color = texel; + } + + vec2 onePixel = vec2(1.0, 1.0) / uTextureSize; + float upAlpha = texture2D(uMainSampler, outTexCoord + vec2(0.0, onePixel.y)).a; + float leftAlpha = texture2D(uMainSampler, outTexCoord + vec2(-onePixel.x, 0.0)).a; + float downAlpha = texture2D(uMainSampler, outTexCoord + vec2(0.0, -onePixel.y)).a; + float rightAlpha = texture2D(uMainSampler, outTexCoord + vec2(onePixel.x, 0.0)).a; + + if (texture.a == 0.0 && max(max(upAlpha, downAlpha), max(leftAlpha, rightAlpha)) == 1.0) + { + color = vec4(1.0, 1.0, 1.0, 1.0); + } + + gl_FragColor = color; + } + ` + }); + } +} diff --git a/front/src/index.ts b/front/src/index.ts index eb63b6d0..b847fa74 100644 --- a/front/src/index.ts +++ b/front/src/index.ts @@ -8,6 +8,8 @@ import {gameManager} from "./Phaser/Game/GameManager"; import {SelectCharacterScene} from "./Phaser/Login/SelectCharacterScene"; import {EnableCameraScene} from "./Phaser/Login/EnableCameraScene"; import {FourOFourScene} from "./Phaser/Reconnecting/FourOFourScene"; +import WebGLRenderer = Phaser.Renderer.WebGL.WebGLRenderer; +import {OutlinePipeline} from "./Phaser/Shaders/OutlinePipeline"; const config: GameConfig = { title: "Office game", @@ -21,6 +23,13 @@ const config: GameConfig = { arcade: { debug: DEBUG_MODE } + }, + callbacks: { + postBoot: game => { + // FIXME: we should fore WebGL in the config. + let renderer = game.renderer as WebGLRenderer; + renderer.addPipeline(OutlinePipeline.KEY, new OutlinePipeline(game)); + } } }; diff --git a/maps/objects/computer.ts b/maps/objects/computer.ts new file mode 100644 index 00000000..e69de29b diff --git a/maps/package.json b/maps/package.json new file mode 100644 index 00000000..a20c876f --- /dev/null +++ b/maps/package.json @@ -0,0 +1,63 @@ +{ + "name": "workadventureback", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "tsc": "tsc", + "dev": "ts-node-dev --respawn --transpileOnly ./server.ts", + "prod": "tsc && node ./dist/server.js", + "profile": "tsc && node --prof ./dist/server.js", + "test": "ts-node node_modules/jasmine/bin/jasmine --config=jasmine.json", + "lint": "node_modules/.bin/eslint src/ . --ext .ts", + "fix": "node_modules/.bin/eslint --fix src/ . --ext .ts" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/thecodingmachine/workadventure.git" + }, + "contributors": [ + { + "name": "Grégoire Parant", + "email": "g.parant@thecodingmachine.com" + }, + { + "name": "David Négrier", + "email": "d.negrier@thecodingmachine.com" + }, + { + "name": "Arthmaël Poly", + "email": "a.poly@thecodingmachine.com" + } + ], + "license": "SEE LICENSE IN LICENSE.txt", + "bugs": { + "url": "https://github.com/thecodingmachine/workadventure/issues" + }, + "homepage": "https://github.com/thecodingmachine/workadventure#readme", + "dependencies": { + "@types/express": "^4.17.4", + "@types/http-status-codes": "^1.2.0", + "@types/jsonwebtoken": "^8.3.8", + "@types/socket.io": "^2.1.4", + "@types/uuidv4": "^5.0.0", + "body-parser": "^1.19.0", + "express": "^4.17.1", + "generic-type-guard": "^3.2.0", + "http-status-codes": "^1.4.0", + "jsonwebtoken": "^8.5.1", + "prom-client": "^12.0.0", + "socket.io": "^2.3.0", + "systeminformation": "^4.26.5", + "ts-node-dev": "^1.0.0-pre.44", + "typescript": "^3.8.3", + "uuidv4": "^6.0.7" + }, + "devDependencies": { + "@types/jasmine": "^3.5.10", + "@typescript-eslint/eslint-plugin": "^2.26.0", + "@typescript-eslint/parser": "^2.26.0", + "eslint": "^6.8.0", + "jasmine": "^3.5.0" + } +} diff --git a/maps/tsconfig.json b/maps/tsconfig.json new file mode 100644 index 00000000..9a140744 --- /dev/null +++ b/maps/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "outDir": "./dist/", + "sourceMap": true, + "moduleResolution": "node", + "module": "ESNext", + "target": "ES2015", + "downlevelIteration": true, + "jsx": "react", + "allowJs": true, + + "strict": false, /* Enable all strict type-checking options. */ + "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + "strictNullChecks": true, /* Enable strict null checks. */ + "strictFunctionTypes": true, /* Enable strict checking of function types. */ + "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + "strictPropertyInitialization": false, /* Enable strict checking of property initialization in classes. */ + "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */ + } +}