Merge pull request #924 from thecodingmachine/resolution
Improving mobile rendering / adding zoom / pinch
This commit is contained in:
commit
9c4a0245a3
@ -153,23 +153,6 @@ services:
|
||||
- "traefik.http.routers.uploader-ssl.tls=true"
|
||||
- "traefik.http.routers.uploader-ssl.service=uploader"
|
||||
|
||||
website:
|
||||
image: thecodingmachine/nodejs:12-apache
|
||||
environment:
|
||||
STARTUP_COMMAND_1: npm install
|
||||
STARTUP_COMMAND_2: npm run watch &
|
||||
APACHE_DOCUMENT_ROOT: dist/
|
||||
volumes:
|
||||
- ./website:/var/www/html
|
||||
labels:
|
||||
- "traefik.http.routers.website.rule=Host(`workadventure.localhost`)"
|
||||
- "traefik.http.routers.website.entryPoints=web"
|
||||
- "traefik.http.services.website.loadbalancer.server.port=80"
|
||||
- "traefik.http.routers.website-ssl.rule=Host(`workadventure.localhost`)"
|
||||
- "traefik.http.routers.website-ssl.entryPoints=websecure"
|
||||
- "traefik.http.routers.website-ssl.tls=true"
|
||||
- "traefik.http.routers.website-ssl.service=website"
|
||||
|
||||
messages:
|
||||
#image: thecodingmachine/nodejs:14
|
||||
image: thecodingmachine/workadventure-back-base:latest
|
||||
|
9
front/dist/resources/style/style.css
vendored
9
front/dist/resources/style/style.css
vendored
@ -381,7 +381,7 @@ body {
|
||||
max-height: 25%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#game {
|
||||
@ -540,7 +540,7 @@ input[type=range]:focus::-ms-fill-upper {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: all;
|
||||
pointer-events: none;
|
||||
/* TODO: DO WE NEED FLEX HERE???? WE WANT A SIDEBAR OF EXACTLY 25% (note: flex useful for direction!!!) */
|
||||
}
|
||||
|
||||
@ -549,7 +549,7 @@ input[type=range]:focus::-ms-fill-upper {
|
||||
}
|
||||
|
||||
.game-overlay video {
|
||||
width: 100%
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.main-section {
|
||||
@ -565,6 +565,7 @@ input[type=range]:focus::-ms-fill-upper {
|
||||
flex-basis: 96%;
|
||||
transition: margin-left 0.2s, margin-right 0.2s, margin-bottom 0.2s, margin-top 0.2s, flex-basis 0.2s;
|
||||
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
||||
pointer-events: auto;
|
||||
/*flex-shrink: 2;*/
|
||||
}
|
||||
|
||||
@ -576,7 +577,6 @@ input[type=range]:focus::-ms-fill-upper {
|
||||
.sidebar {
|
||||
flex: 0 0 25%;
|
||||
display: flex;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.sidebar > div {
|
||||
@ -584,6 +584,7 @@ input[type=range]:focus::-ms-fill-upper {
|
||||
transition: margin-left 0.2s, margin-right 0.2s, margin-bottom 0.2s, margin-top 0.2s, max-height 0.2s, max-width 0.2s;
|
||||
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
||||
border-radius: 15px 15px 15px 15px;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.sidebar > div:hover {
|
||||
|
@ -11,7 +11,7 @@ const TURN_PASSWORD: string = process.env.TURN_PASSWORD || '';
|
||||
const JITSI_URL : string|undefined = (process.env.JITSI_URL === '') ? undefined : process.env.JITSI_URL;
|
||||
const JITSI_PRIVATE_MODE : boolean = process.env.JITSI_PRIVATE_MODE == "true";
|
||||
const RESOLUTION = 2;
|
||||
const ZOOM_LEVEL = 1/*3/4*/;
|
||||
const ZOOM_LEVEL = 1;
|
||||
const POSITION_DELAY = 200; // Wait 200ms between sending position events
|
||||
const MAX_EXTRAPOLATION_TIME = 100; // Extrapolate a maximum of 250ms if no new movement is sent by the player
|
||||
export const MAX_USERNAME_LENGTH = parseInt(process.env.MAX_USERNAME_LENGTH || '') || 8;
|
||||
|
@ -1,8 +1,6 @@
|
||||
import VirtualJoystick from 'phaser3-rex-plugins/plugins/virtualjoystick.js';
|
||||
|
||||
const outOfScreenX = -1000;
|
||||
const outOfScreenY = -1000;
|
||||
|
||||
import ScaleManager = Phaser.Scale.ScaleManager;
|
||||
import {waScaleManager} from "../Services/WaScaleManager";
|
||||
|
||||
//the assets were found here: https://hannemann.itch.io/virtual-joystick-pack-free
|
||||
export const joystickBaseKey = 'joystickBase';
|
||||
@ -10,26 +8,58 @@ export const joystickBaseImg = 'resources/objects/joystickSplitted.png';
|
||||
export const joystickThumbKey = 'joystickThumb';
|
||||
export const joystickThumbImg = 'resources/objects/smallHandleFilledGrey.png';
|
||||
|
||||
const baseSize = 50;
|
||||
const thumbSize = 25;
|
||||
const radius = 17.5;
|
||||
|
||||
export class MobileJoystick extends VirtualJoystick {
|
||||
|
||||
private resizeCallback: () => void;
|
||||
|
||||
constructor(scene: Phaser.Scene) {
|
||||
super(scene, {
|
||||
x: outOfScreenX,
|
||||
y: outOfScreenY,
|
||||
radius: 20,
|
||||
base: scene.add.image(0, 0, joystickBaseKey).setDisplaySize(60, 60).setDepth(99999),
|
||||
thumb: scene.add.image(0, 0, joystickThumbKey).setDisplaySize(30, 30).setDepth(99999),
|
||||
x: -1000,
|
||||
y: -1000,
|
||||
radius: radius * window.devicePixelRatio,
|
||||
base: scene.add.image(0, 0, joystickBaseKey).setDisplaySize(baseSize * window.devicePixelRatio, baseSize * window.devicePixelRatio).setDepth(99999),
|
||||
thumb: scene.add.image(0, 0, joystickThumbKey).setDisplaySize(thumbSize * window.devicePixelRatio, thumbSize * window.devicePixelRatio).setDepth(99999),
|
||||
enable: true,
|
||||
dir: "8dir",
|
||||
});
|
||||
this.visible = false;
|
||||
this.enable = false;
|
||||
|
||||
this.scene.input.on('pointerdown', (pointer: { x: number; y: number; }) => {
|
||||
this.x = pointer.x;
|
||||
this.y = pointer.y;
|
||||
this.scene.input.on('pointerdown', (pointer: { x: number; y: number; wasTouch: boolean; event: TouchEvent }) => {
|
||||
if (!pointer.wasTouch) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's only display the joystick if there is one finger on the screen
|
||||
if (pointer.event.touches.length === 1) {
|
||||
this.x = pointer.x;
|
||||
this.y = pointer.y;
|
||||
this.visible = true;
|
||||
this.enable = true;
|
||||
} else {
|
||||
this.visible = false;
|
||||
this.enable = false;
|
||||
}
|
||||
});
|
||||
this.scene.input.on('pointerup', () => {
|
||||
this.x = outOfScreenX;
|
||||
this.y = outOfScreenY;
|
||||
this.visible = false;
|
||||
this.enable = false;
|
||||
});
|
||||
this.resizeCallback = this.resize.bind(this);
|
||||
this.scene.scale.on(Phaser.Scale.Events.RESIZE, this.resizeCallback);
|
||||
}
|
||||
}
|
||||
|
||||
private resize() {
|
||||
this.base.setDisplaySize(baseSize / waScaleManager.zoomModifier * window.devicePixelRatio, baseSize / waScaleManager.zoomModifier * window.devicePixelRatio);
|
||||
this.thumb.setDisplaySize(thumbSize / waScaleManager.zoomModifier * window.devicePixelRatio, thumbSize / waScaleManager.zoomModifier * window.devicePixelRatio);
|
||||
this.setRadius(radius / waScaleManager.zoomModifier * window.devicePixelRatio);
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
super.destroy();
|
||||
this.scene.scale.removeListener(Phaser.Scale.Events.RESIZE, this.resizeCallback);
|
||||
}
|
||||
}
|
||||
|
@ -89,6 +89,7 @@ import {TextUtils} from "../Components/TextUtils";
|
||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||
import {PinchManager} from "../UserInput/PinchManager";
|
||||
import {joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey} from "../Components/MobileJoystick";
|
||||
import {waScaleManager} from "../Services/WaScaleManager";
|
||||
|
||||
export interface GameSceneInitInterface {
|
||||
initPosition: PointInterface|null,
|
||||
@ -183,6 +184,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
private messageSubscription: Subscription|null = null;
|
||||
private popUpElements : Map<number, DOMElement> = new Map<number, Phaser.GameObjects.DOMElement>();
|
||||
private originalMapUrl: string|undefined;
|
||||
private pinchManager: PinchManager|undefined;
|
||||
|
||||
constructor(private room: Room, MapUrlFile: string, customKey?: string|undefined) {
|
||||
super({
|
||||
@ -201,7 +203,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
})
|
||||
this.connectionAnswerPromise = new Promise<RoomJoinedMessageInterface>((resolve, reject): void => {
|
||||
this.connectionAnswerPromiseResolve = resolve;
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
//hook preload scene
|
||||
@ -371,7 +373,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
this.startLayerName = urlManager.getStartLayerNameFromUrl();
|
||||
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
new PinchManager(this);
|
||||
this.pinchManager = new PinchManager(this);
|
||||
}
|
||||
|
||||
this.messageSubscription = worldFullMessageStream.stream.subscribe((message) => this.showWorldFullError(message))
|
||||
@ -914,6 +916,8 @@ ${escapedMessage}
|
||||
this.simplePeer?.closeAllConnections();
|
||||
this.simplePeer?.unregister();
|
||||
this.messageSubscription?.unsubscribe();
|
||||
this.userInputManager.destroy();
|
||||
this.pinchManager?.destroy();
|
||||
|
||||
for(const iframeEvents of this.iframeSubscriptionList){
|
||||
iframeEvents.unsubscribe();
|
||||
@ -1061,8 +1065,8 @@ ${escapedMessage}
|
||||
//todo: in a dedicated class/function?
|
||||
initCamera() {
|
||||
this.cameras.main.setBounds(0,0, this.Map.widthInPixels, this.Map.heightInPixels);
|
||||
this.cameras.main.startFollow(this.CurrentPlayer, true);
|
||||
this.updateCameraOffset();
|
||||
this.cameras.main.setZoom(ZOOM_LEVEL);
|
||||
}
|
||||
|
||||
addLayer(Layer : Phaser.Tilemaps.StaticTilemapLayer){
|
||||
@ -1435,19 +1439,18 @@ ${escapedMessage}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the offset of the character compared to the center of the screen according to the layout mananger
|
||||
* (tries to put the character in the center of the reamining space if there is a discussion going on.
|
||||
* Updates the offset of the character compared to the center of the screen according to the layout manager
|
||||
* (tries to put the character in the center of the remaining space if there is a discussion going on.
|
||||
*/
|
||||
private updateCameraOffset(): void {
|
||||
const array = layoutManager.findBiggestAvailableArray();
|
||||
let xCenter = (array.xEnd - array.xStart) / 2 + array.xStart;
|
||||
let yCenter = (array.yEnd - array.yStart) / 2 + array.yStart;
|
||||
const xCenter = (array.xEnd - array.xStart) / 2 + array.xStart;
|
||||
const yCenter = (array.yEnd - array.yStart) / 2 + array.yStart;
|
||||
|
||||
const game = HtmlUtils.querySelectorOrFail<HTMLCanvasElement>('#game canvas');
|
||||
// Let's put this in Game coordinates by applying the zoom level:
|
||||
xCenter /= ZOOM_LEVEL * RESOLUTION;
|
||||
yCenter /= ZOOM_LEVEL * RESOLUTION;
|
||||
|
||||
this.cameras.main.startFollow(this.CurrentPlayer, true, 1, 1, xCenter - this.game.renderer.width / 2, yCenter - this.game.renderer.height / 2);
|
||||
this.cameras.main.setFollowOffset((xCenter - game.offsetWidth/2) * window.devicePixelRatio / this.scale.zoom , (yCenter - game.offsetHeight/2) * window.devicePixelRatio / this.scale.zoom);
|
||||
}
|
||||
|
||||
public onCenterChange(): void {
|
||||
@ -1510,4 +1513,9 @@ ${escapedMessage}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
zoomByFactor(zoomFactor: number) {
|
||||
waScaleManager.zoomModifier *= zoomFactor;
|
||||
this.updateCameraOffset();
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import {TextField} from "../Components/TextField";
|
||||
import Image = Phaser.GameObjects.Image;
|
||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
||||
import {mediaManager} from "../../WebRtc/MediaManager";
|
||||
import {RESOLUTION} from "../../Enum/EnvironmentVariable";
|
||||
import {RESOLUTION, ZOOM_LEVEL} from "../../Enum/EnvironmentVariable";
|
||||
import {SoundMeter} from "../Components/SoundMeter";
|
||||
import {SoundMeterSprite} from "../Components/SoundMeterSprite";
|
||||
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
||||
@ -42,6 +42,7 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
private enableCameraSceneElement!: Phaser.GameObjects.DOMElement;
|
||||
|
||||
private mobileTapZone!: Zone;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
key: EnableCameraSceneName
|
||||
@ -75,12 +76,14 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
new PinchManager(this);
|
||||
}
|
||||
|
||||
//this.scale.setZoom(ZOOM_LEVEL);
|
||||
//Phaser.Display.Align.In.BottomCenter(this.pressReturnField, zone);
|
||||
|
||||
/* FIX ME */
|
||||
this.textField = new TextField(this, this.game.renderer.width / 2, 20, '');
|
||||
this.textField = new TextField(this, this.scale.width / 2, 20, '');
|
||||
|
||||
// For mobile purposes - we need a big enough touchable area.
|
||||
this.mobileTapZone = this.add.zone(this.game.renderer.width / 2,this.game.renderer.height - 30,200,50)
|
||||
this.mobileTapZone = this.add.zone(this.scale.width / 2,this.scale.height - 30,200,50)
|
||||
.setInteractive().on("pointerdown", () => {
|
||||
this.login();
|
||||
});
|
||||
@ -243,6 +246,11 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
|
||||
this.arrowUp.x = this.microphoneNameField.x - this.microphoneNameField.width / 2 - 16;
|
||||
this.arrowUp.y = this.microphoneNameField.y;
|
||||
|
||||
const actionBtn = document.querySelector<HTMLDivElement>('#enableCameraScene .action');
|
||||
if (actionBtn !== null) {
|
||||
actionBtn.style.top = (this.scale.height - 65) + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
@ -256,6 +264,7 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private login(): void {
|
||||
@ -283,12 +292,12 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
private getMiddleX() : number{
|
||||
return (this.game.renderer.width / RESOLUTION) -
|
||||
return (this.scale.width / 2) -
|
||||
(
|
||||
this.enableCameraSceneElement
|
||||
&& this.enableCameraSceneElement.node
|
||||
&& this.enableCameraSceneElement.node.getBoundingClientRect().width > 0
|
||||
? (this.enableCameraSceneElement.node.getBoundingClientRect().width / (2*RESOLUTION))
|
||||
? (this.enableCameraSceneElement.node.getBoundingClientRect().width / 2 / this.scale.zoom)
|
||||
: (300 / RESOLUTION)
|
||||
);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import {gameManager} from "../Game/GameManager";
|
||||
import {Scene} from "phaser";
|
||||
import {ErrorScene} from "../Reconnecting/ErrorScene";
|
||||
import {WAError} from "../Reconnecting/WAError";
|
||||
import {waScaleManager} from "../Services/WaScaleManager";
|
||||
|
||||
export const EntrySceneName = "EntryScene";
|
||||
|
||||
@ -17,7 +18,11 @@ export class EntryScene extends Scene {
|
||||
}
|
||||
|
||||
create() {
|
||||
|
||||
gameManager.init(this.scene).then((nextSceneName) => {
|
||||
// Let's rescale before starting the game
|
||||
// We can do it at this stage.
|
||||
waScaleManager.applyNewSize();
|
||||
this.scene.start(nextSceneName);
|
||||
}).catch((err) => {
|
||||
if (err.response && err.response.status == 404) {
|
||||
|
@ -192,11 +192,11 @@ export class MenuScene extends Phaser.Scene {
|
||||
}
|
||||
});
|
||||
|
||||
let middleY = (window.innerHeight / 3) - (257);
|
||||
let middleY = this.scale.height / 2 - 392/2;
|
||||
if(middleY < 0){
|
||||
middleY = 0;
|
||||
}
|
||||
let middleX = (window.innerWidth / 3) - 298;
|
||||
let middleX = this.scale.width / 2 - 457/2;
|
||||
if(middleX < 0){
|
||||
middleX = 0;
|
||||
}
|
||||
@ -236,11 +236,11 @@ export class MenuScene extends Phaser.Scene {
|
||||
|
||||
this.gameShareOpened = true;
|
||||
|
||||
let middleY = (window.innerHeight / 3) - (257);
|
||||
let middleY = this.scale.height / 2 - 85;
|
||||
if(middleY < 0){
|
||||
middleY = 0;
|
||||
}
|
||||
let middleX = (window.innerWidth / 3) - 298;
|
||||
let middleX = this.scale.width / 2 - 200;
|
||||
if(middleX < 0){
|
||||
middleX = 0;
|
||||
}
|
||||
|
105
front/src/Phaser/Services/HdpiManager.ts
Normal file
105
front/src/Phaser/Services/HdpiManager.ts
Normal file
@ -0,0 +1,105 @@
|
||||
import ScaleManager = Phaser.Scale.ScaleManager;
|
||||
|
||||
interface Size {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export class HdpiManager {
|
||||
private _zoomModifier: number = 1;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param minRecommendedGamePixelsNumber The minimum number of pixels we want to display "by default" to the user
|
||||
* @param absoluteMinPixelNumber The very minimum of game pixels to display. Below, we forbid zooming more
|
||||
*/
|
||||
public constructor(private minRecommendedGamePixelsNumber: number, private absoluteMinPixelNumber: number) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the optimal size in "game pixels" based on the screen size in "real pixels".
|
||||
*
|
||||
* Note: the function is returning the optimal size in "game pixels" in the "game" property,
|
||||
* but also recommends resizing the "real" pixel screen size of the canvas.
|
||||
* The proposed new real size is a few pixels bigger than the real size available (if the size is not a multiple of the pixel size) and should overflow.
|
||||
*
|
||||
* @param realPixelScreenSize
|
||||
*/
|
||||
public getOptimalGameSize(realPixelScreenSize: Size): { game: Size, real: Size } {
|
||||
const realPixelNumber = realPixelScreenSize.width * realPixelScreenSize.height;
|
||||
// If the screen has not a definition small enough to match the minimum number of pixels we want to display,
|
||||
// let's make the canvas the size of the screen (in real pixels)
|
||||
if (realPixelNumber <= this.minRecommendedGamePixelsNumber) {
|
||||
return {
|
||||
game: realPixelScreenSize,
|
||||
real: realPixelScreenSize
|
||||
};
|
||||
}
|
||||
|
||||
let i = 1;
|
||||
|
||||
while (realPixelNumber > this.minRecommendedGamePixelsNumber * i * i) {
|
||||
i++;
|
||||
}
|
||||
|
||||
// Has the canvas more pixels than the screen? This is forbidden
|
||||
if ((i - 1) * this._zoomModifier < 1) {
|
||||
// Let's reset the zoom modifier (WARNING this is a SIDE EFFECT in a getter)
|
||||
this._zoomModifier = 1 / (i - 1);
|
||||
|
||||
return {
|
||||
game: {
|
||||
width: realPixelScreenSize.width,
|
||||
height: realPixelScreenSize.height,
|
||||
},
|
||||
real: {
|
||||
width: realPixelScreenSize.width,
|
||||
height: realPixelScreenSize.height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const gameWidth = Math.ceil(realPixelScreenSize.width / (i - 1) / this._zoomModifier);
|
||||
const gameHeight = Math.ceil(realPixelScreenSize.height / (i - 1) / this._zoomModifier);
|
||||
|
||||
// Let's ensure we display a minimum of pixels, even if crazily zoomed in.
|
||||
if (gameWidth * gameHeight < this.absoluteMinPixelNumber) {
|
||||
const minGameHeight = Math.sqrt(this.absoluteMinPixelNumber * realPixelScreenSize.height / realPixelScreenSize.width);
|
||||
const minGameWidth = Math.sqrt(this.absoluteMinPixelNumber * realPixelScreenSize.width / realPixelScreenSize.height);
|
||||
|
||||
// Let's reset the zoom modifier (WARNING this is a SIDE EFFECT in a getter)
|
||||
this._zoomModifier = realPixelScreenSize.width / minGameWidth / (i - 1);
|
||||
|
||||
return {
|
||||
game: {
|
||||
width: minGameWidth,
|
||||
height: minGameHeight,
|
||||
},
|
||||
real: {
|
||||
width: realPixelScreenSize.width,
|
||||
height: realPixelScreenSize.height,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
game: {
|
||||
width: gameWidth,
|
||||
height: gameHeight,
|
||||
},
|
||||
real: {
|
||||
width: Math.ceil(realPixelScreenSize.width / (i - 1)) * (i - 1),
|
||||
height: Math.ceil(realPixelScreenSize.height / (i - 1)) * (i - 1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get zoomModifier(): number {
|
||||
return this._zoomModifier;
|
||||
}
|
||||
|
||||
public set zoomModifier(zoomModifier: number) {
|
||||
this._zoomModifier = zoomModifier;
|
||||
}
|
||||
}
|
47
front/src/Phaser/Services/WaScaleManager.ts
Normal file
47
front/src/Phaser/Services/WaScaleManager.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import {HdpiManager} from "./HdpiManager";
|
||||
import ScaleManager = Phaser.Scale.ScaleManager;
|
||||
import {coWebsiteManager} from "../../WebRtc/CoWebsiteManager";
|
||||
|
||||
|
||||
class WaScaleManager {
|
||||
private hdpiManager: HdpiManager;
|
||||
private scaleManager!: ScaleManager;
|
||||
|
||||
public constructor(private minGamePixelsNumber: number, private absoluteMinPixelNumber: number) {
|
||||
this.hdpiManager = new HdpiManager(minGamePixelsNumber, absoluteMinPixelNumber);
|
||||
}
|
||||
|
||||
public setScaleManager(scaleManager: ScaleManager) {
|
||||
this.scaleManager = scaleManager;
|
||||
}
|
||||
|
||||
public applyNewSize() {
|
||||
const {width, height} = coWebsiteManager.getGameSize();
|
||||
|
||||
let devicePixelRatio = 1;
|
||||
if (window.devicePixelRatio) {
|
||||
devicePixelRatio = window.devicePixelRatio;
|
||||
}
|
||||
|
||||
const { game: gameSize, real: realSize } = this.hdpiManager.getOptimalGameSize({width: width * devicePixelRatio, height: height * devicePixelRatio});
|
||||
|
||||
this.scaleManager.setZoom(realSize.width / gameSize.width / devicePixelRatio);
|
||||
this.scaleManager.resize(gameSize.width, gameSize.height);
|
||||
|
||||
// Override bug in canvas resizing in Phaser. Let's resize the canvas ourselves
|
||||
const style = this.scaleManager.canvas.style;
|
||||
style.width = Math.ceil(realSize.width / devicePixelRatio) + 'px';
|
||||
style.height = Math.ceil(realSize.height / devicePixelRatio) + 'px';
|
||||
}
|
||||
|
||||
public get zoomModifier(): number {
|
||||
return this.hdpiManager.zoomModifier;
|
||||
}
|
||||
|
||||
public set zoomModifier(zoomModifier: number) {
|
||||
this.hdpiManager.zoomModifier = zoomModifier;
|
||||
this.applyNewSize();
|
||||
}
|
||||
}
|
||||
|
||||
export const waScaleManager = new WaScaleManager(640*480, 196*196);
|
@ -1,22 +1,41 @@
|
||||
import {Pinch} from "phaser3-rex-plugins/plugins/gestures.js";
|
||||
import {waScaleManager} from "../Services/WaScaleManager";
|
||||
import {GameScene} from "../Game/GameScene";
|
||||
|
||||
export class PinchManager {
|
||||
private scene: Phaser.Scene;
|
||||
private pinch!: any; // eslint-disable-line
|
||||
|
||||
|
||||
constructor(scene: Phaser.Scene) {
|
||||
this.scene = scene;
|
||||
this.pinch = new Pinch(scene);
|
||||
this.pinch.setDragThreshold(10);
|
||||
|
||||
// The "pinch.scaleFactor" value is very sensitive and causes the screen to flicker.
|
||||
// We are smoothing its value with previous values to prevent the flicking.
|
||||
let smoothPinch = 1;
|
||||
|
||||
this.pinch.on('pinchstart', () => {
|
||||
smoothPinch = 1;
|
||||
});
|
||||
|
||||
|
||||
this.pinch.on('pinch', (pinch:any) => { // eslint-disable-line
|
||||
let newZoom = this.scene.cameras.main.zoom * pinch.scaleFactor;
|
||||
if (newZoom < 0.25) {
|
||||
newZoom = 0.25;
|
||||
} else if(newZoom > 2) {
|
||||
newZoom = 2;
|
||||
if (pinch.scaleFactor > 1.2 || pinch.scaleFactor < 0.8) {
|
||||
// Pinch too fast! Probably a bad measure.
|
||||
return;
|
||||
}
|
||||
|
||||
smoothPinch = 3/5*smoothPinch + 2/5*pinch.scaleFactor;
|
||||
if (this.scene instanceof GameScene) {
|
||||
this.scene.zoomByFactor(smoothPinch);
|
||||
} else {
|
||||
waScaleManager.zoomModifier *= smoothPinch;
|
||||
}
|
||||
this.scene.cameras.main.setZoom(newZoom);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.pinch.removeAllListeners();
|
||||
}
|
||||
}
|
||||
|
@ -54,11 +54,12 @@ export class UserInputManager {
|
||||
this.Scene = Scene;
|
||||
this.isInputDisabled = false;
|
||||
this.initKeyBoardEvent();
|
||||
this.initMouseWheel();
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
this.initVirtualJoystick();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
initVirtualJoystick() {
|
||||
this.joystick = new MobileJoystick(this.Scene);
|
||||
this.joystick.on("update", () => {
|
||||
@ -170,4 +171,14 @@ export class UserInputManager {
|
||||
removeSpaceEventListner(callback : Function){
|
||||
this.Scene.input.keyboard.removeListener('keyup-SPACE', callback);
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
this.joystick.destroy();
|
||||
}
|
||||
|
||||
private initMouseWheel() {
|
||||
this.Scene.input.on('wheel', (pointer: unknown, gameObjects: unknown, deltaX: number, deltaY: number, deltaZ: number) => {
|
||||
this.Scene.zoomByFactor(1 - deltaY / 53 * 0.1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ import {localUserStore} from "./Connexion/LocalUserStore";
|
||||
import {ErrorScene} from "./Phaser/Reconnecting/ErrorScene";
|
||||
import {iframeListener} from "./Api/IframeListener";
|
||||
import { SelectCharacterMobileScene } from './Phaser/Login/SelectCharacterMobileScene';
|
||||
import {HdpiManager} from "./Phaser/Services/HdpiManager";
|
||||
import {waScaleManager} from "./Phaser/Services/WaScaleManager";
|
||||
|
||||
const {width, height} = coWebsiteManager.getGameSize();
|
||||
|
||||
@ -68,23 +70,31 @@ switch (phaserMode) {
|
||||
throw new Error('phaserMode parameter must be one of "auto", "canvas" or "webgl"');
|
||||
}
|
||||
|
||||
const hdpiManager = new HdpiManager(640*480, 196*196);
|
||||
const { game: gameSize, real: realSize } = hdpiManager.getOptimalGameSize({width, height});
|
||||
|
||||
const config: GameConfig = {
|
||||
type: mode,
|
||||
title: "WorkAdventure",
|
||||
width: width / RESOLUTION,
|
||||
height: height / RESOLUTION,
|
||||
parent: "game",
|
||||
scene: [EntryScene,
|
||||
scale: {
|
||||
parent: "game",
|
||||
width: gameSize.width,
|
||||
height: gameSize.height,
|
||||
zoom: realSize.width / gameSize.width,
|
||||
autoRound: true,
|
||||
resizeInterval: 999999999999
|
||||
},
|
||||
scene: [EntryScene,
|
||||
LoginScene,
|
||||
isMobile() ? SelectCharacterMobileScene : SelectCharacterScene,
|
||||
SelectCompanionScene,
|
||||
EnableCameraScene,
|
||||
ReconnectingScene,
|
||||
ErrorScene,
|
||||
CustomizeScene,
|
||||
MenuScene,
|
||||
SelectCompanionScene,
|
||||
EnableCameraScene,
|
||||
ReconnectingScene,
|
||||
ErrorScene,
|
||||
CustomizeScene,
|
||||
MenuScene,
|
||||
HelpCameraSettingsScene],
|
||||
zoom: RESOLUTION,
|
||||
//resolution: window.devicePixelRatio / 2,
|
||||
fps: fps,
|
||||
dom: {
|
||||
createContainer: true
|
||||
@ -113,10 +123,12 @@ const config: GameConfig = {
|
||||
|
||||
const game = new Phaser.Game(config);
|
||||
|
||||
waScaleManager.setScaleManager(game.scale);
|
||||
|
||||
window.addEventListener('resize', function (event) {
|
||||
coWebsiteManager.resetStyle();
|
||||
const {width, height} = coWebsiteManager.getGameSize();
|
||||
game.scale.resize(width / RESOLUTION, height / RESOLUTION);
|
||||
|
||||
waScaleManager.applyNewSize();
|
||||
|
||||
// Let's trigger the onResize method of any active scene that is a ResizableScene
|
||||
for (const scene of game.scene.getScenes(true)) {
|
||||
@ -127,8 +139,7 @@ window.addEventListener('resize', function (event) {
|
||||
});
|
||||
|
||||
coWebsiteManager.onResize.subscribe(() => {
|
||||
const {width, height} = coWebsiteManager.getGameSize();
|
||||
game.scale.resize(width / RESOLUTION, height / RESOLUTION);
|
||||
waScaleManager.applyNewSize();
|
||||
});
|
||||
|
||||
iframeListener.init();
|
||||
|
4
front/src/rex-plugins.d.ts
vendored
4
front/src/rex-plugins.d.ts
vendored
@ -4,9 +4,9 @@ declare module 'phaser3-rex-plugins/plugins/virtualjoystick.js' {
|
||||
export default content;
|
||||
}
|
||||
declare module 'phaser3-rex-plugins/plugins/gestures-plugin.js' {
|
||||
const content: any; // eslint-disable-line
|
||||
const content: any; // eslint-disable-line
|
||||
export default content;
|
||||
}
|
||||
declare module 'phaser3-rex-plugins/plugins/gestures.js' {
|
||||
export const Pinch: any; // eslint-disable-line
|
||||
}
|
||||
}
|
||||
|
55
front/tests/Phaser/Services/HdpiManagerTest.ts
Normal file
55
front/tests/Phaser/Services/HdpiManagerTest.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import "jasmine";
|
||||
import {HdpiManager} from "../../../src/Phaser/Services/HdpiManager";
|
||||
|
||||
describe("Test HdpiManager", () => {
|
||||
it("should match screen size if size is too small.", () => {
|
||||
const hdpiManager = new HdpiManager(640*480, 64*64);
|
||||
|
||||
const result = hdpiManager.getOptimalGameSize({ width: 320, height: 200 });
|
||||
expect(result.game.width).toEqual(320);
|
||||
expect(result.game.height).toEqual(200);
|
||||
expect(result.real.width).toEqual(320);
|
||||
expect(result.real.height).toEqual(200);
|
||||
});
|
||||
|
||||
it("should match multiple just above.", () => {
|
||||
const hdpiManager = new HdpiManager(640*480, 64*64);
|
||||
|
||||
let result = hdpiManager.getOptimalGameSize({ width: 960, height: 600 });
|
||||
expect(result.game.width).toEqual(960);
|
||||
expect(result.game.height).toEqual(600);
|
||||
|
||||
result = hdpiManager.getOptimalGameSize({ width: 640 * 2 + 50, height: 480 * 2 + 50 });
|
||||
expect(result.game.width).toEqual(Math.ceil((640 * 2 + 50) / 2));
|
||||
expect(result.game.height).toEqual((480 * 2 + 50) / 2);
|
||||
|
||||
result = hdpiManager.getOptimalGameSize({ width: 640 * 3 + 50, height: 480 * 3 + 50 });
|
||||
expect(result.game.width).toEqual(Math.ceil((640 * 3 + 50) / 3));
|
||||
expect(result.game.height).toEqual(Math.ceil((480 * 3 + 50) / 3));
|
||||
expect(result.real.width).toEqual(result.game.width * 3);
|
||||
expect(result.real.height).toEqual(result.game.height * 3);
|
||||
});
|
||||
|
||||
it("should not zoom in too much.", () => {
|
||||
const hdpiManager = new HdpiManager(640*480, 64*64);
|
||||
|
||||
hdpiManager.zoomModifier = 11;
|
||||
|
||||
const result = hdpiManager.getOptimalGameSize({ width: 640, height: 640 });
|
||||
expect(result.game.width).toEqual(64);
|
||||
expect(result.game.height).toEqual(64);
|
||||
expect(hdpiManager.zoomModifier).toEqual(10);
|
||||
|
||||
});
|
||||
|
||||
it("should not zoom out too much.", () => {
|
||||
const hdpiManager = new HdpiManager(640*480, 64*64);
|
||||
|
||||
hdpiManager.zoomModifier = 1/10;
|
||||
|
||||
const result = hdpiManager.getOptimalGameSize({ width: 1280, height: 768 });
|
||||
expect(result.game.width).toEqual(1280);
|
||||
expect(result.game.height).toEqual(768);
|
||||
expect(hdpiManager.zoomModifier).toEqual(1);
|
||||
});
|
||||
});
|
82
maps/tests/autoresize.json
Normal file
82
maps/tests/autoresize.json
Normal file
@ -0,0 +1,82 @@
|
||||
{ "compressionlevel":-1,
|
||||
"height":25,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 1, 1, 1, 1, 1, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 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, 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, 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, 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, 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, 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, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
"height":25,
|
||||
"id":1,
|
||||
"name":"floor",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":25,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":25,
|
||||
"id":2,
|
||||
"name":"start",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":25,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":3,
|
||||
"name":"floorLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":114.5,
|
||||
"id":3,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"Sans Serif",
|
||||
"pixelsize":11,
|
||||
"text":"Test:\nOpen your browser to the maximum size of your screen. Resize the browser window just smaller than the blue \"carpet\".\nResult:\nThe viewport is zoomed out x2 so that you can still see the \"carpet\"",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":252.4375,
|
||||
"x":162.78125,
|
||||
"y":129.5
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":8,
|
||||
"nextobjectid":5,
|
||||
"orientation":"orthogonal",
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"2021.03.23",
|
||||
"tileheight":32,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":11,
|
||||
"firstgid":1,
|
||||
"image":"tileset1.png",
|
||||
"imageheight":352,
|
||||
"imagewidth":352,
|
||||
"margin":0,
|
||||
"name":"tileset1",
|
||||
"spacing":0,
|
||||
"tilecount":121,
|
||||
"tileheight":32,
|
||||
"tilewidth":32
|
||||
}],
|
||||
"tilewidth":32,
|
||||
"type":"map",
|
||||
"version":1.5,
|
||||
"width":25
|
||||
}
|
@ -42,6 +42,30 @@
|
||||
<a href="#" class="testLink" data-testmap="script_api.json" target="_blank">Testing scripting API with a script</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="radio" name="test-autoresize"> Success <input type="radio" name="test-autoresize"> Failure <input type="radio" name="test-autoresize" checked> Pending
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" class="testLink" data-testmap="autoresize.json" target="_blank">Testing auto-zoom of viewport</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="radio" name="test-mouse-wheel"> Success <input type="radio" name="test-mouse-wheel"> Failure <input type="radio" name="test-mouse-wheel" checked> Pending
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" class="testLink" data-testmap="mousewheel.json" target="_blank">Testing zoom via mouse wheel</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="radio" name="test-mobile"> Success <input type="radio" name="test-mobile"> Failure <input type="radio" name="test-mobile" checked> Pending
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" class="testLink" data-testmap="mobile.json" target="_blank">Testing movement on mobile</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
|
82
maps/tests/mobile.json
Normal file
82
maps/tests/mobile.json
Normal file
@ -0,0 +1,82 @@
|
||||
{ "compressionlevel":-1,
|
||||
"height":10,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[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, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
"height":10,
|
||||
"id":1,
|
||||
"name":"floor",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":10,
|
||||
"id":2,
|
||||
"name":"start",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":3,
|
||||
"name":"floorLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":281.232647439376,
|
||||
"id":3,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"Sans Serif",
|
||||
"pixelsize":11,
|
||||
"text":"Test:\nOpen the page on a mobile device (or set Chrome in mobile mode)\n\nResult:\nBy default, the zoom level is not too zoomed in nor out (zoom level gives you the same visibility you typically have on desktop)\n\nYou can move using a virtual joystick\n\nYou can zoom using the \"pinch\" gesture\n\nWhen you zoom in or out, the size of the virtual joystick stays the same (about the size of your thumb)\n\nWhen you \"pinch\", your character does not move\n\nChanging phone orientation works",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":252.4375,
|
||||
"x":46.5894222943362,
|
||||
"y":34.2876372135732
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":8,
|
||||
"nextobjectid":5,
|
||||
"orientation":"orthogonal",
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"2021.03.23",
|
||||
"tileheight":32,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":11,
|
||||
"firstgid":1,
|
||||
"image":"tileset1.png",
|
||||
"imageheight":352,
|
||||
"imagewidth":352,
|
||||
"margin":0,
|
||||
"name":"tileset1",
|
||||
"spacing":0,
|
||||
"tilecount":121,
|
||||
"tileheight":32,
|
||||
"tilewidth":32
|
||||
}],
|
||||
"tilewidth":32,
|
||||
"type":"map",
|
||||
"version":1.5,
|
||||
"width":10
|
||||
}
|
82
maps/tests/mousewheel.json
Normal file
82
maps/tests/mousewheel.json
Normal file
@ -0,0 +1,82 @@
|
||||
{ "compressionlevel":-1,
|
||||
"height":10,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[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, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
"height":10,
|
||||
"id":1,
|
||||
"name":"floor",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":10,
|
||||
"id":2,
|
||||
"name":"start",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":10,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":3,
|
||||
"name":"floorLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":261.73266830836,
|
||||
"id":3,
|
||||
"name":"",
|
||||
"rotation":0,
|
||||
"text":
|
||||
{
|
||||
"fontfamily":"Sans Serif",
|
||||
"pixelsize":11,
|
||||
"text":"Test:\nUse your mouse wheel\nResult:\nThe canvas is zooming in or out\n\nTest:\nZoom out to the maximum\nResult:\nThe pixel size is the canvas = the pixel size on your monitor\n\nTest:\nZoom in to the maximum\nResult:\nYou see an area slightly larger than your character (with your character at the center if you are not standing on a border of the map)",
|
||||
"wrap":true
|
||||
},
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":252.4375,
|
||||
"x":46.5894222943362,
|
||||
"y":34.2876372135732
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":8,
|
||||
"nextobjectid":5,
|
||||
"orientation":"orthogonal",
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"2021.03.23",
|
||||
"tileheight":32,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":11,
|
||||
"firstgid":1,
|
||||
"image":"tileset1.png",
|
||||
"imageheight":352,
|
||||
"imagewidth":352,
|
||||
"margin":0,
|
||||
"name":"tileset1",
|
||||
"spacing":0,
|
||||
"tilecount":121,
|
||||
"tileheight":32,
|
||||
"tilewidth":32
|
||||
}],
|
||||
"tilewidth":32,
|
||||
"type":"map",
|
||||
"version":1.5,
|
||||
"width":10
|
||||
}
|
Loading…
Reference in New Issue
Block a user