Merge branch 'develop' into menu-command-api
33
.github/workflows/build-and-deploy.yml
vendored
@ -1,7 +1,11 @@
|
|||||||
name: Build, push and deploy Docker image
|
name: Build, push and deploy Docker image
|
||||||
|
|
||||||
on:
|
on:
|
||||||
- push
|
release:
|
||||||
|
types: [created]
|
||||||
|
pull_request:
|
||||||
|
types: [ labeled, synchronize ]
|
||||||
|
|
||||||
|
|
||||||
# Enables BuildKit
|
# Enables BuildKit
|
||||||
env:
|
env:
|
||||||
@ -10,7 +14,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
build-front:
|
build-front:
|
||||||
|
if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@ -30,11 +34,11 @@ jobs:
|
|||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
repository: thecodingmachine/workadventure-front
|
repository: thecodingmachine/workadventure-front
|
||||||
tags: ${{ env.GITHUB_REF_SLUG }}
|
tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
|
||||||
add_git_labels: true
|
add_git_labels: true
|
||||||
|
|
||||||
build-back:
|
build-back:
|
||||||
|
if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@ -53,11 +57,11 @@ jobs:
|
|||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
repository: thecodingmachine/workadventure-back
|
repository: thecodingmachine/workadventure-back
|
||||||
tags: ${{ env.GITHUB_REF_SLUG }}
|
tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
|
||||||
add_git_labels: true
|
add_git_labels: true
|
||||||
|
|
||||||
build-pusher:
|
build-pusher:
|
||||||
|
if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@ -76,11 +80,11 @@ jobs:
|
|||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
repository: thecodingmachine/workadventure-pusher
|
repository: thecodingmachine/workadventure-pusher
|
||||||
tags: ${{ env.GITHUB_REF_SLUG }}
|
tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
|
||||||
add_git_labels: true
|
add_git_labels: true
|
||||||
|
|
||||||
build-uploader:
|
build-uploader:
|
||||||
|
if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@ -99,11 +103,11 @@ jobs:
|
|||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
repository: thecodingmachine/workadventure-uploader
|
repository: thecodingmachine/workadventure-uploader
|
||||||
tags: ${{ env.GITHUB_REF_SLUG }}
|
tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
|
||||||
add_git_labels: true
|
add_git_labels: true
|
||||||
|
|
||||||
build-maps:
|
build-maps:
|
||||||
|
if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@ -123,7 +127,7 @@ jobs:
|
|||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
repository: thecodingmachine/workadventure-maps
|
repository: thecodingmachine/workadventure-maps
|
||||||
tags: ${{ env.GITHUB_REF_SLUG }}
|
tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
|
||||||
add_git_labels: true
|
add_git_labels: true
|
||||||
|
|
||||||
deeploy:
|
deeploy:
|
||||||
@ -134,6 +138,7 @@ jobs:
|
|||||||
- build-maps
|
- build-maps
|
||||||
- build-uploader
|
- build-uploader
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ contains(github.event.pull_request.labels.*.name, 'deploy') }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@ -151,14 +156,14 @@ jobs:
|
|||||||
JITSI_URL: ${{ secrets.JITSI_URL }}
|
JITSI_URL: ${{ secrets.JITSI_URL }}
|
||||||
SECRET_JITSI_KEY: ${{ secrets.SECRET_JITSI_KEY }}
|
SECRET_JITSI_KEY: ${{ secrets.SECRET_JITSI_KEY }}
|
||||||
TURN_STATIC_AUTH_SECRET: ${{ secrets.TURN_STATIC_AUTH_SECRET }}
|
TURN_STATIC_AUTH_SECRET: ${{ secrets.TURN_STATIC_AUTH_SECRET }}
|
||||||
|
DEPLOY_REF: ${{ env.GITHUB_HEAD_REF_SLUG }}
|
||||||
with:
|
with:
|
||||||
namespace: workadventure-${{ env.GITHUB_REF_SLUG }}
|
namespace: workadventure-${{ env.GITHUB_HEAD_REF_SLUG }}
|
||||||
|
|
||||||
- name: Add a comment in PR
|
- name: Add a comment in PR
|
||||||
uses: unsplash/comment-on-pr@v1.2.0
|
uses: unsplash/comment-on-pr@v1.2.0
|
||||||
if: ${{ env.GITHUB_REF_SLUG != 'master' }}
|
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
msg: Environment deployed at https://play.${{ env.GITHUB_REF_SLUG }}.workadventure.test.thecodingmachine.com
|
msg: Environment deployed at https://play.${{ env.GITHUB_HEAD_REF_SLUG }}.test.workadventu.re
|
||||||
check_for_duplicate_msg: true
|
check_for_duplicate_msg: true
|
||||||
|
10
.github/workflows/cleanup.yml
vendored
@ -1,7 +1,8 @@
|
|||||||
name: Cleanup images and environments
|
name: Cleanup images and environments
|
||||||
|
|
||||||
on:
|
on:
|
||||||
- delete
|
pull_request:
|
||||||
|
types: [ closed ]
|
||||||
|
|
||||||
# Enables BuildKit
|
# Enables BuildKit
|
||||||
env:
|
env:
|
||||||
@ -14,13 +15,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
# Create a slugified value of the branch
|
# Create a slugified value of the branch
|
||||||
- uses: rlespinasse/github-slug-action@1.1.0
|
- uses: rlespinasse/github-slug-action@3.1.0
|
||||||
|
|
||||||
- name: Cleanup
|
- name: Cleanup
|
||||||
|
continue-on-error: true
|
||||||
uses: thecodingmachine/deeployer-cleanup-action@master
|
uses: thecodingmachine/deeployer-cleanup-action@master
|
||||||
env:
|
env:
|
||||||
KUBE_CONFIG_FILE: ${{ secrets.KUBE_CONFIG_FILE }}
|
KUBE_CONFIG_FILE: ${{ secrets.KUBE_CONFIG_FILE }}
|
||||||
with:
|
with:
|
||||||
# FIXME: we are not using ${{ env.GITHUB_REF_SLUG }} that resolves to master BUT! we are not using a slugified namespace
|
namespace: workadventure-${{ env.GITHUB_HEAD_REF_SLUG }}
|
||||||
# so complex namespace names will not be treated correctly
|
|
||||||
namespace: workadventure-${{ github.event.ref }}
|
|
||||||
|
7
.github/workflows/continuous_integration.yml
vendored
@ -3,8 +3,11 @@
|
|||||||
name: "Continuous Integration"
|
name: "Continuous Integration"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
- "pull_request"
|
push:
|
||||||
- "push"
|
branches:
|
||||||
|
- master
|
||||||
|
- develop
|
||||||
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
|
16
CHANGELOG.md
@ -1,4 +1,18 @@
|
|||||||
## Version 1.3.0 - in dev
|
## Version 1.3.9 - in dev
|
||||||
|
|
||||||
|
### Updates
|
||||||
|
|
||||||
|
- Mobile support has been improved
|
||||||
|
- WorkAdventure automatically sets the zoom level based on the viewport size to ensure a sensible size of the map is visible, whatever the viewport used
|
||||||
|
- Mouse wheel support to zoom in / out
|
||||||
|
- Pinch support on mobile to zoom in / out
|
||||||
|
- Improved virtual joystick size (adapts to the zoom level)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- Pinch gesture does no longer move the character
|
||||||
|
|
||||||
|
## Version 1.3.0
|
||||||
|
|
||||||
### New Features
|
### New Features
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ Install Docker.
|
|||||||
Run:
|
Run:
|
||||||
|
|
||||||
```
|
```
|
||||||
docker-compose up
|
docker-compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
The environment will start.
|
The environment will start.
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
local env = std.extVar("env"),
|
local env = std.extVar("env"),
|
||||||
local namespace = env.GITHUB_REF_SLUG,
|
local namespace = env.DEPLOY_REF,
|
||||||
local tag = namespace,
|
local tag = namespace,
|
||||||
local url = if namespace == "master" then "workadventu.re" else namespace+".workadventure.test.thecodingmachine.com",
|
local url = if namespace == "master" then "workadventu.re" else namespace+".test.workadventu.re",
|
||||||
// develop branch does not use admin because of issue with SSL certificate of admin as of now.
|
// develop branch does not use admin because of issue with SSL certificate of admin as of now.
|
||||||
local adminUrl = if namespace == "master" || namespace == "develop" || std.startsWith(namespace, "admin") then "https://"+url else null,
|
local adminUrl = if namespace == "master" || namespace == "develop" || std.startsWith(namespace, "admin") then "https://"+url else null,
|
||||||
"$schema": "https://raw.githubusercontent.com/thecodingmachine/deeployer/master/deeployer.schema.json",
|
"$schema": "https://raw.githubusercontent.com/thecodingmachine/deeployer/master/deeployer.schema.json",
|
||||||
|
@ -30,7 +30,8 @@ services:
|
|||||||
UPLOADER_URL: /uploader
|
UPLOADER_URL: /uploader
|
||||||
ADMIN_URL: /admin
|
ADMIN_URL: /admin
|
||||||
MAPS_URL: /maps
|
MAPS_URL: /maps
|
||||||
STARTUP_COMMAND_1: yarn install
|
STARTUP_COMMAND_1: ./templater.sh
|
||||||
|
STARTUP_COMMAND_2: yarn install
|
||||||
TURN_SERVER: "turn:localhost:3478,turns:localhost:5349"
|
TURN_SERVER: "turn:localhost:3478,turns:localhost:5349"
|
||||||
# Use TURN_USER/TURN_PASSWORD if your Coturn server is secured via hard coded credentials.
|
# Use TURN_USER/TURN_PASSWORD if your Coturn server is secured via hard coded credentials.
|
||||||
# Advice: you should instead use Coturn REST API along the TURN_STATIC_AUTH_SECRET in the Back container
|
# Advice: you should instead use Coturn REST API along the TURN_STATIC_AUTH_SECRET in the Back container
|
||||||
@ -152,23 +153,6 @@ services:
|
|||||||
- "traefik.http.routers.uploader-ssl.tls=true"
|
- "traefik.http.routers.uploader-ssl.tls=true"
|
||||||
- "traefik.http.routers.uploader-ssl.service=uploader"
|
- "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:
|
messages:
|
||||||
#image: thecodingmachine/nodejs:14
|
#image: thecodingmachine/nodejs:14
|
||||||
image: thecodingmachine/workadventure-back-base:latest
|
image: thecodingmachine/workadventure-back-base:latest
|
||||||
|
19
front/dist/index.tmpl.html
vendored
@ -48,20 +48,27 @@
|
|||||||
<div id="activeCam" class="activeCam">
|
<div id="activeCam" class="activeCam">
|
||||||
<div id="div-myCamVideo" class="video-container">
|
<div id="div-myCamVideo" class="video-container">
|
||||||
<video id="myCamVideo" autoplay muted></video>
|
<video id="myCamVideo" autoplay muted></video>
|
||||||
|
<div id="mySoundMeter" class="sound-progress">
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-cam-action">
|
<div class="btn-cam-action">
|
||||||
<div id="btn-micro" class="btn-micro">
|
<div id="btn-monitor" class="btn-monitor">
|
||||||
<img id="microphone" src="resources/logos/microphone.svg">
|
<img id="monitor" src="resources/logos/monitor.svg">
|
||||||
<img id="microphone-close" src="resources/logos/microphone-close.svg">
|
<img id="monitor-close" src="resources/logos/monitor-close.svg">
|
||||||
</div>
|
</div>
|
||||||
<div id="btn-video" class="btn-video">
|
<div id="btn-video" class="btn-video">
|
||||||
<img id="cinema" src="resources/logos/cinema.svg">
|
<img id="cinema" src="resources/logos/cinema.svg">
|
||||||
<img id="cinema-close" src="resources/logos/cinema-close.svg">
|
<img id="cinema-close" src="resources/logos/cinema-close.svg">
|
||||||
</div>
|
</div>
|
||||||
<div id="btn-monitor" class="btn-monitor">
|
<div id="btn-micro" class="btn-micro">
|
||||||
<img id="monitor" src="resources/logos/monitor.svg">
|
<img id="microphone" src="resources/logos/microphone.svg">
|
||||||
<img id="monitor-close" src="resources/logos/monitor-close.svg">
|
<img id="microphone-close" src="resources/logos/microphone-close.svg">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -8,11 +8,11 @@
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
margin: 10px auto 0;
|
margin: 10px auto 0;
|
||||||
color: #ebeeee;
|
color: #ebeeee;
|
||||||
overflow: scroll;
|
|
||||||
width: 42vw;
|
width: 42vw;
|
||||||
height: 38vh;
|
height: 48vh;
|
||||||
/*max-width: 300px;*/
|
/*max-width: 300px;
|
||||||
max-height: 40vh;
|
max-height: 48vh;*/
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
#customizeScene h1 {
|
#customizeScene h1 {
|
||||||
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
||||||
@ -130,6 +130,7 @@
|
|||||||
@media only screen and (max-width: 600px) {
|
@media only screen and (max-width: 600px) {
|
||||||
#customizeScene {
|
#customizeScene {
|
||||||
max-width: 160px;
|
max-width: 160px;
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media only screen and (max-height: 400px) {
|
@media only screen and (max-height: 400px) {
|
||||||
|
10
front/dist/resources/html/EnableCameraScene.html
vendored
@ -8,10 +8,10 @@
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
margin: 20px auto 0;
|
margin: 20px auto 0;
|
||||||
color: #ebeeee;
|
color: #ebeeee;
|
||||||
max-height: 40vh;
|
max-height: 48vh;
|
||||||
width: 42vw;
|
width: 42vw;
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
/*overflow: scroll;*/
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
#enableCameraScene h1 {
|
#enableCameraScene h1 {
|
||||||
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
||||||
@ -97,6 +97,12 @@
|
|||||||
width: 160px;
|
width: 160px;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
/*@media only screen and (max-width: 800px),
|
||||||
|
only screen and (max-height: 600px) {
|
||||||
|
#enableCameraScene{
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<form id="enableCameraScene" hidden>
|
<form id="enableCameraScene" hidden>
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
margin: 10px auto 0;
|
margin: 10px auto 0;
|
||||||
color: #ebeeee;
|
color: #ebeeee;
|
||||||
max-height: 40vh;
|
max-height: 40vh;
|
||||||
overflow: scroll;
|
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
width: 40vw;
|
width: 40vw;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
#selectCompanionScene h1 {
|
#selectCompanionScene h1 {
|
||||||
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
||||||
@ -113,6 +113,12 @@
|
|||||||
background-color: #ffd700;
|
background-color: #ffd700;
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
@media only screen and (max-width: 800px),
|
||||||
|
only screen and (max-height: 600px) {
|
||||||
|
#selectCompanionScene{
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<form id="selectCompanionScene" hidden>
|
<form id="selectCompanionScene" hidden>
|
||||||
@ -122,7 +128,7 @@
|
|||||||
<button class="selectCharacterButton" id="selectCharacterButtonRight"> > </button>
|
<button class="selectCharacterButton" id="selectCharacterButtonRight"> > </button>
|
||||||
</section>
|
</section>
|
||||||
<section class="action">
|
<section class="action">
|
||||||
<a herf="#" id="selectCompanionSceneFormBack">Back</a>
|
<a herf="#" id="selectCompanionSceneFormBack">No companion</a>
|
||||||
<button type="submit" id="selectCompanionSceneFormSubmit">Continue</button>
|
<button type="submit" id="selectCompanionSceneFormSubmit">Continue</button>
|
||||||
</section>
|
</section>
|
||||||
</form>
|
</form>
|
||||||
|
@ -8,9 +8,10 @@
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
margin: 25px auto 0;
|
margin: 25px auto 0;
|
||||||
width: 400px;
|
width: 400px;
|
||||||
max-height: calc(50vh - 25px);
|
max-height: calc(48vh - 50px);
|
||||||
overflow: scroll;
|
|
||||||
max-width: 48vw;
|
max-width: 48vw;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
#helpCameraSettings h1 {
|
#helpCameraSettings h1 {
|
||||||
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
||||||
@ -59,6 +60,9 @@
|
|||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
margin: 0px 20px;
|
margin: 0px 20px;
|
||||||
}
|
}
|
||||||
|
#helpCameraSettings section p a{
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
#helpCameraSettings section p.err{
|
#helpCameraSettings section p.err{
|
||||||
color: #ff0000;
|
color: #ff0000;
|
||||||
}
|
}
|
||||||
@ -73,6 +77,12 @@
|
|||||||
width: 200px;
|
width: 200px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
@media only screen and (max-width: 800px),
|
||||||
|
only screen and (max-height: 600px) {
|
||||||
|
#helpCameraSettings{
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<form id="helpCameraSettings" hidden>
|
<form id="helpCameraSettings" hidden>
|
||||||
@ -88,6 +98,10 @@
|
|||||||
<p>If you prefer to continue without allowing camera and microphone access, click on Continue</p>
|
<p>If you prefer to continue without allowing camera and microphone access, click on Continue</p>
|
||||||
<p id='browserHelpSetting'></p>
|
<p id='browserHelpSetting'></p>
|
||||||
</section>
|
</section>
|
||||||
|
<!--<section class="text-center">
|
||||||
|
<p>If your problem persist, please contact us: <a id="mailto" href="mailto:workadventure@thecodingmachine.com?subject=Support camera and microphone settings" target="_blank"> workadventure@thecodingmachine.com</a>.</p>
|
||||||
|
</section>-->
|
||||||
|
</section>
|
||||||
<section class="action">
|
<section class="action">
|
||||||
<a href="#" id="helpCameraSettingsFormRefresh">Refresh</a>
|
<a href="#" id="helpCameraSettingsFormRefresh">Refresh</a>
|
||||||
<button type="submit" id="helpCameraSettingsFormContinue">Continue</button>
|
<button type="submit" id="helpCameraSettingsFormContinue">Continue</button>
|
||||||
|
8
front/dist/resources/html/loginScene.html
vendored
@ -11,7 +11,7 @@
|
|||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
color: #ebeeee;
|
color: #ebeeee;
|
||||||
max-height: 40vh;
|
max-height: 40vh;
|
||||||
overflow: scroll;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
#loginScene h1 {
|
#loginScene h1 {
|
||||||
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
||||||
@ -93,6 +93,12 @@
|
|||||||
width: 160px;
|
width: 160px;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
@media only screen and (max-width: 800px),
|
||||||
|
only screen and (max-height: 600px) {
|
||||||
|
#loginScene{
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<form id="loginScene" hidden>
|
<form id="loginScene" hidden>
|
||||||
|
@ -8,11 +8,10 @@
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
margin: 10px auto 0;
|
margin: 10px auto 0;
|
||||||
color: #ebeeee;
|
color: #ebeeee;
|
||||||
max-height: 40vh;
|
max-height: 48vh;
|
||||||
overflow: scroll;
|
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
width: 40vw;
|
width: 40vw;
|
||||||
overflow: unset;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
#selectCharacterScene h1 {
|
#selectCharacterScene h1 {
|
||||||
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
||||||
@ -118,6 +117,9 @@
|
|||||||
}
|
}
|
||||||
@media only screen and (max-width: 800px),
|
@media only screen and (max-width: 800px),
|
||||||
only screen and (max-height: 600px) {
|
only screen and (max-height: 600px) {
|
||||||
|
#selectCharacterScene{
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
#selectCharacterScene section button.selectCharacterButton#selectCharacterButtonRight{
|
#selectCharacterScene section button.selectCharacterButton#selectCharacterButtonRight{
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
18
front/dist/resources/style/mobile-style.scss
vendored
@ -23,27 +23,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.btn-cam-action {
|
.btn-cam-action {
|
||||||
|
min-width: 150px;
|
||||||
|
|
||||||
&:hover{
|
&:hover{
|
||||||
transform: translateY(20px);
|
transform: translateY(20px);
|
||||||
}
|
}
|
||||||
div {
|
div {
|
||||||
|
margin: 0 1%;
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #666;
|
background-color: #666;
|
||||||
}
|
}
|
||||||
|
margin-bottom: 30px;
|
||||||
bottom: 30px;
|
|
||||||
|
|
||||||
&.btn-micro {
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.btn-monitor {
|
|
||||||
right: 130px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.btn-video {
|
|
||||||
right: 65px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
102
front/dist/resources/style/style.css
vendored
@ -98,7 +98,7 @@ body .message-info.warning{
|
|||||||
}
|
}
|
||||||
|
|
||||||
.video-container button.report:hover {
|
.video-container button.report:hover {
|
||||||
width: 150px;
|
width: 160px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-container button.report img{
|
.video-container button.report img{
|
||||||
@ -126,6 +126,7 @@ body .message-info.warning{
|
|||||||
|
|
||||||
.video-container video{
|
.video-container video{
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-container video:focus{
|
.video-container video:focus{
|
||||||
@ -141,6 +142,7 @@ body .message-info.warning{
|
|||||||
right: 15px;
|
right: 15px;
|
||||||
bottom: 30px;
|
bottom: 30px;
|
||||||
border-radius: 15px 15px 15px 15px;
|
border-radius: 15px 15px 15px 15px;
|
||||||
|
max-height: 20%;
|
||||||
}
|
}
|
||||||
|
|
||||||
video#myCamVideo{
|
video#myCamVideo{
|
||||||
@ -152,19 +154,60 @@ video#myCamVideo{
|
|||||||
/*height: 113px;*/
|
/*height: 113px;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sound-progress{
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
right: 14px;
|
||||||
|
top: calc(50% - 5px);
|
||||||
|
}
|
||||||
|
.sound-progress.active{
|
||||||
|
display: table-column;
|
||||||
|
}
|
||||||
|
.sound-progress span{
|
||||||
|
position: absolute;
|
||||||
|
color: black;
|
||||||
|
background-color: #00000020;
|
||||||
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.sound-progress span.active{
|
||||||
|
background-color: #00c3ff66
|
||||||
|
}
|
||||||
|
.sound-progress span:nth-child(1){
|
||||||
|
top: calc(50% + 20px);
|
||||||
|
}
|
||||||
|
.sound-progress span:nth-child(2){
|
||||||
|
top: calc(50% + 10px);
|
||||||
|
}
|
||||||
|
.sound-progress span:nth-child(3){
|
||||||
|
top: calc(50% - 0px);
|
||||||
|
}
|
||||||
|
.sound-progress span:nth-child(4){
|
||||||
|
top: calc(50% - 10px);
|
||||||
|
}
|
||||||
|
.sound-progress span:nth-child(5){
|
||||||
|
top: calc(50% - 20px);
|
||||||
|
}
|
||||||
|
|
||||||
.btn-cam-action {
|
.btn-cam-action {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0px;
|
display: inline-flex;
|
||||||
right: 0px;
|
bottom: 10px;
|
||||||
width: 450px;
|
right: 15px;
|
||||||
height: 150px;
|
width: 15vw;
|
||||||
|
height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
justify-items: center;
|
||||||
}
|
}
|
||||||
/*btn animation*/
|
/*btn animation*/
|
||||||
.btn-cam-action div{
|
.btn-cam-action div{
|
||||||
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
||||||
position: absolute;
|
/*position: absolute;*/
|
||||||
border: solid 0px black;
|
border: solid 0px black;
|
||||||
width: 44px;
|
width: 44px;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
@ -173,7 +216,8 @@ video#myCamVideo{
|
|||||||
border-radius: 48px;
|
border-radius: 48px;
|
||||||
transform: translateY(20px);
|
transform: translateY(20px);
|
||||||
transition-timing-function: ease-in-out;
|
transition-timing-function: ease-in-out;
|
||||||
bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
margin: 0 4%;
|
||||||
}
|
}
|
||||||
.btn-cam-action div.disabled {
|
.btn-cam-action div.disabled {
|
||||||
background: #d75555;
|
background: #d75555;
|
||||||
@ -192,17 +236,17 @@ video#myCamVideo{
|
|||||||
.btn-micro{
|
.btn-micro{
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
transition: all .3s;
|
transition: all .3s;
|
||||||
right: 44px;
|
/*right: 44px;*/
|
||||||
}
|
}
|
||||||
.btn-video{
|
.btn-video{
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
transition: all .25s;
|
transition: all .25s;
|
||||||
right: 134px;
|
/*right: 134px;*/
|
||||||
}
|
}
|
||||||
.btn-monitor{
|
.btn-monitor{
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
transition: all .2s;
|
transition: all .2s;
|
||||||
right: 224px;
|
/*right: 224px;*/
|
||||||
}
|
}
|
||||||
.btn-copy{
|
.btn-copy{
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
@ -500,12 +544,20 @@ input[type=range]:focus::-ms-fill-upper {
|
|||||||
/* TODO: DO WE NEED FLEX HERE???? WE WANT A SIDEBAR OF EXACTLY 25% (note: flex useful for direction!!!) */
|
/* TODO: DO WE NEED FLEX HERE???? WE WANT A SIDEBAR OF EXACTLY 25% (note: flex useful for direction!!!) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.game-overlay + div {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-overlay + div > div {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.game-overlay.active {
|
.game-overlay.active {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.game-overlay video {
|
.game-overlay video {
|
||||||
width: 100%
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-section {
|
.main-section {
|
||||||
@ -521,6 +573,7 @@ input[type=range]:focus::-ms-fill-upper {
|
|||||||
flex-basis: 96%;
|
flex-basis: 96%;
|
||||||
transition: margin-left 0.2s, margin-right 0.2s, margin-bottom 0.2s, margin-top 0.2s, flex-basis 0.2s;
|
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;
|
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
||||||
|
pointer-events: auto;
|
||||||
/*flex-shrink: 2;*/
|
/*flex-shrink: 2;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,7 +585,6 @@ input[type=range]:focus::-ms-fill-upper {
|
|||||||
.sidebar {
|
.sidebar {
|
||||||
flex: 0 0 25%;
|
flex: 0 0 25%;
|
||||||
display: flex;
|
display: flex;
|
||||||
pointer-events: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar > div {
|
.sidebar > div {
|
||||||
@ -540,12 +592,17 @@ 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;
|
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;
|
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
||||||
border-radius: 15px 15px 15px 15px;
|
border-radius: 15px 15px 15px 15px;
|
||||||
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar > div:hover {
|
.sidebar > div:hover {
|
||||||
margin: 0%;
|
margin: 0%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar > div video {
|
||||||
|
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
||||||
|
}
|
||||||
|
|
||||||
/* Let's make sure videos are vertically centered if they need to be cropped */
|
/* Let's make sure videos are vertically centered if they need to be cropped */
|
||||||
.media-container {
|
.media-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -1110,17 +1167,34 @@ div.action{
|
|||||||
animation-iteration-count: infinite;
|
animation-iteration-count: infinite;
|
||||||
animation-timing-function: ease-in-out;
|
animation-timing-function: ease-in-out;
|
||||||
}
|
}
|
||||||
|
div.action.info,
|
||||||
|
div.action.warning,
|
||||||
|
div.action.danger{
|
||||||
|
transition: all 1s ease;
|
||||||
|
animation: mymove 1s;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
animation-timing-function: ease-in-out;
|
||||||
|
}
|
||||||
div.action p.action-body{
|
div.action p.action-body{
|
||||||
|
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background-color: #2d2d2dba;
|
background-color: #2d2d2dba;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
max-width: 250px;
|
max-width: 350px;
|
||||||
margin-left: calc(50% - 125px);
|
margin-left: calc(50% - 175px);
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
}
|
}
|
||||||
|
div.action.warning p.action-body{
|
||||||
|
background-color: #ff9800eb;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
div.action.danger p.action-body{
|
||||||
|
background-color: #da0000e3;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
.popUpElement{
|
.popUpElement{
|
||||||
font-family: 'Press Start 2P';
|
font-family: 'Press Start 2P';
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
124
front/dist/static/images/favicons/manifest.json
vendored
@ -1,41 +1,149 @@
|
|||||||
{
|
{
|
||||||
"name": "App",
|
"short_name": "WA",
|
||||||
|
"name": "WorkAdventure",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "\/android-icon-36x36.png",
|
"src": "/static/images/favicons/apple-icon-57x57.png",
|
||||||
|
"sizes": "57x57",
|
||||||
|
"type": "image\/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/apple-icon-60x60.png",
|
||||||
|
"sizes": "60x60",
|
||||||
|
"type": "image\/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/apple-icon-72x72.png",
|
||||||
|
"sizes": "72x72",
|
||||||
|
"type": "image\/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/apple-icon-76x76.png",
|
||||||
|
"sizes": "76x76",
|
||||||
|
"type": "image\/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/apple-icon-114x114.png",
|
||||||
|
"sizes": "114x114",
|
||||||
|
"type": "image\/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/apple-icon-120x120.png",
|
||||||
|
"sizes": "120x120",
|
||||||
|
"type": "image\/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/apple-icon-144x144.png",
|
||||||
|
"sizes": "144x144",
|
||||||
|
"type": "image\/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/apple-icon-152x152.png",
|
||||||
|
"sizes": "152x152",
|
||||||
|
"type": "image\/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/apple-icon-180x180.png",
|
||||||
|
"sizes": "180x180",
|
||||||
|
"type": "image\/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/android-icon-36x36.png",
|
||||||
"sizes": "36x36",
|
"sizes": "36x36",
|
||||||
"type": "image\/png",
|
"type": "image\/png",
|
||||||
"density": "0.75"
|
"density": "0.75"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "\/android-icon-48x48.png",
|
"src": "/static/images/favicons/android-icon-48x48.png",
|
||||||
"sizes": "48x48",
|
"sizes": "48x48",
|
||||||
"type": "image\/png",
|
"type": "image\/png",
|
||||||
"density": "1.0"
|
"density": "1.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "\/android-icon-72x72.png",
|
"src": "/static/images/favicons/android-icon-72x72.png",
|
||||||
|
"sizes": "72x72",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "1.5"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/favicon-16x16.png",
|
||||||
|
"sizes": "16x16",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/favicon-32x32.png",
|
||||||
|
"sizes": "32x32",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "1.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/favicon-96x96.png",
|
||||||
|
"sizes": "96x96",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "2.0"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/android-icon-36x36.png",
|
||||||
|
"sizes": "36x36",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/android-icon-48x48.png",
|
||||||
|
"sizes": "48x48",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/images/favicons/android-icon-72x72.png",
|
||||||
"sizes": "72x72",
|
"sizes": "72x72",
|
||||||
"type": "image\/png",
|
"type": "image\/png",
|
||||||
"density": "1.5"
|
"density": "1.5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "\/android-icon-96x96.png",
|
"src": "/static/images/favicons/android-icon-96x96.png",
|
||||||
"sizes": "96x96",
|
"sizes": "96x96",
|
||||||
"type": "image\/png",
|
"type": "image\/png",
|
||||||
"density": "2.0"
|
"density": "2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "\/android-icon-144x144.png",
|
"src": "/static/images/favicons/android-icon-144x144.png",
|
||||||
"sizes": "144x144",
|
"sizes": "144x144",
|
||||||
"type": "image\/png",
|
"type": "image\/png",
|
||||||
"density": "3.0"
|
"density": "3.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "\/android-icon-192x192.png",
|
"src": "/static/images/favicons/android-icon-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image\/png",
|
"type": "image\/png",
|
||||||
"density": "4.0"
|
"density": "4.0"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"start_url": "/",
|
||||||
|
"background_color": "#000000",
|
||||||
|
"display_override": ["window-control-overlay", "minimal-ui"],
|
||||||
|
"display": "standalone",
|
||||||
|
"scope": "/",
|
||||||
|
"theme_color": "#000000",
|
||||||
|
"shortcuts": [
|
||||||
|
{
|
||||||
|
"name": "WorkAdventures",
|
||||||
|
"short_name": "WA",
|
||||||
|
"description": "WorkAdventure application",
|
||||||
|
"url": "/",
|
||||||
|
"icons": [{ "src": "/static/images/favicons/android-icon-192x192.png", "sizes": "192x192" }]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "WorkAdventure application",
|
||||||
|
"screenshots": [],
|
||||||
|
"related_applications": [{
|
||||||
|
"platform": "web",
|
||||||
|
"url": "https://workadventu.re"
|
||||||
|
}, {
|
||||||
|
"platform": "play",
|
||||||
|
"url": "https://play.workadventu.re"
|
||||||
|
}]
|
||||||
}
|
}
|
@ -30,10 +30,10 @@
|
|||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"generic-type-guard": "^3.2.0",
|
"generic-type-guard": "^3.2.0",
|
||||||
"google-protobuf": "^3.13.0",
|
"google-protobuf": "^3.13.0",
|
||||||
"phaser": "3.24.1",
|
"phaser": "^3.54.0",
|
||||||
"phaser3-rex-plugins": "^1.1.42",
|
"phaser3-rex-plugins": "^1.1.42",
|
||||||
"queue-typescript": "^1.0.1",
|
"queue-typescript": "^1.0.1",
|
||||||
"quill": "^1.3.7",
|
"quill": "1.3.6",
|
||||||
"rxjs": "^6.6.3",
|
"rxjs": "^6.6.3",
|
||||||
"simple-peer": "^9.6.2",
|
"simple-peer": "^9.6.2",
|
||||||
"socket.io-client": "^2.3.0",
|
"socket.io-client": "^2.3.0",
|
||||||
|
@ -2,7 +2,6 @@ import {HtmlUtils} from "../WebRtc/HtmlUtils";
|
|||||||
import {UserInputManager} from "../Phaser/UserInput/UserInputManager";
|
import {UserInputManager} from "../Phaser/UserInput/UserInputManager";
|
||||||
import {RoomConnection} from "../Connexion/RoomConnection";
|
import {RoomConnection} from "../Connexion/RoomConnection";
|
||||||
import {PlayGlobalMessageInterface} from "../Connexion/ConnexionModels";
|
import {PlayGlobalMessageInterface} from "../Connexion/ConnexionModels";
|
||||||
import {ADMIN_URL} from "../Enum/EnvironmentVariable";
|
|
||||||
import {AdminMessageEventTypes} from "../Connexion/AdminMessagesService";
|
import {AdminMessageEventTypes} from "../Connexion/AdminMessagesService";
|
||||||
|
|
||||||
export const CLASS_CONSOLE_MESSAGE = 'main-console';
|
export const CLASS_CONSOLE_MESSAGE = 'main-console';
|
||||||
@ -162,10 +161,11 @@ export class ConsoleGlobalMessageManager {
|
|||||||
this.divMessageConsole.appendChild(section);
|
this.divMessageConsole.appendChild(section);
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
try{
|
||||||
// Start loading CSS
|
// Start loading CSS
|
||||||
const cssPromise = ConsoleGlobalMessageManager.loadCss();
|
const cssPromise = ConsoleGlobalMessageManager.loadCss();
|
||||||
// Import quill
|
// Import quill
|
||||||
const Quill:any = await import("quill"); // eslint-disable-line @typescript-eslint/no-explicit-any
|
const {default: Quill}:any = await import("quill"); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
// Wait for CSS to be loaded
|
// Wait for CSS to be loaded
|
||||||
await cssPromise;
|
await cssPromise;
|
||||||
|
|
||||||
@ -198,6 +198,9 @@ export class ConsoleGlobalMessageManager {
|
|||||||
toolbar: toolbarOptions
|
toolbar: toolbarOptions
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
}catch(err){
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,14 +64,14 @@ class IframeListener {
|
|||||||
// Do we trust the sender of this message?
|
// Do we trust the sender of this message?
|
||||||
// Let's only accept messages from the iframe that are allowed.
|
// Let's only accept messages from the iframe that are allowed.
|
||||||
// Note: maybe we could restrict on the domain too for additional security (in case the iframe goes to another domain).
|
// Note: maybe we could restrict on the domain too for additional security (in case the iframe goes to another domain).
|
||||||
let found = false;
|
let foundSrc: string | null = null;
|
||||||
for (const iframe of this.iframes) {
|
for (const iframe of this.iframes) {
|
||||||
if (iframe.contentWindow === message.source) {
|
if (iframe.contentWindow === message.source) {
|
||||||
found = true;
|
foundSrc = iframe.src;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!foundSrc) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,11 @@ class IframeListener {
|
|||||||
scriptUtils.goToPage(payload.data.url);
|
scriptUtils.goToPage(payload.data.url);
|
||||||
}
|
}
|
||||||
else if (payload.type === 'openCoWebSite' && isOpenCoWebsite(payload.data)) {
|
else if (payload.type === 'openCoWebSite' && isOpenCoWebsite(payload.data)) {
|
||||||
scriptUtils.openCoWebsite(payload.data.url);
|
const scriptUrl = [...this.scripts.keys()].find(key => {
|
||||||
|
return this.scripts.get(key)?.contentWindow == message.source
|
||||||
|
})
|
||||||
|
|
||||||
|
scriptUtils.openCoWebsite(payload.data.url, scriptUrl || foundSrc);
|
||||||
}
|
}
|
||||||
else if(payload.type === 'closeCoWebSite') {
|
else if(payload.type === 'closeCoWebSite') {
|
||||||
scriptUtils.closeCoWebSite();
|
scriptUtils.closeCoWebSite();
|
||||||
|
@ -11,8 +11,8 @@ class ScriptUtils {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public openCoWebsite(url : string){
|
public openCoWebsite(url: string, base: string) {
|
||||||
coWebsiteManager.loadCoWebsite(url,url);
|
coWebsiteManager.loadCoWebsite(url, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeCoWebSite(){
|
public closeCoWebSite(){
|
||||||
|
@ -10,7 +10,7 @@ export interface CharacterTexture {
|
|||||||
export const maxUserNameLength: number = MAX_USERNAME_LENGTH;
|
export const maxUserNameLength: number = MAX_USERNAME_LENGTH;
|
||||||
|
|
||||||
export function isUserNameValid(value: string): boolean {
|
export function isUserNameValid(value: string): boolean {
|
||||||
const regexp = new RegExp('^[A-Za-z]{1,'+maxUserNameLength+'}$');
|
const regexp = new RegExp('^[A-Za-z0-9]{1,'+maxUserNameLength+'}$');
|
||||||
return regexp.test(value);
|
return regexp.test(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,8 @@ import {
|
|||||||
SendJitsiJwtMessage,
|
SendJitsiJwtMessage,
|
||||||
CharacterLayerMessage,
|
CharacterLayerMessage,
|
||||||
PingMessage,
|
PingMessage,
|
||||||
SendUserMessage, BanUserMessage
|
SendUserMessage,
|
||||||
|
BanUserMessage
|
||||||
} from "../Messages/generated/messages_pb"
|
} from "../Messages/generated/messages_pb"
|
||||||
|
|
||||||
import {UserSimplePeerInterface} from "../WebRtc/SimplePeer";
|
import {UserSimplePeerInterface} from "../WebRtc/SimplePeer";
|
||||||
@ -169,6 +170,9 @@ export class RoomConnection implements RoomConnection {
|
|||||||
} else if (message.hasWorldfullmessage()) {
|
} else if (message.hasWorldfullmessage()) {
|
||||||
worldFullMessageStream.onMessage();
|
worldFullMessageStream.onMessage();
|
||||||
this.closed = true;
|
this.closed = true;
|
||||||
|
} else if (message.hasWorldconnexionmessage()) {
|
||||||
|
worldFullMessageStream.onMessage(message.getWorldconnexionmessage()?.getMessage());
|
||||||
|
this.closed = true;
|
||||||
}else if (message.hasWebrtcsignaltoclientmessage()) {
|
}else if (message.hasWebrtcsignaltoclientmessage()) {
|
||||||
this.dispatch(EventMessage.WEBRTC_SIGNAL, message.getWebrtcsignaltoclientmessage());
|
this.dispatch(EventMessage.WEBRTC_SIGNAL, message.getWebrtcsignaltoclientmessage());
|
||||||
} else if (message.hasWebrtcscreensharingsignaltoclientmessage()) {
|
} else if (message.hasWebrtcscreensharingsignaltoclientmessage()) {
|
||||||
|
@ -2,12 +2,12 @@ import {Subject} from "rxjs";
|
|||||||
|
|
||||||
class WorldFullMessageStream {
|
class WorldFullMessageStream {
|
||||||
|
|
||||||
private _stream:Subject<void> = new Subject();
|
private _stream:Subject<string|null> = new Subject<string|null>();
|
||||||
public stream = this._stream.asObservable();
|
public stream = this._stream.asObservable();
|
||||||
|
|
||||||
|
|
||||||
onMessage() {
|
onMessage(message? :string) {
|
||||||
this._stream.next();
|
this._stream.next(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,8 +10,6 @@ const TURN_USER: string = process.env.TURN_USER || '';
|
|||||||
const TURN_PASSWORD: string = process.env.TURN_PASSWORD || '';
|
const TURN_PASSWORD: string = process.env.TURN_PASSWORD || '';
|
||||||
const JITSI_URL : string|undefined = (process.env.JITSI_URL === '') ? undefined : process.env.JITSI_URL;
|
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 JITSI_PRIVATE_MODE : boolean = process.env.JITSI_PRIVATE_MODE == "true";
|
||||||
const RESOLUTION = 2;
|
|
||||||
const ZOOM_LEVEL = 1/*3/4*/;
|
|
||||||
const POSITION_DELAY = 200; // Wait 200ms between sending position events
|
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
|
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;
|
export const MAX_USERNAME_LENGTH = parseInt(process.env.MAX_USERNAME_LENGTH || '') || 8;
|
||||||
@ -25,8 +23,6 @@ export {
|
|||||||
PUSHER_URL,
|
PUSHER_URL,
|
||||||
UPLOADER_URL,
|
UPLOADER_URL,
|
||||||
ADMIN_URL,
|
ADMIN_URL,
|
||||||
RESOLUTION,
|
|
||||||
ZOOM_LEVEL,
|
|
||||||
POSITION_DELAY,
|
POSITION_DELAY,
|
||||||
MAX_EXTRAPOLATION_TIME,
|
MAX_EXTRAPOLATION_TIME,
|
||||||
STUN_SERVER,
|
STUN_SERVER,
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import VirtualJoystick from 'phaser3-rex-plugins/plugins/virtualjoystick.js';
|
import VirtualJoystick from 'phaser3-rex-plugins/plugins/virtualjoystick.js';
|
||||||
|
import ScaleManager = Phaser.Scale.ScaleManager;
|
||||||
const outOfScreenX = -1000;
|
import {waScaleManager} from "../Services/WaScaleManager";
|
||||||
const outOfScreenY = -1000;
|
|
||||||
|
|
||||||
|
|
||||||
//the assets were found here: https://hannemann.itch.io/virtual-joystick-pack-free
|
//the assets were found here: https://hannemann.itch.io/virtual-joystick-pack-free
|
||||||
export const joystickBaseKey = 'joystickBase';
|
export const joystickBaseKey = 'joystickBase';
|
||||||
@ -10,26 +8,58 @@ export const joystickBaseImg = 'resources/objects/joystickSplitted.png';
|
|||||||
export const joystickThumbKey = 'joystickThumb';
|
export const joystickThumbKey = 'joystickThumb';
|
||||||
export const joystickThumbImg = 'resources/objects/smallHandleFilledGrey.png';
|
export const joystickThumbImg = 'resources/objects/smallHandleFilledGrey.png';
|
||||||
|
|
||||||
|
const baseSize = 50;
|
||||||
|
const thumbSize = 25;
|
||||||
|
const radius = 17.5;
|
||||||
|
|
||||||
export class MobileJoystick extends VirtualJoystick {
|
export class MobileJoystick extends VirtualJoystick {
|
||||||
|
private resizeCallback: () => void;
|
||||||
|
|
||||||
constructor(scene: Phaser.Scene) {
|
constructor(scene: Phaser.Scene) {
|
||||||
super(scene, {
|
super(scene, {
|
||||||
x: outOfScreenX,
|
x: -1000,
|
||||||
y: outOfScreenY,
|
y: -1000,
|
||||||
radius: 20,
|
radius: radius * window.devicePixelRatio,
|
||||||
base: scene.add.image(0, 0, joystickBaseKey).setDisplaySize(60, 60).setDepth(99999),
|
base: scene.add.image(0, 0, joystickBaseKey).setDisplaySize(baseSize * window.devicePixelRatio, baseSize * window.devicePixelRatio).setDepth(99999),
|
||||||
thumb: scene.add.image(0, 0, joystickThumbKey).setDisplaySize(30, 30).setDepth(99999),
|
thumb: scene.add.image(0, 0, joystickThumbKey).setDisplaySize(thumbSize * window.devicePixelRatio, thumbSize * window.devicePixelRatio).setDepth(99999),
|
||||||
enable: true,
|
enable: true,
|
||||||
dir: "8dir",
|
dir: "8dir",
|
||||||
});
|
});
|
||||||
|
this.visible = false;
|
||||||
|
this.enable = false;
|
||||||
|
|
||||||
this.scene.input.on('pointerdown', (pointer: { x: number; y: number; }) => {
|
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.x = pointer.x;
|
||||||
this.y = pointer.y;
|
this.y = pointer.y;
|
||||||
|
this.visible = true;
|
||||||
|
this.enable = true;
|
||||||
|
} else {
|
||||||
|
this.visible = false;
|
||||||
|
this.enable = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.scene.input.on('pointerup', () => {
|
this.scene.input.on('pointerup', () => {
|
||||||
this.x = outOfScreenX;
|
this.visible = false;
|
||||||
this.y = outOfScreenY;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
52
front/src/Phaser/Game/DirtyScene.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import {ResizableScene} from "../Login/ResizableScene";
|
||||||
|
import GameObject = Phaser.GameObjects.GameObject;
|
||||||
|
import Events = Phaser.Scenes.Events;
|
||||||
|
import AnimationEvents = Phaser.Animations.Events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A scene that can track its dirty/pristine state.
|
||||||
|
*/
|
||||||
|
export abstract class DirtyScene extends ResizableScene {
|
||||||
|
private isAlreadyTracking: boolean = false;
|
||||||
|
protected dirty:boolean = true;
|
||||||
|
private objectListChanged:boolean = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track all objects added to the scene and adds a callback each time an animation is added.
|
||||||
|
* Whenever an object is added, removed, or when an animation is played, the dirty state is set to true.
|
||||||
|
*
|
||||||
|
* Note: this does not work with animations from sprites inside containers.
|
||||||
|
*/
|
||||||
|
protected trackDirtyAnims(): void {
|
||||||
|
if (this.isAlreadyTracking) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.isAlreadyTracking = true;
|
||||||
|
const trackAnimationFunction = this.trackAnimation.bind(this);
|
||||||
|
this.events.on(Events.ADDED_TO_SCENE, (gameObject: GameObject) => {
|
||||||
|
this.objectListChanged = true;
|
||||||
|
gameObject.on(AnimationEvents.ANIMATION_UPDATE, trackAnimationFunction);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.events.on(Events.REMOVED_FROM_SCENE, (gameObject: GameObject) => {
|
||||||
|
this.objectListChanged = true;
|
||||||
|
gameObject.removeListener(AnimationEvents.ANIMATION_UPDATE, trackAnimationFunction);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.events.on(Events.RENDER, () => {
|
||||||
|
this.objectListChanged = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private trackAnimation(): void {
|
||||||
|
this.objectListChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isDirty(): boolean {
|
||||||
|
return this.dirty || this.objectListChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public onResize(ev: UIEvent): void {
|
||||||
|
this.objectListChanged = true;
|
||||||
|
}
|
||||||
|
}
|
88
front/src/Phaser/Game/Game.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
const Events = Phaser.Core.Events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A specialization of the main Phaser Game scene.
|
||||||
|
* It comes with an optimization to skip rendering.
|
||||||
|
*
|
||||||
|
* Beware, the "step" function might vary in future versions of Phaser.
|
||||||
|
*/
|
||||||
|
export class Game extends Phaser.Game {
|
||||||
|
public step(time: number, delta: number)
|
||||||
|
{
|
||||||
|
// @ts-ignore
|
||||||
|
if (this.pendingDestroy)
|
||||||
|
{
|
||||||
|
// @ts-ignore
|
||||||
|
return this.runDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
const eventEmitter = this.events;
|
||||||
|
|
||||||
|
// Global Managers like Input and Sound update in the prestep
|
||||||
|
|
||||||
|
eventEmitter.emit(Events.PRE_STEP, time, delta);
|
||||||
|
|
||||||
|
// This is mostly meant for user-land code and plugins
|
||||||
|
|
||||||
|
eventEmitter.emit(Events.STEP, time, delta);
|
||||||
|
|
||||||
|
// Update the Scene Manager and all active Scenes
|
||||||
|
|
||||||
|
this.scene.update(time, delta);
|
||||||
|
|
||||||
|
// Our final event before rendering starts
|
||||||
|
|
||||||
|
eventEmitter.emit(Events.POST_STEP, time, delta);
|
||||||
|
|
||||||
|
// This "if" is the changed introduced by the new "Game" class to avoid rendering unnecessarily.
|
||||||
|
if (this.isDirty()) {
|
||||||
|
const renderer = this.renderer;
|
||||||
|
|
||||||
|
// Run the Pre-render (clearing the canvas, setting background colors, etc)
|
||||||
|
|
||||||
|
renderer.preRender();
|
||||||
|
|
||||||
|
eventEmitter.emit(Events.PRE_RENDER, renderer, time, delta);
|
||||||
|
|
||||||
|
// The main render loop. Iterates all Scenes and all Cameras in those scenes, rendering to the renderer instance.
|
||||||
|
|
||||||
|
this.scene.render(renderer);
|
||||||
|
|
||||||
|
// The Post-Render call. Tidies up loose end, takes snapshots, etc.
|
||||||
|
|
||||||
|
renderer.postRender();
|
||||||
|
|
||||||
|
// The final event before the step repeats. Your last chance to do anything to the canvas before it all starts again.
|
||||||
|
|
||||||
|
eventEmitter.emit(Events.POST_RENDER, renderer, time, delta);
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
this.scene.isProcessing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private isDirty(): boolean {
|
||||||
|
// Loop through the scenes in forward order
|
||||||
|
for (let i = 0; i < this.scene.scenes.length; i++)
|
||||||
|
{
|
||||||
|
const scene = this.scene.scenes[i];
|
||||||
|
const sys = scene.sys;
|
||||||
|
|
||||||
|
if (sys.settings.visible && sys.settings.status >= Phaser.Scenes.LOADING && sys.settings.status < Phaser.Scenes.SLEEPING)
|
||||||
|
{
|
||||||
|
// @ts-ignore
|
||||||
|
if(typeof scene.isDirty === 'function') {
|
||||||
|
// @ts-ignore
|
||||||
|
const isDirty = scene.isDirty() || scene.tweens.getAllTweens().length > 0;
|
||||||
|
if (isDirty) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -89,11 +89,8 @@ export class GameManager {
|
|||||||
console.log('starting '+ (this.currentGameSceneName || this.startRoom.id))
|
console.log('starting '+ (this.currentGameSceneName || this.startRoom.id))
|
||||||
scenePlugin.start(this.currentGameSceneName || this.startRoom.id);
|
scenePlugin.start(this.currentGameSceneName || this.startRoom.id);
|
||||||
scenePlugin.launch(MenuSceneName);
|
scenePlugin.launch(MenuSceneName);
|
||||||
|
|
||||||
if (!localUserStore.getHelpCameraSettingsShown()) {
|
|
||||||
scenePlugin.launch(HelpCameraSettingsSceneName);//700
|
scenePlugin.launch(HelpCameraSettingsSceneName);//700
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public gameSceneIsCreated(scene: GameScene) {
|
public gameSceneIsCreated(scene: GameScene) {
|
||||||
this.currentGameSceneName = scene.scene.key;
|
this.currentGameSceneName = scene.scene.key;
|
||||||
|
@ -15,8 +15,6 @@ import {
|
|||||||
JITSI_PRIVATE_MODE,
|
JITSI_PRIVATE_MODE,
|
||||||
MAX_PER_GROUP,
|
MAX_PER_GROUP,
|
||||||
POSITION_DELAY,
|
POSITION_DELAY,
|
||||||
RESOLUTION,
|
|
||||||
ZOOM_LEVEL
|
|
||||||
} from "../../Enum/EnvironmentVariable";
|
} from "../../Enum/EnvironmentVariable";
|
||||||
import {
|
import {
|
||||||
ITiledMap,
|
ITiledMap,
|
||||||
@ -85,12 +83,16 @@ import DOMElement = Phaser.GameObjects.DOMElement;
|
|||||||
import {Subscription} from "rxjs";
|
import {Subscription} from "rxjs";
|
||||||
import {worldFullMessageStream} from "../../Connexion/WorldFullMessageStream";
|
import {worldFullMessageStream} from "../../Connexion/WorldFullMessageStream";
|
||||||
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
|
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
|
||||||
|
import RenderTexture = Phaser.GameObjects.RenderTexture;
|
||||||
|
import Tilemap = Phaser.Tilemaps.Tilemap;
|
||||||
|
import {DirtyScene} from "./DirtyScene";
|
||||||
import {TextUtils} from "../Components/TextUtils";
|
import {TextUtils} from "../Components/TextUtils";
|
||||||
import {LayersIterator} from "../Map/LayersIterator";
|
|
||||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||||
import {PinchManager} from "../UserInput/PinchManager";
|
import {PinchManager} from "../UserInput/PinchManager";
|
||||||
import {joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey} from "../Components/MobileJoystick";
|
import {joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey} from "../Components/MobileJoystick";
|
||||||
import { MenuScene, MenuSceneName } from '../Menu/MenuScene';
|
import { MenuScene, MenuSceneName } from '../Menu/MenuScene';
|
||||||
|
import {waScaleManager} from "../Services/WaScaleManager";
|
||||||
|
|
||||||
|
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
initPosition: PointInterface|null,
|
initPosition: PointInterface|null,
|
||||||
@ -129,13 +131,13 @@ interface DeleteGroupEventInterface {
|
|||||||
|
|
||||||
const defaultStartLayerName = 'start';
|
const defaultStartLayerName = 'start';
|
||||||
|
|
||||||
export class GameScene extends ResizableScene implements CenterListener {
|
export class GameScene extends DirtyScene implements CenterListener {
|
||||||
Terrains : Array<Phaser.Tilemaps.Tileset>;
|
Terrains : Array<Phaser.Tilemaps.Tileset>;
|
||||||
CurrentPlayer!: CurrentGamerInterface;
|
CurrentPlayer!: CurrentGamerInterface;
|
||||||
MapPlayers!: Phaser.Physics.Arcade.Group;
|
MapPlayers!: Phaser.Physics.Arcade.Group;
|
||||||
MapPlayersByKey : Map<number, RemotePlayer> = new Map<number, RemotePlayer>();
|
MapPlayersByKey : Map<number, RemotePlayer> = new Map<number, RemotePlayer>();
|
||||||
Map!: Phaser.Tilemaps.Tilemap;
|
Map!: Phaser.Tilemaps.Tilemap;
|
||||||
Layers!: Array<Phaser.Tilemaps.StaticTilemapLayer>;
|
Layers!: Array<Phaser.Tilemaps.TilemapLayer>;
|
||||||
Objects!: Array<Phaser.Physics.Arcade.Sprite>;
|
Objects!: Array<Phaser.Physics.Arcade.Sprite>;
|
||||||
mapFile!: ITiledMap;
|
mapFile!: ITiledMap;
|
||||||
groups: Map<number, Sprite>;
|
groups: Map<number, Sprite>;
|
||||||
@ -185,6 +187,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
private messageSubscription: Subscription|null = null;
|
private messageSubscription: Subscription|null = null;
|
||||||
private popUpElements : Map<number, DOMElement> = new Map<number, Phaser.GameObjects.DOMElement>();
|
private popUpElements : Map<number, DOMElement> = new Map<number, Phaser.GameObjects.DOMElement>();
|
||||||
private originalMapUrl: string|undefined;
|
private originalMapUrl: string|undefined;
|
||||||
|
private pinchManager: PinchManager|undefined;
|
||||||
|
|
||||||
constructor(private room: Room, MapUrlFile: string, customKey?: string|undefined) {
|
constructor(private room: Room, MapUrlFile: string, customKey?: string|undefined) {
|
||||||
super({
|
super({
|
||||||
@ -203,12 +206,11 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
})
|
})
|
||||||
this.connectionAnswerPromise = new Promise<RoomJoinedMessageInterface>((resolve, reject): void => {
|
this.connectionAnswerPromise = new Promise<RoomJoinedMessageInterface>((resolve, reject): void => {
|
||||||
this.connectionAnswerPromiseResolve = resolve;
|
this.connectionAnswerPromiseResolve = resolve;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//hook preload scene
|
//hook preload scene
|
||||||
preload(): void {
|
preload(): void {
|
||||||
addLoader(this);
|
|
||||||
const localUser = localUserStore.getLocalUser();
|
const localUser = localUserStore.getLocalUser();
|
||||||
const textures = localUser?.textures;
|
const textures = localUser?.textures;
|
||||||
if (textures) {
|
if (textures) {
|
||||||
@ -268,6 +270,9 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
|
|
||||||
this.load.spritesheet('layout_modes', 'resources/objects/layout_modes.png', {frameWidth: 32, frameHeight: 32});
|
this.load.spritesheet('layout_modes', 'resources/objects/layout_modes.png', {frameWidth: 32, frameHeight: 32});
|
||||||
this.load.bitmapFont('main_font', 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
this.load.bitmapFont('main_font', 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
||||||
|
|
||||||
|
//this function must stay at the end of preload function
|
||||||
|
addLoader(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: we need to put a "unknown" instead of a "any" and validate the structure of the JSON we are receiving.
|
// FIXME: we need to put a "unknown" instead of a "any" and validate the structure of the JSON we are receiving.
|
||||||
@ -366,15 +371,17 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
|
|
||||||
//hook create scene
|
//hook create scene
|
||||||
create(): void {
|
create(): void {
|
||||||
|
this.trackDirtyAnims();
|
||||||
|
|
||||||
gameManager.gameSceneIsCreated(this);
|
gameManager.gameSceneIsCreated(this);
|
||||||
urlManager.pushRoomIdToUrl(this.room);
|
urlManager.pushRoomIdToUrl(this.room);
|
||||||
this.startLayerName = urlManager.getStartLayerNameFromUrl();
|
this.startLayerName = urlManager.getStartLayerNameFromUrl();
|
||||||
|
|
||||||
if (touchScreenManager.supportTouchScreen) {
|
if (touchScreenManager.supportTouchScreen) {
|
||||||
new PinchManager(this);
|
this.pinchManager = new PinchManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.messageSubscription = worldFullMessageStream.stream.subscribe((message) => this.showWorldFullError())
|
this.messageSubscription = worldFullMessageStream.stream.subscribe((message) => this.showWorldFullError(message))
|
||||||
|
|
||||||
const playerName = gameManager.getPlayerName();
|
const playerName = gameManager.getPlayerName();
|
||||||
if (!playerName) {
|
if (!playerName) {
|
||||||
@ -396,12 +403,11 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
this.physics.world.setBounds(0, 0, this.Map.widthInPixels, this.Map.heightInPixels);
|
this.physics.world.setBounds(0, 0, this.Map.widthInPixels, this.Map.heightInPixels);
|
||||||
|
|
||||||
//add layer on map
|
//add layer on map
|
||||||
this.Layers = new Array<Phaser.Tilemaps.StaticTilemapLayer>();
|
this.Layers = new Array<Phaser.Tilemaps.TilemapLayer>();
|
||||||
|
|
||||||
let depth = -2;
|
let depth = -2;
|
||||||
for (const layer of this.gameMap.layersIterator) {
|
for (const layer of this.gameMap.layersIterator) {
|
||||||
if (layer.type === 'tilelayer') {
|
if (layer.type === 'tilelayer') {
|
||||||
this.addLayer(this.Map.createStaticLayer(layer.name, this.Terrains, 0, 0).setDepth(depth));
|
this.addLayer(this.Map.createLayer(layer.name, this.Terrains, 0, 0).setDepth(depth));
|
||||||
|
|
||||||
const exitSceneUrl = this.getExitSceneUrl(layer);
|
const exitSceneUrl = this.getExitSceneUrl(layer);
|
||||||
if (exitSceneUrl !== undefined) {
|
if (exitSceneUrl !== undefined) {
|
||||||
@ -437,8 +443,8 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||||||
|
|
||||||
|
|
||||||
//create input to move
|
//create input to move
|
||||||
mediaManager.setUserInputManager(this.userInputManager);
|
|
||||||
this.userInputManager = new UserInputManager(this);
|
this.userInputManager = new UserInputManager(this);
|
||||||
|
mediaManager.setUserInputManager(this.userInputManager);
|
||||||
|
|
||||||
if (localUserStore.getFullscreen()) {
|
if (localUserStore.getFullscreen()) {
|
||||||
document.querySelector('body')?.requestFullscreen();
|
document.querySelector('body')?.requestFullscreen();
|
||||||
@ -913,9 +919,11 @@ ${escapedMessage}
|
|||||||
audioManager.unloadAudio();
|
audioManager.unloadAudio();
|
||||||
// We are completely destroying the current scene to avoid using a half-backed instance when coming back to the same map.
|
// We are completely destroying the current scene to avoid using a half-backed instance when coming back to the same map.
|
||||||
this.connection?.closeConnection();
|
this.connection?.closeConnection();
|
||||||
this.simplePeer.closeAllConnections();
|
this.simplePeer?.closeAllConnections();
|
||||||
this.simplePeer?.unregister();
|
this.simplePeer?.unregister();
|
||||||
this.messageSubscription?.unsubscribe();
|
this.messageSubscription?.unsubscribe();
|
||||||
|
this.userInputManager.destroy();
|
||||||
|
this.pinchManager?.destroy();
|
||||||
|
|
||||||
for(const iframeEvents of this.iframeSubscriptionList){
|
for(const iframeEvents of this.iframeSubscriptionList){
|
||||||
iframeEvents.unsubscribe();
|
iframeEvents.unsubscribe();
|
||||||
@ -1063,17 +1071,18 @@ ${escapedMessage}
|
|||||||
//todo: in a dedicated class/function?
|
//todo: in a dedicated class/function?
|
||||||
initCamera() {
|
initCamera() {
|
||||||
this.cameras.main.setBounds(0,0, this.Map.widthInPixels, this.Map.heightInPixels);
|
this.cameras.main.setBounds(0,0, this.Map.widthInPixels, this.Map.heightInPixels);
|
||||||
|
this.cameras.main.startFollow(this.CurrentPlayer, true);
|
||||||
this.updateCameraOffset();
|
this.updateCameraOffset();
|
||||||
this.cameras.main.setZoom(ZOOM_LEVEL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addLayer(Layer : Phaser.Tilemaps.StaticTilemapLayer){
|
addLayer(Layer : Phaser.Tilemaps.TilemapLayer){
|
||||||
this.Layers.push(Layer);
|
this.Layers.push(Layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
createCollisionWithPlayer() {
|
createCollisionWithPlayer() {
|
||||||
|
this.physics.disableUpdate();
|
||||||
//add collision layer
|
//add collision layer
|
||||||
this.Layers.forEach((Layer: Phaser.Tilemaps.StaticTilemapLayer) => {
|
this.Layers.forEach((Layer: Phaser.Tilemaps.TilemapLayer) => {
|
||||||
this.physics.add.collider(this.CurrentPlayer, Layer, (object1: GameObject, object2: GameObject) => {
|
this.physics.add.collider(this.CurrentPlayer, Layer, (object1: GameObject, object2: GameObject) => {
|
||||||
//this.CurrentPlayer.say("Collision with layer : "+ (object2 as Tile).layer.name)
|
//this.CurrentPlayer.say("Collision with layer : "+ (object2 as Tile).layer.name)
|
||||||
});
|
});
|
||||||
@ -1202,12 +1211,24 @@ ${escapedMessage}
|
|||||||
* @param delta The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
|
* @param delta The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
|
||||||
*/
|
*/
|
||||||
update(time: number, delta: number) : void {
|
update(time: number, delta: number) : void {
|
||||||
mediaManager.setLastUpdateScene();
|
this.dirty = false;
|
||||||
|
mediaManager.updateScene();
|
||||||
this.currentTick = time;
|
this.currentTick = time;
|
||||||
|
if (this.CurrentPlayer.isMoving()) {
|
||||||
|
this.dirty = true;
|
||||||
|
}
|
||||||
this.CurrentPlayer.moveUser(delta);
|
this.CurrentPlayer.moveUser(delta);
|
||||||
|
if (this.CurrentPlayer.isMoving()) {
|
||||||
|
this.dirty = true;
|
||||||
|
this.physics.enableUpdate();
|
||||||
|
} else {
|
||||||
|
this.physics.disableUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Let's handle all events
|
// Let's handle all events
|
||||||
while (this.pendingEvents.length !== 0) {
|
while (this.pendingEvents.length !== 0) {
|
||||||
|
this.dirty = true;
|
||||||
const event = this.pendingEvents.dequeue();
|
const event = this.pendingEvents.dequeue();
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case "InitUserPositionEvent":
|
case "InitUserPositionEvent":
|
||||||
@ -1233,6 +1254,7 @@ ${escapedMessage}
|
|||||||
// Let's move all users
|
// Let's move all users
|
||||||
const updatedPlayersPositions = this.playersPositionInterpolator.getUpdatedPositions(time);
|
const updatedPlayersPositions = this.playersPositionInterpolator.getUpdatedPositions(time);
|
||||||
updatedPlayersPositions.forEach((moveEvent: HasMovedEvent, userId: number) => {
|
updatedPlayersPositions.forEach((moveEvent: HasMovedEvent, userId: number) => {
|
||||||
|
this.dirty = true;
|
||||||
const player: RemotePlayer | undefined = this.MapPlayersByKey.get(userId);
|
const player: RemotePlayer | undefined = this.MapPlayersByKey.get(userId);
|
||||||
if (player === undefined) {
|
if (player === undefined) {
|
||||||
throw new Error('Cannot find player with ID "' + userId + '"');
|
throw new Error('Cannot find player with ID "' + userId + '"');
|
||||||
@ -1402,7 +1424,8 @@ ${escapedMessage}
|
|||||||
this.connection?.emitActionableEvent(itemId, eventName, state, parameters);
|
this.connection?.emitActionableEvent(itemId, eventName, state, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onResize(): void {
|
public onResize(ev: UIEvent): void {
|
||||||
|
super.onResize(ev);
|
||||||
this.reposition();
|
this.reposition();
|
||||||
|
|
||||||
// Send new viewport to server
|
// Send new viewport to server
|
||||||
@ -1437,19 +1460,18 @@ ${escapedMessage}
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the offset of the character compared to the center of the screen according to the layout mananger
|
* 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 reamining space if there is a discussion going on.
|
* (tries to put the character in the center of the remaining space if there is a discussion going on.
|
||||||
*/
|
*/
|
||||||
private updateCameraOffset(): void {
|
private updateCameraOffset(): void {
|
||||||
const array = layoutManager.findBiggestAvailableArray();
|
const array = layoutManager.findBiggestAvailableArray();
|
||||||
let xCenter = (array.xEnd - array.xStart) / 2 + array.xStart;
|
const xCenter = (array.xEnd - array.xStart) / 2 + array.xStart;
|
||||||
let yCenter = (array.yEnd - array.yStart) / 2 + array.yStart;
|
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:
|
// 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 {
|
public onCenterChange(): void {
|
||||||
@ -1492,14 +1514,29 @@ ${escapedMessage}
|
|||||||
}
|
}
|
||||||
|
|
||||||
//todo: put this into an 'orchestrator' scene (EntryScene?)
|
//todo: put this into an 'orchestrator' scene (EntryScene?)
|
||||||
private showWorldFullError(): void {
|
private showWorldFullError(message: string|null): void {
|
||||||
this.cleanupClosingScene();
|
this.cleanupClosingScene();
|
||||||
this.scene.stop(ReconnectingSceneName);
|
this.scene.stop(ReconnectingSceneName);
|
||||||
|
this.scene.remove(ReconnectingSceneName);
|
||||||
this.userInputManager.disableControls();
|
this.userInputManager.disableControls();
|
||||||
|
//FIX ME to use status code
|
||||||
|
if(message == undefined){
|
||||||
this.scene.start(ErrorSceneName, {
|
this.scene.start(ErrorSceneName, {
|
||||||
title: 'Connection rejected',
|
title: 'Connection rejected',
|
||||||
subTitle: 'The world you are trying to join is full. Try again later.',
|
subTitle: 'The world you are trying to join is full. Try again later.',
|
||||||
message: 'If you want more information, you may contact us at: workadventure@thecodingmachine.com'
|
message: 'If you want more information, you may contact us at: workadventure@thecodingmachine.com'
|
||||||
});
|
});
|
||||||
|
}else{
|
||||||
|
this.scene.start(ErrorSceneName, {
|
||||||
|
title: 'Connection rejected',
|
||||||
|
subTitle: 'You cannot join the World. Try again later. \n\r \n\r Error: '+message+'.',
|
||||||
|
message: 'If you want more information, you may contact administrator or contact us at: workadventure@thecodingmachine.com'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zoomByFactor(zoomFactor: number) {
|
||||||
|
waScaleManager.zoomModifier *= zoomFactor;
|
||||||
|
this.updateCameraOffset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,24 +34,25 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
preload() {
|
preload() {
|
||||||
addLoader(this);
|
|
||||||
|
|
||||||
this.load.html(customizeSceneKey, 'resources/html/CustomCharacterScene.html');
|
this.load.html(customizeSceneKey, 'resources/html/CustomCharacterScene.html');
|
||||||
|
|
||||||
this.layers = loadAllLayers(this.load);
|
this.layers = loadAllLayers(this.load);
|
||||||
this.loadCustomSceneSelectCharacters().then((bodyResourceDescriptions) => {
|
this.loadCustomSceneSelectCharacters().then((bodyResourceDescriptions) => {
|
||||||
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
|
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
|
||||||
if(!bodyResourceDescription.level){
|
if(bodyResourceDescription.level == undefined || bodyResourceDescription.level < 0 || bodyResourceDescription.level > 5 ){
|
||||||
throw 'Texture level is null';
|
throw 'Texture level is null';
|
||||||
}
|
}
|
||||||
this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription);
|
this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//this function must stay at the end of preload function
|
||||||
|
addLoader(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
create() {
|
create() {
|
||||||
const middleX = this.getMiddleX();
|
this.customizeSceneElement = this.add.dom(-1000, 0).createFromCache(customizeSceneKey);
|
||||||
this.customizeSceneElement = this.add.dom(middleX, 0).createFromCache(customizeSceneKey);
|
this.centerXDomElement(this.customizeSceneElement, 150);
|
||||||
MenuScene.revealMenusAfterInit(this.customizeSceneElement, customizeSceneKey);
|
MenuScene.revealMenusAfterInit(this.customizeSceneElement, customizeSceneKey);
|
||||||
|
|
||||||
this.customizeSceneElement.addListener('click');
|
this.customizeSceneElement.addListener('click');
|
||||||
@ -111,6 +112,8 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
this.moveLayers();
|
this.moveLayers();
|
||||||
this.updateSelectedLayer();
|
this.updateSelectedLayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.onResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
private moveCursorHorizontally(index: number): void {
|
private moveCursorHorizontally(index: number): void {
|
||||||
@ -139,7 +142,7 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
|
|
||||||
if(index === -1 && this.activeRow === 1){
|
if(index === -1 && this.activeRow === 1){
|
||||||
const button = this.customizeSceneElement.getChildByID('customizeSceneFormBack') as HTMLButtonElement;
|
const button = this.customizeSceneElement.getChildByID('customizeSceneFormBack') as HTMLButtonElement;
|
||||||
button.innerText = `Back`;
|
button.innerText = `Return`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(index === 1 && this.activeRow === 0){
|
if(index === 1 && this.activeRow === 0){
|
||||||
@ -258,13 +261,7 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update(time: number, delta: number): void {
|
update(time: number, delta: number): void {
|
||||||
const middleX = this.getMiddleX();
|
|
||||||
this.tweens.add({
|
|
||||||
targets: this.customizeSceneElement,
|
|
||||||
x: middleX,
|
|
||||||
duration: 1000,
|
|
||||||
ease: 'Power3'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onResize(): void {
|
public onResize(): void {
|
||||||
@ -273,24 +270,7 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
this.Rectangle.x = this.cameras.main.worldView.x + this.cameras.main.width / 2;
|
this.Rectangle.x = this.cameras.main.worldView.x + this.cameras.main.width / 2;
|
||||||
this.Rectangle.y = this.cameras.main.worldView.y + this.cameras.main.height / 3;
|
this.Rectangle.y = this.cameras.main.worldView.y + this.cameras.main.height / 3;
|
||||||
|
|
||||||
const middleX = this.getMiddleX();
|
this.centerXDomElement(this.customizeSceneElement, 150);
|
||||||
this.tweens.add({
|
|
||||||
targets: this.customizeSceneElement,
|
|
||||||
x: middleX,
|
|
||||||
duration: 1000,
|
|
||||||
ease: 'Power3'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected getMiddleX() : number{
|
|
||||||
return (this.game.renderer.width / 2) -
|
|
||||||
(
|
|
||||||
this.customizeSceneElement
|
|
||||||
&& this.customizeSceneElement.node
|
|
||||||
&& this.customizeSceneElement.node.getBoundingClientRect().width > 0
|
|
||||||
? (this.customizeSceneElement.node.getBoundingClientRect().width / 4)
|
|
||||||
: 150
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private nextSceneToCamera(){
|
private nextSceneToCamera(){
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import {gameManager} from "../Game/GameManager";
|
import {gameManager} from "../Game/GameManager";
|
||||||
import {TextField} from "../Components/TextField";
|
import {TextField} from "../Components/TextField";
|
||||||
import Image = Phaser.GameObjects.Image;
|
import Image = Phaser.GameObjects.Image;
|
||||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
|
||||||
import {mediaManager} from "../../WebRtc/MediaManager";
|
import {mediaManager} from "../../WebRtc/MediaManager";
|
||||||
import {RESOLUTION} from "../../Enum/EnvironmentVariable";
|
|
||||||
import {SoundMeter} from "../Components/SoundMeter";
|
import {SoundMeter} from "../Components/SoundMeter";
|
||||||
import {SoundMeterSprite} from "../Components/SoundMeterSprite";
|
import {SoundMeterSprite} from "../Components/SoundMeterSprite";
|
||||||
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
||||||
@ -11,6 +9,7 @@ import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
|||||||
import {PinchManager} from "../UserInput/PinchManager";
|
import {PinchManager} from "../UserInput/PinchManager";
|
||||||
import Zone = Phaser.GameObjects.Zone;
|
import Zone = Phaser.GameObjects.Zone;
|
||||||
import { MenuScene } from "../Menu/MenuScene";
|
import { MenuScene } from "../Menu/MenuScene";
|
||||||
|
import {ResizableScene} from "./ResizableScene";
|
||||||
|
|
||||||
export const EnableCameraSceneName = "EnableCameraScene";
|
export const EnableCameraSceneName = "EnableCameraScene";
|
||||||
enum LoginTextures {
|
enum LoginTextures {
|
||||||
@ -23,7 +22,7 @@ enum LoginTextures {
|
|||||||
|
|
||||||
const enableCameraSceneKey = 'enableCameraScene';
|
const enableCameraSceneKey = 'enableCameraScene';
|
||||||
|
|
||||||
export class EnableCameraScene extends Phaser.Scene {
|
export class EnableCameraScene extends ResizableScene {
|
||||||
private textField!: TextField;
|
private textField!: TextField;
|
||||||
private cameraNameField!: TextField;
|
private cameraNameField!: TextField;
|
||||||
private arrowLeft!: Image;
|
private arrowLeft!: Image;
|
||||||
@ -37,11 +36,11 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||||||
private soundMeter: SoundMeter;
|
private soundMeter: SoundMeter;
|
||||||
private soundMeterSprite!: SoundMeterSprite;
|
private soundMeterSprite!: SoundMeterSprite;
|
||||||
private microphoneNameField!: TextField;
|
private microphoneNameField!: TextField;
|
||||||
private repositionCallback!: (this: Window, ev: UIEvent) => void;
|
|
||||||
|
|
||||||
private enableCameraSceneElement!: Phaser.GameObjects.DOMElement;
|
private enableCameraSceneElement!: Phaser.GameObjects.DOMElement;
|
||||||
|
|
||||||
private mobileTapZone!: Zone;
|
private mobileTapZone!: Zone;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
key: EnableCameraSceneName
|
key: EnableCameraSceneName
|
||||||
@ -62,8 +61,9 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||||||
|
|
||||||
create() {
|
create() {
|
||||||
|
|
||||||
const middleX = this.getMiddleX();
|
this.enableCameraSceneElement = this.add.dom(-1000, 0).createFromCache(enableCameraSceneKey);
|
||||||
this.enableCameraSceneElement = this.add.dom(middleX, 0).createFromCache(enableCameraSceneKey);
|
this.centerXDomElement(this.enableCameraSceneElement, 300);
|
||||||
|
|
||||||
MenuScene.revealMenusAfterInit(this.enableCameraSceneElement, enableCameraSceneKey);
|
MenuScene.revealMenusAfterInit(this.enableCameraSceneElement, enableCameraSceneKey);
|
||||||
|
|
||||||
const continuingButton = this.enableCameraSceneElement.getChildByID('enableCameraSceneFormSubmit') as HTMLButtonElement;
|
const continuingButton = this.enableCameraSceneElement.getChildByID('enableCameraSceneFormSubmit') as HTMLButtonElement;
|
||||||
@ -75,12 +75,14 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||||||
if (touchScreenManager.supportTouchScreen) {
|
if (touchScreenManager.supportTouchScreen) {
|
||||||
new PinchManager(this);
|
new PinchManager(this);
|
||||||
}
|
}
|
||||||
|
//this.scale.setZoom(ZOOM_LEVEL);
|
||||||
|
//Phaser.Display.Align.In.BottomCenter(this.pressReturnField, zone);
|
||||||
|
|
||||||
/* FIX ME */
|
/* 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.
|
// 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", () => {
|
.setInteractive().on("pointerdown", () => {
|
||||||
this.login();
|
this.login();
|
||||||
});
|
});
|
||||||
@ -130,8 +132,7 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||||||
this.soundMeterSprite.setVisible(false);
|
this.soundMeterSprite.setVisible(false);
|
||||||
this.add.existing(this.soundMeterSprite);
|
this.add.existing(this.soundMeterSprite);
|
||||||
|
|
||||||
this.repositionCallback = this.reposition.bind(this);
|
this.onResize();
|
||||||
window.addEventListener('resize', this.repositionCallback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private previousCam(): void {
|
private previousCam(): void {
|
||||||
@ -209,10 +210,9 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||||||
this.arrowUp.setVisible(this.microphoneSelected > 0);
|
this.arrowUp.setVisible(this.microphoneSelected > 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
this.reposition();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private reposition(): void {
|
public onResize(): void {
|
||||||
let div = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideoSetup');
|
let div = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideoSetup');
|
||||||
let bounds = div.getBoundingClientRect();
|
let bounds = div.getBoundingClientRect();
|
||||||
if (!div.srcObject) {
|
if (!div.srcObject) {
|
||||||
@ -225,44 +225,41 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||||||
this.cameraNameField.x = this.game.renderer.width / 2;
|
this.cameraNameField.x = this.game.renderer.width / 2;
|
||||||
this.microphoneNameField.x = this.game.renderer.width / 2;
|
this.microphoneNameField.x = this.game.renderer.width / 2;
|
||||||
|
|
||||||
this.cameraNameField.y = bounds.top / RESOLUTION - 8;
|
this.cameraNameField.y = bounds.top / this.scale.zoom - 8;
|
||||||
|
|
||||||
this.soundMeterSprite.x = this.game.renderer.width / 2 - this.soundMeterSprite.getWidth() / 2;
|
this.soundMeterSprite.x = this.game.renderer.width / 2 - this.soundMeterSprite.getWidth() / 2;
|
||||||
this.soundMeterSprite.y = bounds.bottom / RESOLUTION + 16;
|
this.soundMeterSprite.y = bounds.bottom / this.scale.zoom + 16;
|
||||||
|
|
||||||
this.microphoneNameField.y = this.soundMeterSprite.y + 22;
|
this.microphoneNameField.y = this.soundMeterSprite.y + 22;
|
||||||
|
|
||||||
this.arrowRight.x = bounds.right / RESOLUTION + 16;
|
this.arrowRight.x = bounds.right / this.scale.zoom + 16;
|
||||||
this.arrowRight.y = (bounds.top + bounds.height / 2) / RESOLUTION;
|
this.arrowRight.y = (bounds.top + bounds.height / 2) / this.scale.zoom;
|
||||||
|
|
||||||
this.arrowLeft.x = bounds.left / RESOLUTION - 16;
|
this.arrowLeft.x = bounds.left / this.scale.zoom - 16;
|
||||||
this.arrowLeft.y = (bounds.top + bounds.height / 2) / RESOLUTION;
|
this.arrowLeft.y = (bounds.top + bounds.height / 2) / this.scale.zoom;
|
||||||
|
|
||||||
this.arrowDown.x = this.microphoneNameField.x + this.microphoneNameField.width / 2 + 16;
|
this.arrowDown.x = this.microphoneNameField.x + this.microphoneNameField.width / 2 + 16;
|
||||||
this.arrowDown.y = this.microphoneNameField.y;
|
this.arrowDown.y = this.microphoneNameField.y;
|
||||||
|
|
||||||
this.arrowUp.x = this.microphoneNameField.x - this.microphoneNameField.width / 2 - 16;
|
this.arrowUp.x = this.microphoneNameField.x - this.microphoneNameField.width / 2 - 16;
|
||||||
this.arrowUp.y = this.microphoneNameField.y;
|
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 {
|
update(time: number, delta: number): void {
|
||||||
this.soundMeterSprite.setVolume(this.soundMeter.getVolume());
|
this.soundMeterSprite.setVolume(this.soundMeter.getVolume());
|
||||||
|
mediaManager.updateScene();
|
||||||
|
|
||||||
mediaManager.setLastUpdateScene();
|
this.centerXDomElement(this.enableCameraSceneElement, 300);
|
||||||
|
|
||||||
const middleX = this.getMiddleX();
|
|
||||||
this.tweens.add({
|
|
||||||
targets: this.enableCameraSceneElement,
|
|
||||||
x: middleX,
|
|
||||||
duration: 1000,
|
|
||||||
ease: 'Power3'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private login(): void {
|
private login(): void {
|
||||||
HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').style.display = 'none';
|
HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').style.display = 'none';
|
||||||
this.soundMeter.stop();
|
this.soundMeter.stop();
|
||||||
window.removeEventListener('resize', this.repositionCallback);
|
|
||||||
|
|
||||||
mediaManager.stopCamera();
|
mediaManager.stopCamera();
|
||||||
mediaManager.stopMicrophone();
|
mediaManager.stopMicrophone();
|
||||||
@ -282,15 +279,4 @@ export class EnableCameraScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
this.updateWebCamName();
|
this.updateWebCamName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getMiddleX() : number{
|
|
||||||
return (this.game.renderer.width / 2) -
|
|
||||||
(
|
|
||||||
this.enableCameraSceneElement
|
|
||||||
&& this.enableCameraSceneElement.node
|
|
||||||
&& this.enableCameraSceneElement.node.getBoundingClientRect().width > 0
|
|
||||||
? (this.enableCameraSceneElement.node.getBoundingClientRect().width / 4)
|
|
||||||
: (300 / 2)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import {gameManager} from "../Game/GameManager";
|
|||||||
import {Scene} from "phaser";
|
import {Scene} from "phaser";
|
||||||
import {ErrorScene} from "../Reconnecting/ErrorScene";
|
import {ErrorScene} from "../Reconnecting/ErrorScene";
|
||||||
import {WAError} from "../Reconnecting/WAError";
|
import {WAError} from "../Reconnecting/WAError";
|
||||||
|
import {waScaleManager} from "../Services/WaScaleManager";
|
||||||
|
|
||||||
export const EntrySceneName = "EntryScene";
|
export const EntrySceneName = "EntryScene";
|
||||||
|
|
||||||
@ -17,11 +18,18 @@ export class EntryScene extends Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
create() {
|
create() {
|
||||||
|
|
||||||
gameManager.init(this.scene).then((nextSceneName) => {
|
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);
|
this.scene.start(nextSceneName);
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
if (err.response && err.response.status == 404) {
|
if (err.response && err.response.status == 404) {
|
||||||
ErrorScene.showError(new WAError('Page Not Found', 'Could not find map', window.location.pathname), this.scene);
|
ErrorScene.showError(new WAError(
|
||||||
|
'Access link incorrect',
|
||||||
|
'Could not find map. Please check your access link.',
|
||||||
|
'If you want more information, you may contact administrator or contact us at: workadventure@thecodingmachine.com'), this.scene);
|
||||||
} else {
|
} else {
|
||||||
ErrorScene.showError(err, this.scene);
|
ErrorScene.showError(err, this.scene);
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,8 @@ export class LoginScene extends ResizableScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
create() {
|
create() {
|
||||||
const middleX = this.getMiddleX();
|
this.loginSceneElement = this.add.dom(-1000, 0).createFromCache(loginSceneKey);
|
||||||
this.loginSceneElement = this.add.dom((middleX/2), 0).createFromCache(loginSceneKey);
|
this.centerXDomElement(this.loginSceneElement, 200);
|
||||||
MenuScene.revealMenusAfterInit(this.loginSceneElement, loginSceneKey);
|
MenuScene.revealMenusAfterInit(this.loginSceneElement, loginSceneKey);
|
||||||
|
|
||||||
const pErrorElement = this.loginSceneElement.getChildByID('errorLoginScene') as HTMLInputElement;
|
const pErrorElement = this.loginSceneElement.getChildByID('errorLoginScene') as HTMLInputElement;
|
||||||
@ -77,27 +77,10 @@ export class LoginScene extends ResizableScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update(time: number, delta: number): void {
|
update(time: number, delta: number): void {
|
||||||
const middleX = this.getMiddleX();
|
|
||||||
this.tweens.add({
|
|
||||||
targets: this.loginSceneElement,
|
|
||||||
x: (middleX/2),
|
|
||||||
duration: 1000,
|
|
||||||
ease: 'Power3'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onResize(ev: UIEvent): void {
|
public onResize(ev: UIEvent): void {
|
||||||
const middleX = this.getMiddleX();
|
this.centerXDomElement(this.loginSceneElement, 200);
|
||||||
this.tweens.add({
|
|
||||||
targets: this.loginSceneElement,
|
|
||||||
x: (middleX/2),
|
|
||||||
duration: 1000,
|
|
||||||
ease: 'Power3'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private getMiddleX() : number{
|
|
||||||
const middleX = ((window.innerWidth) - ((this.loginSceneElement && this.loginSceneElement.width > 0 ? this.loginSceneElement.width : 200 /*FIXME to use a const will be injected in HTMLElement*/)*2)) / 2;
|
|
||||||
return (middleX > 0 ? middleX : 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,23 @@
|
|||||||
import {Scene} from "phaser";
|
import {Scene} from "phaser";
|
||||||
|
import DOMElement = Phaser.GameObjects.DOMElement;
|
||||||
|
|
||||||
export abstract class ResizableScene extends Scene {
|
export abstract class ResizableScene extends Scene {
|
||||||
public abstract onResize(ev: UIEvent): void;
|
public abstract onResize(ev: UIEvent): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Centers the DOM element on the X axis.
|
||||||
|
*
|
||||||
|
* @param object
|
||||||
|
* @param defaultWidth The width of the DOM element. We try to compute it but it may not be available if called from "create".
|
||||||
|
*/
|
||||||
|
public centerXDomElement(object: DOMElement, defaultWidth: number): void {
|
||||||
|
object.x = (this.scale.width / 2) -
|
||||||
|
(
|
||||||
|
object
|
||||||
|
&& object.node
|
||||||
|
&& object.node.getBoundingClientRect().width > 0
|
||||||
|
? (object.node.getBoundingClientRect().width / 2 / this.scale.zoom)
|
||||||
|
: (300 / this.scale.zoom)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import {EnableCameraSceneName} from "./EnableCameraScene";
|
|||||||
import {CustomizeSceneName} from "./CustomizeScene";
|
import {CustomizeSceneName} from "./CustomizeScene";
|
||||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||||
import {loadAllDefaultModels} from "../Entity/PlayerTexturesLoadingManager";
|
import {loadAllDefaultModels} from "../Entity/PlayerTexturesLoadingManager";
|
||||||
import {addLoader} from "../Components/Loader";
|
|
||||||
import {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures";
|
import {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures";
|
||||||
import {AbstractCharacterScene} from "./AbstractCharacterScene";
|
import {AbstractCharacterScene} from "./AbstractCharacterScene";
|
||||||
import {areCharacterLayersValid} from "../../Connexion/LocalUser";
|
import {areCharacterLayersValid} from "../../Connexion/LocalUser";
|
||||||
|
@ -37,8 +37,6 @@ export class SelectCharacterScene extends AbstractCharacterScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
preload() {
|
preload() {
|
||||||
addLoader(this);
|
|
||||||
|
|
||||||
this.load.html(selectCharacterKey, 'resources/html/selectCharacterScene.html');
|
this.load.html(selectCharacterKey, 'resources/html/selectCharacterScene.html');
|
||||||
|
|
||||||
this.loadSelectSceneCharacters().then((bodyResourceDescriptions) => {
|
this.loadSelectSceneCharacters().then((bodyResourceDescriptions) => {
|
||||||
@ -47,13 +45,15 @@ export class SelectCharacterScene extends AbstractCharacterScene {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
this.playerModels = loadAllDefaultModels(this.load);
|
this.playerModels = loadAllDefaultModels(this.load);
|
||||||
|
|
||||||
|
//this function must stay at the end of preload function
|
||||||
addLoader(this);
|
addLoader(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
create() {
|
create() {
|
||||||
|
|
||||||
const middleX = this.getMiddleX();
|
this.selectCharacterSceneElement = this.add.dom(-1000, 0).createFromCache(selectCharacterKey);
|
||||||
this.selectCharacterSceneElement = this.add.dom(middleX, 0).createFromCache(selectCharacterKey);
|
this.centerXDomElement(this.selectCharacterSceneElement, 150);
|
||||||
MenuScene.revealMenusAfterInit(this.selectCharacterSceneElement, selectCharacterKey);
|
MenuScene.revealMenusAfterInit(this.selectCharacterSceneElement, selectCharacterKey);
|
||||||
|
|
||||||
this.selectCharacterSceneElement.addListener('click');
|
this.selectCharacterSceneElement.addListener('click');
|
||||||
@ -240,36 +240,12 @@ export class SelectCharacterScene extends AbstractCharacterScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update(time: number, delta: number): void {
|
update(time: number, delta: number): void {
|
||||||
const middleX = this.getMiddleX();
|
|
||||||
this.tweens.add({
|
|
||||||
targets: this.selectCharacterSceneElement,
|
|
||||||
x: middleX,
|
|
||||||
duration: 1000,
|
|
||||||
ease: 'Power3'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onResize(ev: UIEvent): void {
|
public onResize(ev: UIEvent): void {
|
||||||
//move position of user
|
//move position of user
|
||||||
this.moveUser();
|
this.moveUser();
|
||||||
|
|
||||||
const middleX = this.getMiddleX();
|
this.centerXDomElement(this.selectCharacterSceneElement, 150);
|
||||||
this.tweens.add({
|
|
||||||
targets: this.selectCharacterSceneElement,
|
|
||||||
x: middleX,
|
|
||||||
duration: 1000,
|
|
||||||
ease: 'Power3'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected getMiddleX() : number{
|
|
||||||
return (this.game.renderer.width / 2) -
|
|
||||||
(
|
|
||||||
this.selectCharacterSceneElement
|
|
||||||
&& this.selectCharacterSceneElement.node
|
|
||||||
&& this.selectCharacterSceneElement.node.getBoundingClientRect().width > 0
|
|
||||||
? (this.selectCharacterSceneElement.node.getBoundingClientRect().width / 4)
|
|
||||||
: 150
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,21 +30,20 @@ export class SelectCompanionScene extends ResizableScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
preload() {
|
preload() {
|
||||||
addLoader(this);
|
|
||||||
|
|
||||||
this.load.html(selectCompanionSceneKey, 'resources/html/SelectCompanionScene.html');
|
this.load.html(selectCompanionSceneKey, 'resources/html/SelectCompanionScene.html');
|
||||||
|
|
||||||
getAllCompanionResources(this.load).forEach(model => {
|
getAllCompanionResources(this.load).forEach(model => {
|
||||||
this.companionModels.push(model);
|
this.companionModels.push(model);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//this function must stay at the end of preload function
|
||||||
addLoader(this);
|
addLoader(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
create() {
|
create() {
|
||||||
|
|
||||||
const middleX = this.getMiddleX();
|
this.selectCompanionSceneElement = this.add.dom(-1000, 0).createFromCache(selectCompanionSceneKey);
|
||||||
this.selectCompanionSceneElement = this.add.dom(middleX, 0).createFromCache(selectCompanionSceneKey);
|
this.centerXDomElement(this.selectCompanionSceneElement, 150);
|
||||||
MenuScene.revealMenusAfterInit(this.selectCompanionSceneElement, selectCompanionSceneKey);
|
MenuScene.revealMenusAfterInit(this.selectCompanionSceneElement, selectCompanionSceneKey);
|
||||||
|
|
||||||
this.selectCompanionSceneElement.addListener('click');
|
this.selectCompanionSceneElement.addListener('click');
|
||||||
@ -87,13 +86,7 @@ export class SelectCompanionScene extends ResizableScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update(time: number, delta: number): void {
|
update(time: number, delta: number): void {
|
||||||
const middleX = this.getMiddleX();
|
|
||||||
this.tweens.add({
|
|
||||||
targets: this.selectCompanionSceneElement,
|
|
||||||
x: middleX,
|
|
||||||
duration: 1000,
|
|
||||||
ease: 'Power3'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private nextScene(): void {
|
private nextScene(): void {
|
||||||
@ -125,7 +118,7 @@ export class SelectCompanionScene extends ResizableScene {
|
|||||||
|
|
||||||
companion.setInteractive().on("pointerdown", () => {
|
companion.setInteractive().on("pointerdown", () => {
|
||||||
this.currentCompanion = i;
|
this.currentCompanion = i;
|
||||||
this.updateSelectedCompanion();
|
this.moveCompanion();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.companions.push(companion);
|
this.companions.push(companion);
|
||||||
@ -136,13 +129,7 @@ export class SelectCompanionScene extends ResizableScene {
|
|||||||
public onResize(ev: UIEvent): void {
|
public onResize(ev: UIEvent): void {
|
||||||
this.moveCompanion();
|
this.moveCompanion();
|
||||||
|
|
||||||
const middleX = this.getMiddleX();
|
this.centerXDomElement(this.selectCompanionSceneElement, 150);
|
||||||
this.tweens.add({
|
|
||||||
targets: this.selectCompanionSceneElement,
|
|
||||||
x: middleX,
|
|
||||||
duration: 1000,
|
|
||||||
ease: 'Power3'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateSelectedCompanion(): void {
|
private updateSelectedCompanion(): void {
|
||||||
@ -238,15 +225,4 @@ export class SelectCompanionScene extends ResizableScene {
|
|||||||
companion.setX(companionX);
|
companion.setX(companionX);
|
||||||
companion.setY(companionY);
|
companion.setY(companionY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getMiddleX() : number{
|
|
||||||
return (this.game.renderer.width / 2) -
|
|
||||||
(
|
|
||||||
this.selectCompanionSceneElement
|
|
||||||
&& this.selectCompanionSceneElement.node
|
|
||||||
&& this.selectCompanionSceneElement.node.getBoundingClientRect().width > 0
|
|
||||||
? (this.selectCompanionSceneElement.node.getBoundingClientRect().width / 4)
|
|
||||||
: 150
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import {mediaManager} from "../../WebRtc/MediaManager";
|
import {mediaManager} from "../../WebRtc/MediaManager";
|
||||||
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
||||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||||
|
import {DirtyScene} from "../Game/DirtyScene";
|
||||||
|
|
||||||
export const HelpCameraSettingsSceneName = 'HelpCameraSettingsScene';
|
export const HelpCameraSettingsSceneName = 'HelpCameraSettingsScene';
|
||||||
const helpCameraSettings = 'helpCameraSettings';
|
const helpCameraSettings = 'helpCameraSettings';
|
||||||
/**
|
/**
|
||||||
* The scene that show how to permit Camera and Microphone access if there are not already allowed
|
* The scene that show how to permit Camera and Microphone access if there are not already allowed
|
||||||
*/
|
*/
|
||||||
export class HelpCameraSettingsScene extends Phaser.Scene {
|
export class HelpCameraSettingsScene extends DirtyScene {
|
||||||
private helpCameraSettingsElement!: Phaser.GameObjects.DOMElement;
|
private helpCameraSettingsElement!: Phaser.GameObjects.DOMElement;
|
||||||
private helpCameraSettingsOpened: boolean = false;
|
private helpCameraSettingsOpened: boolean = false;
|
||||||
|
|
||||||
@ -20,7 +21,6 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
create(){
|
create(){
|
||||||
localUserStore.setHelpCameraSettingsShown();
|
|
||||||
this.createHelpCameraSettings();
|
this.createHelpCameraSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,6 +30,9 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
|||||||
this.revealMenusAfterInit(this.helpCameraSettingsElement, helpCameraSettings);
|
this.revealMenusAfterInit(this.helpCameraSettingsElement, helpCameraSettings);
|
||||||
this.helpCameraSettingsElement.addListener('click');
|
this.helpCameraSettingsElement.addListener('click');
|
||||||
this.helpCameraSettingsElement.on('click', (event:MouseEvent) => {
|
this.helpCameraSettingsElement.on('click', (event:MouseEvent) => {
|
||||||
|
if((event?.target as HTMLInputElement).id === 'mailto') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if((event?.target as HTMLInputElement).id === 'helpCameraSettingsFormRefresh') {
|
if((event?.target as HTMLInputElement).id === 'helpCameraSettingsFormRefresh') {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
@ -38,19 +41,28 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if(!mediaManager.constraintsMedia.audio || !mediaManager.constraintsMedia.video){
|
if(!localUserStore.getHelpCameraSettingsShown() && (!mediaManager.constraintsMedia.audio || !mediaManager.constraintsMedia.video)){
|
||||||
this.openHelpCameraSettingsOpened();
|
this.openHelpCameraSettingsOpened();
|
||||||
|
localUserStore.setHelpCameraSettingsShown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mediaManager.setHelpCameraSettingsCallBack(() => {
|
||||||
|
this.openHelpCameraSettingsOpened();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private openHelpCameraSettingsOpened(): void{
|
private openHelpCameraSettingsOpened(): void{
|
||||||
HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').style.display = 'none';
|
HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').style.display = 'none';
|
||||||
this.helpCameraSettingsOpened = true;
|
this.helpCameraSettingsOpened = true;
|
||||||
|
try{
|
||||||
if(window.navigator.userAgent.includes('Firefox')){
|
if(window.navigator.userAgent.includes('Firefox')){
|
||||||
HtmlUtils.getElementByIdOrFail<HTMLParagraphElement>('browserHelpSetting').innerHTML ='<img src="/resources/objects/help-setting-camera-permission-firefox.png"/>';
|
HtmlUtils.getElementByIdOrFail<HTMLParagraphElement>('browserHelpSetting').innerHTML ='<img src="/resources/objects/help-setting-camera-permission-firefox.png"/>';
|
||||||
}else if(window.navigator.userAgent.includes('Chrome')){
|
}else if(window.navigator.userAgent.includes('Chrome')){
|
||||||
HtmlUtils.getElementByIdOrFail<HTMLParagraphElement>('browserHelpSetting').innerHTML ='<img src="/resources/objects/help-setting-camera-permission-chrome.png"/>';
|
HtmlUtils.getElementByIdOrFail<HTMLParagraphElement>('browserHelpSetting').innerHTML ='<img src="/resources/objects/help-setting-camera-permission-chrome.png"/>';
|
||||||
}
|
}
|
||||||
|
}catch(err) {
|
||||||
|
console.error('openHelpCameraSettingsOpened => getElementByIdOrFail => error', err);
|
||||||
|
}
|
||||||
const middleY = this.getMiddleY();
|
const middleY = this.getMiddleY();
|
||||||
const middleX = this.getMiddleX();
|
const middleX = this.getMiddleX();
|
||||||
this.tweens.add({
|
this.tweens.add({
|
||||||
@ -61,22 +73,26 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
|||||||
ease: 'Power3',
|
ease: 'Power3',
|
||||||
overflow: 'scroll'
|
overflow: 'scroll'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private closeHelpCameraSettingsOpened(): void{
|
private closeHelpCameraSettingsOpened(): void{
|
||||||
const middleX = this.getMiddleX();
|
const middleX = this.getMiddleX();
|
||||||
const helpCameraSettingsInfo = this.helpCameraSettingsElement.getChildByID('helpCameraSettings') as HTMLParagraphElement;
|
/*const helpCameraSettingsInfo = this.helpCameraSettingsElement.getChildByID('helpCameraSettings') as HTMLParagraphElement;
|
||||||
helpCameraSettingsInfo.innerText = '';
|
helpCameraSettingsInfo.innerText = '';
|
||||||
helpCameraSettingsInfo.style.display = 'none';
|
helpCameraSettingsInfo.style.display = 'none';*/
|
||||||
this.helpCameraSettingsOpened = false;
|
this.helpCameraSettingsOpened = false;
|
||||||
this.tweens.add({
|
this.tweens.add({
|
||||||
targets: this.helpCameraSettingsElement,
|
targets: this.helpCameraSettingsElement,
|
||||||
y: -400,
|
y: -1000,
|
||||||
x: middleX,
|
x: middleX,
|
||||||
duration: 1000,
|
duration: 1000,
|
||||||
ease: 'Power3',
|
ease: 'Power3',
|
||||||
overflow: 'scroll'
|
overflow: 'scroll'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private revealMenusAfterInit(menuElement: Phaser.GameObjects.DOMElement, rootDomId: string) {
|
private revealMenusAfterInit(menuElement: Phaser.GameObjects.DOMElement, rootDomId: string) {
|
||||||
@ -88,18 +104,11 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update(time: number, delta: number): void {
|
update(time: number, delta: number): void {
|
||||||
const middleX = this.getMiddleX();
|
this.dirty = false;
|
||||||
const middleY = this.getMiddleY();
|
|
||||||
this.tweens.add({
|
|
||||||
targets: this.helpCameraSettingsElement,
|
|
||||||
x: middleX,
|
|
||||||
y: middleY,
|
|
||||||
duration: 1000,
|
|
||||||
ease: 'Power3'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onResize(ev: UIEvent): void {
|
public onResize(ev: UIEvent): void {
|
||||||
|
super.onResize(ev);
|
||||||
const middleX = this.getMiddleX();
|
const middleX = this.getMiddleX();
|
||||||
const middleY = this.getMiddleY();
|
const middleY = this.getMiddleY();
|
||||||
this.tweens.add({
|
this.tweens.add({
|
||||||
@ -112,24 +121,27 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getMiddleX() : number{
|
private getMiddleX() : number{
|
||||||
return (this.game.renderer.width / 2) -
|
return (this.scale.width / 2) -
|
||||||
(
|
(
|
||||||
this.helpCameraSettingsElement
|
this.helpCameraSettingsElement
|
||||||
&& this.helpCameraSettingsElement.node
|
&& this.helpCameraSettingsElement.node
|
||||||
&& this.helpCameraSettingsElement.node.getBoundingClientRect().width > 0
|
&& this.helpCameraSettingsElement.node.getBoundingClientRect().width > 0
|
||||||
? (this.helpCameraSettingsElement.node.getBoundingClientRect().width / 4)
|
? (this.helpCameraSettingsElement.node.getBoundingClientRect().width / (2 * this.scale.zoom))
|
||||||
: (400 / 2)
|
: (400 / 2)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getMiddleY() : number{
|
private getMiddleY() : number{
|
||||||
const middleY = ((window.innerHeight) - (
|
const middleY = ((this.scale.height) - (
|
||||||
(this.helpCameraSettingsElement
|
(this.helpCameraSettingsElement
|
||||||
&& this.helpCameraSettingsElement.node
|
&& this.helpCameraSettingsElement.node
|
||||||
&& this.helpCameraSettingsElement.node.getBoundingClientRect().height > 0
|
&& this.helpCameraSettingsElement.node.getBoundingClientRect().height > 0
|
||||||
? this.helpCameraSettingsElement.node.getBoundingClientRect().height : 400 /*FIXME to use a const will be injected in HTMLElement*/)*2)) / 2;
|
? this.helpCameraSettingsElement.node.getBoundingClientRect().height : 400 /*FIXME to use a const will be injected in HTMLElement*/)/this.scale.zoom)) / 2;
|
||||||
return (middleY > 0 ? middleY / 2 : 0);
|
return (middleY > 0 ? middleY : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public isDirty(): boolean {
|
||||||
|
return this.dirty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,11 +207,11 @@ export class MenuScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let middleY = (window.innerHeight / 3) - (257);
|
let middleY = this.scale.height / 2 - 392/2;
|
||||||
if(middleY < 0){
|
if(middleY < 0){
|
||||||
middleY = 0;
|
middleY = 0;
|
||||||
}
|
}
|
||||||
let middleX = (window.innerWidth / 3) - 298;
|
let middleX = this.scale.width / 2 - 457/2;
|
||||||
if(middleX < 0){
|
if(middleX < 0){
|
||||||
middleX = 0;
|
middleX = 0;
|
||||||
}
|
}
|
||||||
@ -251,11 +251,11 @@ export class MenuScene extends Phaser.Scene {
|
|||||||
|
|
||||||
this.gameShareOpened = true;
|
this.gameShareOpened = true;
|
||||||
|
|
||||||
let middleY = (window.innerHeight / 3) - (257);
|
let middleY = this.scale.height / 2 - 85;
|
||||||
if(middleY < 0){
|
if(middleY < 0){
|
||||||
middleY = 0;
|
middleY = 0;
|
||||||
}
|
}
|
||||||
let middleX = (window.innerWidth / 3) - 298;
|
let middleX = this.scale.width / 2 - 200;
|
||||||
if(middleX < 0){
|
if(middleX < 0){
|
||||||
middleX = 0;
|
middleX = 0;
|
||||||
}
|
}
|
||||||
@ -382,4 +382,8 @@ export class MenuScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public isDirty(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ export const hasMovedEventName = "hasMoved";
|
|||||||
export interface CurrentGamerInterface extends Character{
|
export interface CurrentGamerInterface extends Character{
|
||||||
moveUser(delta: number) : void;
|
moveUser(delta: number) : void;
|
||||||
say(text : string) : void;
|
say(text : string) : void;
|
||||||
|
isMoving(): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Player extends Character implements CurrentGamerInterface {
|
export class Player extends Character implements CurrentGamerInterface {
|
||||||
@ -83,4 +84,8 @@ export class Player extends Character implements CurrentGamerInterface {
|
|||||||
}
|
}
|
||||||
this.wasMoving = moving;
|
this.wasMoving = moving;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public isMoving(): boolean {
|
||||||
|
return this.wasMoving;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ export class ErrorScene extends Phaser.Scene {
|
|||||||
|
|
||||||
this.subTitleField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height / 2 + 24, this.subTitle);
|
this.subTitleField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height / 2 + 24, this.subTitle);
|
||||||
|
|
||||||
this.messageField = this.add.text(this.game.renderer.width / 2, this.game.renderer.height / 2 + 38, this.message, {
|
this.messageField = this.add.text(this.game.renderer.width / 2, this.game.renderer.height / 2 + 48, this.message, {
|
||||||
fontFamily: 'Georgia, "Goudy Bookletter 1911", Times, serif',
|
fontFamily: 'Georgia, "Goudy Bookletter 1911", Times, serif',
|
||||||
fontSize: '10px'
|
fontSize: '10px'
|
||||||
});
|
});
|
||||||
|
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
@ -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,4 +1,4 @@
|
|||||||
export class OutlinePipeline extends Phaser.Renderer.WebGL.Pipelines.TextureTintPipeline {
|
export class OutlinePipeline extends Phaser.Renderer.WebGL.Pipelines.MultiPipeline {
|
||||||
|
|
||||||
// the unique id of this pipeline
|
// the unique id of this pipeline
|
||||||
public static readonly KEY = 'Outline';
|
public static readonly KEY = 'Outline';
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import {Pinch} from "phaser3-rex-plugins/plugins/gestures.js";
|
import {Pinch} from "phaser3-rex-plugins/plugins/gestures.js";
|
||||||
|
import {waScaleManager} from "../Services/WaScaleManager";
|
||||||
|
import {GameScene} from "../Game/GameScene";
|
||||||
|
|
||||||
export class PinchManager {
|
export class PinchManager {
|
||||||
private scene: Phaser.Scene;
|
private scene: Phaser.Scene;
|
||||||
@ -7,16 +9,33 @@ export class PinchManager {
|
|||||||
constructor(scene: Phaser.Scene) {
|
constructor(scene: Phaser.Scene) {
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
this.pinch = new Pinch(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
|
this.pinch.on('pinch', (pinch:any) => { // eslint-disable-line
|
||||||
let newZoom = this.scene.cameras.main.zoom * pinch.scaleFactor;
|
if (pinch.scaleFactor > 1.2 || pinch.scaleFactor < 0.8) {
|
||||||
if (newZoom < 0.25) {
|
// Pinch too fast! Probably a bad measure.
|
||||||
newZoom = 0.25;
|
return;
|
||||||
} else if(newZoom > 2) {
|
}
|
||||||
newZoom = 2;
|
|
||||||
|
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,6 +54,7 @@ export class UserInputManager {
|
|||||||
this.Scene = Scene;
|
this.Scene = Scene;
|
||||||
this.isInputDisabled = false;
|
this.isInputDisabled = false;
|
||||||
this.initKeyBoardEvent();
|
this.initKeyBoardEvent();
|
||||||
|
this.initMouseWheel();
|
||||||
if (touchScreenManager.supportTouchScreen) {
|
if (touchScreenManager.supportTouchScreen) {
|
||||||
this.initVirtualJoystick();
|
this.initVirtualJoystick();
|
||||||
}
|
}
|
||||||
@ -170,4 +171,14 @@ export class UserInputManager {
|
|||||||
removeSpaceEventListner(callback : Function){
|
removeSpaceEventListner(callback : Function){
|
||||||
this.Scene.input.keyboard.removeListener('keyup-SPACE', callback);
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,7 +346,7 @@ class LayoutManager {
|
|||||||
userInputManager.addSpaceEventListner(callBack);
|
userInputManager.addSpaceEventListner(callBack);
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeActionButton(id: string, userInputManager: UserInputManager){
|
public removeActionButton(id: string, userInputManager?: UserInputManager){
|
||||||
//delete previous element
|
//delete previous element
|
||||||
const previousDiv = this.actionButtonInformation.get(id);
|
const previousDiv = this.actionButtonInformation.get(id);
|
||||||
if(previousDiv){
|
if(previousDiv){
|
||||||
@ -354,10 +354,45 @@ class LayoutManager {
|
|||||||
this.actionButtonInformation.delete(id);
|
this.actionButtonInformation.delete(id);
|
||||||
}
|
}
|
||||||
const previousEventCallback = this.actionButtonTrigger.get(id);
|
const previousEventCallback = this.actionButtonTrigger.get(id);
|
||||||
if(previousEventCallback){
|
if(previousEventCallback && userInputManager){
|
||||||
userInputManager.removeSpaceEventListner(previousEventCallback);
|
userInputManager.removeSpaceEventListner(previousEventCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public addInformation(id: string, text: string, callBack?: Function, userInputManager?: UserInputManager){
|
||||||
|
//delete previous element
|
||||||
|
for ( const [key, value] of this.actionButtonInformation ) {
|
||||||
|
this.removeActionButton(key, userInputManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
//create div and text html component
|
||||||
|
const p = document.createElement('p');
|
||||||
|
p.classList.add('action-body');
|
||||||
|
p.innerText = text;
|
||||||
|
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.classList.add('action');
|
||||||
|
div.classList.add(id);
|
||||||
|
div.id = id;
|
||||||
|
div.appendChild(p);
|
||||||
|
|
||||||
|
this.actionButtonInformation.set(id, div);
|
||||||
|
|
||||||
|
const mainContainer = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('main-container');
|
||||||
|
mainContainer.appendChild(div);
|
||||||
|
//add trigger action
|
||||||
|
if(callBack){
|
||||||
|
div.onpointerdown = () => {
|
||||||
|
callBack();
|
||||||
|
this.removeActionButton(id, userInputManager);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove it after 10 sec
|
||||||
|
setTimeout(() => {
|
||||||
|
this.removeActionButton(id, userInputManager);
|
||||||
|
}, 10000)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const layoutManager = new LayoutManager();
|
const layoutManager = new LayoutManager();
|
||||||
|
@ -4,6 +4,8 @@ import {discussionManager, SendMessageCallback} from "./DiscussionManager";
|
|||||||
import {UserInputManager} from "../Phaser/UserInput/UserInputManager";
|
import {UserInputManager} from "../Phaser/UserInput/UserInputManager";
|
||||||
import {localUserStore} from "../Connexion/LocalUserStore";
|
import {localUserStore} from "../Connexion/LocalUserStore";
|
||||||
import {UserSimplePeerInterface} from "./SimplePeer";
|
import {UserSimplePeerInterface} from "./SimplePeer";
|
||||||
|
import {SoundMeter} from "../Phaser/Components/SoundMeter";
|
||||||
|
|
||||||
declare const navigator:any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
declare const navigator:any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
|
||||||
let videoConstraint: boolean|MediaTrackConstraints = {
|
let videoConstraint: boolean|MediaTrackConstraints = {
|
||||||
@ -26,6 +28,7 @@ export type StartScreenSharingCallback = (media: MediaStream) => void;
|
|||||||
export type StopScreenSharingCallback = (media: MediaStream) => void;
|
export type StopScreenSharingCallback = (media: MediaStream) => void;
|
||||||
export type ReportCallback = (message: string) => void;
|
export type ReportCallback = (message: string) => void;
|
||||||
export type ShowReportCallBack = (userId: string, userName: string|undefined) => void;
|
export type ShowReportCallBack = (userId: string, userName: string|undefined) => void;
|
||||||
|
export type HelpCameraSettingsCallBack = () => void;
|
||||||
|
|
||||||
// TODO: Split MediaManager in 2 classes: MediaManagerUI (in charge of HTML) and MediaManager (singleton in charge of the camera only)
|
// TODO: Split MediaManager in 2 classes: MediaManagerUI (in charge of HTML) and MediaManager (singleton in charge of the camera only)
|
||||||
export class MediaManager {
|
export class MediaManager {
|
||||||
@ -40,6 +43,7 @@ export class MediaManager {
|
|||||||
microphoneClose: HTMLImageElement;
|
microphoneClose: HTMLImageElement;
|
||||||
microphone: HTMLImageElement;
|
microphone: HTMLImageElement;
|
||||||
webrtcInAudio: HTMLAudioElement;
|
webrtcInAudio: HTMLAudioElement;
|
||||||
|
mySoundMeterElement: HTMLDivElement;
|
||||||
private webrtcOutAudio: HTMLAudioElement;
|
private webrtcOutAudio: HTMLAudioElement;
|
||||||
constraintsMedia : MediaStreamConstraints = {
|
constraintsMedia : MediaStreamConstraints = {
|
||||||
audio: audioConstraint,
|
audio: audioConstraint,
|
||||||
@ -49,6 +53,8 @@ export class MediaManager {
|
|||||||
startScreenSharingCallBacks : Set<StartScreenSharingCallback> = new Set<StartScreenSharingCallback>();
|
startScreenSharingCallBacks : Set<StartScreenSharingCallback> = new Set<StartScreenSharingCallback>();
|
||||||
stopScreenSharingCallBacks : Set<StopScreenSharingCallback> = new Set<StopScreenSharingCallback>();
|
stopScreenSharingCallBacks : Set<StopScreenSharingCallback> = new Set<StopScreenSharingCallback>();
|
||||||
showReportModalCallBacks : Set<ShowReportCallBack> = new Set<ShowReportCallBack>();
|
showReportModalCallBacks : Set<ShowReportCallBack> = new Set<ShowReportCallBack>();
|
||||||
|
helpCameraSettingsCallBacks : Set<HelpCameraSettingsCallBack> = new Set<HelpCameraSettingsCallBack>();
|
||||||
|
|
||||||
private microphoneBtn: HTMLDivElement;
|
private microphoneBtn: HTMLDivElement;
|
||||||
private cinemaBtn: HTMLDivElement;
|
private cinemaBtn: HTMLDivElement;
|
||||||
private monitorBtn: HTMLDivElement;
|
private monitorBtn: HTMLDivElement;
|
||||||
@ -63,6 +69,12 @@ export class MediaManager {
|
|||||||
|
|
||||||
private triggerCloseJistiFrame : Map<String, Function> = new Map<String, Function>();
|
private triggerCloseJistiFrame : Map<String, Function> = new Map<String, Function>();
|
||||||
|
|
||||||
|
private userInputManager?: UserInputManager;
|
||||||
|
|
||||||
|
private mySoundMeter?: SoundMeter|null;
|
||||||
|
private soundMeters: Map<string, SoundMeter> = new Map<string, SoundMeter>();
|
||||||
|
private soundMeterElements: Map<string, HTMLDivElement> = new Map<string, HTMLDivElement>();
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
||||||
this.myCamVideo = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideo');
|
this.myCamVideo = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideo');
|
||||||
@ -121,10 +133,16 @@ export class MediaManager {
|
|||||||
this.pingCameraStatus();
|
this.pingCameraStatus();
|
||||||
|
|
||||||
this.checkActiveUser(); //todo: desactivated in case of bug
|
this.checkActiveUser(); //todo: desactivated in case of bug
|
||||||
|
|
||||||
|
this.mySoundMeterElement = (HtmlUtils.getElementByIdOrFail('mySoundMeter'));
|
||||||
|
this.mySoundMeterElement.childNodes.forEach((value: ChildNode, index) => {
|
||||||
|
this.mySoundMeterElement.children.item(index)?.classList.remove('active');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public setLastUpdateScene(){
|
public updateScene(){
|
||||||
this.lastUpdateScene = new Date();
|
this.lastUpdateScene = new Date();
|
||||||
|
this.updateSoudMeter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public blurCamera() {
|
public blurCamera() {
|
||||||
@ -225,6 +243,10 @@ export class MediaManager {
|
|||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
this.disableCameraStyle();
|
this.disableCameraStyle();
|
||||||
|
|
||||||
|
layoutManager.addInformation('warning', 'Camera access denied. Click here and check navigators permissions.', () => {
|
||||||
|
this.showHelpCameraSettingsCallBack();
|
||||||
|
}, this.userInputManager);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,6 +275,10 @@ export class MediaManager {
|
|||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
this.disableMicrophoneStyle();
|
this.disableMicrophoneStyle();
|
||||||
|
|
||||||
|
layoutManager.addInformation('warning', 'Microphone access denied. Click here and check navigators permissions.', () => {
|
||||||
|
this.showHelpCameraSettingsCallBack();
|
||||||
|
}, this.userInputManager);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,6 +350,10 @@ export class MediaManager {
|
|||||||
this.monitorClose.style.display = "block";
|
this.monitorClose.style.display = "block";
|
||||||
this.monitor.style.display = "none";
|
this.monitor.style.display = "none";
|
||||||
this.monitorBtn.classList.remove("enabled");
|
this.monitorBtn.classList.remove("enabled");
|
||||||
|
|
||||||
|
layoutManager.addInformation('warning', 'Screen sharing access denied. Click here and check navigators permissions.', () => {
|
||||||
|
this.showHelpCameraSettingsCallBack();
|
||||||
|
}, this.userInputManager);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -402,13 +432,14 @@ export class MediaManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.getLocalStream().catch(() => {
|
return this.getLocalStream().catch((err) => {
|
||||||
console.info('Error get camera, trying with video option at null');
|
console.info('Error get camera, trying with video option at null =>', err);
|
||||||
this.disableCameraStyle();
|
this.disableCameraStyle();
|
||||||
return this.getLocalStream().then((stream : MediaStream) => {
|
return this.getLocalStream().then((stream : MediaStream) => {
|
||||||
this.hasCamera = false;
|
this.hasCamera = false;
|
||||||
return stream;
|
return stream;
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
|
this.disableMicrophoneStyle();
|
||||||
console.info("error get media ", this.constraintsMedia.video, this.constraintsMedia.audio, err);
|
console.info("error get media ", this.constraintsMedia.video, this.constraintsMedia.audio, err);
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
@ -425,6 +456,13 @@ export class MediaManager {
|
|||||||
return navigator.mediaDevices.getUserMedia(this.constraintsMedia).then((stream : MediaStream) => {
|
return navigator.mediaDevices.getUserMedia(this.constraintsMedia).then((stream : MediaStream) => {
|
||||||
this.localStream = stream;
|
this.localStream = stream;
|
||||||
this.myCamVideo.srcObject = this.localStream;
|
this.myCamVideo.srcObject = this.localStream;
|
||||||
|
|
||||||
|
//init sound meter
|
||||||
|
this.mySoundMeter = null;
|
||||||
|
if(this.constraintsMedia.audio){
|
||||||
|
this.mySoundMeter = new SoundMeter();
|
||||||
|
this.mySoundMeter.connectToSource(stream, new AudioContext());
|
||||||
|
}
|
||||||
return stream;
|
return stream;
|
||||||
}).catch((err: Error) => {
|
}).catch((err: Error) => {
|
||||||
throw err;
|
throw err;
|
||||||
@ -451,6 +489,7 @@ export class MediaManager {
|
|||||||
track.stop();
|
track.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.mySoundMeter?.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
setCamera(id: string): Promise<MediaStream> {
|
setCamera(id: string): Promise<MediaStream> {
|
||||||
@ -496,6 +535,13 @@ export class MediaManager {
|
|||||||
</button>
|
</button>
|
||||||
<video id="${userId}" autoplay></video>
|
<video id="${userId}" autoplay></video>
|
||||||
<img src="resources/logos/blockSign.svg" id="blocking-${userId}" class="block-logo">
|
<img src="resources/logos/blockSign.svg" id="blocking-${userId}" class="block-logo">
|
||||||
|
<div id="soundMeter-${userId}" class="sound-progress">
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -585,6 +631,12 @@ export class MediaManager {
|
|||||||
throw `Unable to find video for ${userId}`;
|
throw `Unable to find video for ${userId}`;
|
||||||
}
|
}
|
||||||
remoteVideo.srcObject = stream;
|
remoteVideo.srcObject = stream;
|
||||||
|
|
||||||
|
//sound metter
|
||||||
|
const soundMeter = new SoundMeter();
|
||||||
|
soundMeter.connectToSource(stream, new AudioContext());
|
||||||
|
this.soundMeters.set(userId, soundMeter);
|
||||||
|
this.soundMeterElements.set(userId, HtmlUtils.getElementByIdOrFail<HTMLImageElement>('soundMeter-'+userId));
|
||||||
}
|
}
|
||||||
addStreamRemoteScreenSharing(userId: string, stream : MediaStream){
|
addStreamRemoteScreenSharing(userId: string, stream : MediaStream){
|
||||||
// In the case of screen sharing (going both ways), we may need to create the HTML element if it does not exist yet
|
// In the case of screen sharing (going both ways), we may need to create the HTML element if it does not exist yet
|
||||||
@ -600,6 +652,10 @@ export class MediaManager {
|
|||||||
layoutManager.remove(userId);
|
layoutManager.remove(userId);
|
||||||
this.remoteVideo.delete(userId);
|
this.remoteVideo.delete(userId);
|
||||||
|
|
||||||
|
this.soundMeters.get(userId)?.stop();
|
||||||
|
this.soundMeters.delete(userId);
|
||||||
|
this.soundMeterElements.delete(userId);
|
||||||
|
|
||||||
//permit to remove user in discussion part
|
//permit to remove user in discussion part
|
||||||
this.removeParticipant(userId);
|
this.removeParticipant(userId);
|
||||||
}
|
}
|
||||||
@ -717,6 +773,7 @@ export class MediaManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public setUserInputManager(userInputManager : UserInputManager){
|
public setUserInputManager(userInputManager : UserInputManager){
|
||||||
|
this.userInputManager = userInputManager;
|
||||||
discussionManager.setUserInputManager(userInputManager);
|
discussionManager.setUserInputManager(userInputManager);
|
||||||
}
|
}
|
||||||
//check if user is active
|
//check if user is active
|
||||||
@ -739,6 +796,57 @@ export class MediaManager {
|
|||||||
public setShowReportModalCallBacks(callback: ShowReportCallBack){
|
public setShowReportModalCallBacks(callback: ShowReportCallBack){
|
||||||
this.showReportModalCallBacks.add(callback);
|
this.showReportModalCallBacks.add(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setHelpCameraSettingsCallBack(callback: HelpCameraSettingsCallBack){
|
||||||
|
this.helpCameraSettingsCallBacks.add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private showHelpCameraSettingsCallBack(){
|
||||||
|
for(const callBack of this.helpCameraSettingsCallBacks){
|
||||||
|
callBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSoudMeter(){
|
||||||
|
try{
|
||||||
|
const volume = parseInt(((this.mySoundMeter ? this.mySoundMeter.getVolume() : 0) / 10).toFixed(0));
|
||||||
|
this.setVolumeSoundMeter(volume, this.mySoundMeterElement);
|
||||||
|
|
||||||
|
for(const indexUserId of this.soundMeters.keys()){
|
||||||
|
const soundMeter = this.soundMeters.get(indexUserId);
|
||||||
|
const soundMeterElement = this.soundMeterElements.get(indexUserId);
|
||||||
|
if(!soundMeter || !soundMeterElement){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const volumeByUser = parseInt((soundMeter.getVolume() / 10).toFixed(0));
|
||||||
|
this.setVolumeSoundMeter(volumeByUser, soundMeterElement);
|
||||||
|
}
|
||||||
|
}catch(err){
|
||||||
|
//console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private setVolumeSoundMeter(volume: number, element: HTMLDivElement){
|
||||||
|
if(volume <= 0 && !element.classList.contains('active')){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
element.classList.remove('active');
|
||||||
|
if(volume <= 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
element.classList.add('active');
|
||||||
|
element.childNodes.forEach((value: ChildNode, index) => {
|
||||||
|
const elementChildre = element.children.item(index);
|
||||||
|
if(!elementChildre){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
elementChildre.classList.remove('active');
|
||||||
|
if((index +1) > volume){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
elementChildre.classList.add('active');
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mediaManager = new MediaManager();
|
export const mediaManager = new MediaManager();
|
||||||
|
@ -22,7 +22,7 @@ export class ScreenSharingPeer extends Peer {
|
|||||||
constructor(user: UserSimplePeerInterface, initiator: boolean, private connection: RoomConnection) {
|
constructor(user: UserSimplePeerInterface, initiator: boolean, private connection: RoomConnection) {
|
||||||
super({
|
super({
|
||||||
initiator: initiator ? initiator : false,
|
initiator: initiator ? initiator : false,
|
||||||
reconnectTimer: 10000,
|
//reconnectTimer: 10000,
|
||||||
config: {
|
config: {
|
||||||
iceServers: [
|
iceServers: [
|
||||||
{
|
{
|
||||||
|
@ -82,15 +82,11 @@ export class SimplePeer {
|
|||||||
});
|
});
|
||||||
|
|
||||||
mediaManager.showGameOverlay();
|
mediaManager.showGameOverlay();
|
||||||
mediaManager.getCamera().then(() => {
|
mediaManager.getCamera().finally(() => {
|
||||||
|
|
||||||
//receive message start
|
//receive message start
|
||||||
this.Connection.receiveWebrtcStart((message: UserSimplePeerInterface) => {
|
this.Connection.receiveWebrtcStart((message: UserSimplePeerInterface) => {
|
||||||
this.receiveWebrtcStart(message);
|
this.receiveWebrtcStart(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
}).catch((err) => {
|
|
||||||
console.error("err", err);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Connection.disconnectMessage((data: WebRtcDisconnectMessageInterface): void => {
|
this.Connection.disconnectMessage((data: WebRtcDisconnectMessageInterface): void => {
|
||||||
|
@ -28,7 +28,7 @@ export class VideoPeer extends Peer {
|
|||||||
constructor(public user: UserSimplePeerInterface, initiator: boolean, private connection: RoomConnection) {
|
constructor(public user: UserSimplePeerInterface, initiator: boolean, private connection: RoomConnection) {
|
||||||
super({
|
super({
|
||||||
initiator: initiator ? initiator : false,
|
initiator: initiator ? initiator : false,
|
||||||
reconnectTimer: 10000,
|
//reconnectTimer: 10000,
|
||||||
config: {
|
config: {
|
||||||
iceServers: [
|
iceServers: [
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@ import 'phaser';
|
|||||||
import GameConfig = Phaser.Types.Core.GameConfig;
|
import GameConfig = Phaser.Types.Core.GameConfig;
|
||||||
import "../dist/resources/style/index.scss";
|
import "../dist/resources/style/index.scss";
|
||||||
|
|
||||||
import {DEBUG_MODE, isMobile, RESOLUTION} from "./Enum/EnvironmentVariable";
|
import {DEBUG_MODE, isMobile} from "./Enum/EnvironmentVariable";
|
||||||
import {LoginScene} from "./Phaser/Login/LoginScene";
|
import {LoginScene} from "./Phaser/Login/LoginScene";
|
||||||
import {ReconnectingScene} from "./Phaser/Reconnecting/ReconnectingScene";
|
import {ReconnectingScene} from "./Phaser/Reconnecting/ReconnectingScene";
|
||||||
import {SelectCharacterScene} from "./Phaser/Login/SelectCharacterScene";
|
import {SelectCharacterScene} from "./Phaser/Login/SelectCharacterScene";
|
||||||
@ -18,6 +18,9 @@ import {localUserStore} from "./Connexion/LocalUserStore";
|
|||||||
import {ErrorScene} from "./Phaser/Reconnecting/ErrorScene";
|
import {ErrorScene} from "./Phaser/Reconnecting/ErrorScene";
|
||||||
import {iframeListener} from "./Api/IframeListener";
|
import {iframeListener} from "./Api/IframeListener";
|
||||||
import { SelectCharacterMobileScene } from './Phaser/Login/SelectCharacterMobileScene';
|
import { SelectCharacterMobileScene } from './Phaser/Login/SelectCharacterMobileScene';
|
||||||
|
import {HdpiManager} from "./Phaser/Services/HdpiManager";
|
||||||
|
import {waScaleManager} from "./Phaser/Services/WaScaleManager";
|
||||||
|
import {Game} from "./Phaser/Game/Game";
|
||||||
|
|
||||||
const {width, height} = coWebsiteManager.getGameSize();
|
const {width, height} = coWebsiteManager.getGameSize();
|
||||||
|
|
||||||
@ -68,12 +71,20 @@ switch (phaserMode) {
|
|||||||
throw new Error('phaserMode parameter must be one of "auto", "canvas" or "webgl"');
|
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 = {
|
const config: GameConfig = {
|
||||||
type: mode,
|
type: mode,
|
||||||
title: "WorkAdventure",
|
title: "WorkAdventure",
|
||||||
width: width / RESOLUTION,
|
scale: {
|
||||||
height: height / RESOLUTION,
|
|
||||||
parent: "game",
|
parent: "game",
|
||||||
|
width: gameSize.width,
|
||||||
|
height: gameSize.height,
|
||||||
|
zoom: realSize.width / gameSize.width,
|
||||||
|
autoRound: true,
|
||||||
|
resizeInterval: 999999999999
|
||||||
|
},
|
||||||
scene: [EntryScene,
|
scene: [EntryScene,
|
||||||
LoginScene,
|
LoginScene,
|
||||||
isMobile() ? SelectCharacterMobileScene : SelectCharacterScene,
|
isMobile() ? SelectCharacterMobileScene : SelectCharacterScene,
|
||||||
@ -84,7 +95,7 @@ const config: GameConfig = {
|
|||||||
CustomizeScene,
|
CustomizeScene,
|
||||||
MenuScene,
|
MenuScene,
|
||||||
HelpCameraSettingsScene],
|
HelpCameraSettingsScene],
|
||||||
zoom: RESOLUTION,
|
//resolution: window.devicePixelRatio / 2,
|
||||||
fps: fps,
|
fps: fps,
|
||||||
dom: {
|
dom: {
|
||||||
createContainer: true
|
createContainer: true
|
||||||
@ -100,6 +111,8 @@ const config: GameConfig = {
|
|||||||
debug: DEBUG_MODE,
|
debug: DEBUG_MODE,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// Instruct systems with 2 GPU to choose the low power one. We don't need that extra power and we want to save battery
|
||||||
|
powerPreference: "low-power",
|
||||||
callbacks: {
|
callbacks: {
|
||||||
postBoot: game => {
|
postBoot: game => {
|
||||||
// Commented out to try to fix MacOS bug
|
// Commented out to try to fix MacOS bug
|
||||||
@ -111,12 +124,15 @@ const config: GameConfig = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const game = new Phaser.Game(config);
|
//const game = new Phaser.Game(config);
|
||||||
|
const game = new Game(config);
|
||||||
|
|
||||||
|
waScaleManager.setScaleManager(game.scale);
|
||||||
|
|
||||||
window.addEventListener('resize', function (event) {
|
window.addEventListener('resize', function (event) {
|
||||||
coWebsiteManager.resetStyle();
|
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
|
// Let's trigger the onResize method of any active scene that is a ResizableScene
|
||||||
for (const scene of game.scene.getScenes(true)) {
|
for (const scene of game.scene.getScenes(true)) {
|
||||||
@ -127,8 +143,7 @@ window.addEventListener('resize', function (event) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
coWebsiteManager.onResize.subscribe(() => {
|
coWebsiteManager.onResize.subscribe(() => {
|
||||||
const {width, height} = coWebsiteManager.getGameSize();
|
waScaleManager.applyNewSize();
|
||||||
game.scale.resize(width / RESOLUTION, height / RESOLUTION);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
iframeListener.init();
|
iframeListener.init();
|
||||||
|
@ -19,9 +19,6 @@ describe("isUserNameValid()", () => {
|
|||||||
it("should not validate spaces", () => {
|
it("should not validate spaces", () => {
|
||||||
expect(isUserNameValid(' ')).toBe(false);
|
expect(isUserNameValid(' ')).toBe(false);
|
||||||
});
|
});
|
||||||
it("should not validate numbers", () => {
|
|
||||||
expect(isUserNameValid('a12')).toBe(false);
|
|
||||||
});
|
|
||||||
it("should not validate special characters", () => {
|
it("should not validate special characters", () => {
|
||||||
expect(isUserNameValid('a&-')).toBe(false);
|
expect(isUserNameValid('a&-')).toBe(false);
|
||||||
});
|
});
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
});
|
1185
front/yarn.lock
@ -24,7 +24,7 @@
|
|||||||
{
|
{
|
||||||
"name":"exitUrl",
|
"name":"exitUrl",
|
||||||
"type":"string",
|
"type":"string",
|
||||||
"value":"\/@\/tcm\/workadventure\/floor0"
|
"value":"\/@\/tcm\/workadventure\/wa-village"
|
||||||
}],
|
}],
|
||||||
"type":"tilelayer",
|
"type":"tilelayer",
|
||||||
"visible":true,
|
"visible":true,
|
||||||
@ -260,15 +260,15 @@
|
|||||||
"name":"floorLayer",
|
"name":"floorLayer",
|
||||||
"objects":[
|
"objects":[
|
||||||
{
|
{
|
||||||
"height":199.667,
|
"height":140,
|
||||||
"id":1,
|
"id":1,
|
||||||
"name":"Tutobubble",
|
"name":"Tutobubble",
|
||||||
"rotation":0,
|
"rotation":0,
|
||||||
"type":"",
|
"type":"",
|
||||||
"visible":true,
|
"visible":true,
|
||||||
"width":245.667,
|
"width":185,
|
||||||
"x":1170,
|
"x":1022,
|
||||||
"y":350
|
"y":308
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"height":86.9996666666667,
|
"height":86.9996666666667,
|
||||||
@ -277,9 +277,9 @@
|
|||||||
"rotation":0,
|
"rotation":0,
|
||||||
"type":"",
|
"type":"",
|
||||||
"visible":true,
|
"visible":true,
|
||||||
"width":245.667,
|
"width":187,
|
||||||
"x":1171,
|
"x":1019,
|
||||||
"y":412
|
"y":361
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"height":84.6667,
|
"height":84.6667,
|
||||||
@ -288,9 +288,9 @@
|
|||||||
"rotation":0,
|
"rotation":0,
|
||||||
"type":"",
|
"type":"",
|
||||||
"visible":true,
|
"visible":true,
|
||||||
"width":210.667,
|
"width":184.5,
|
||||||
"x":1030.5,
|
"x":1023,
|
||||||
"y":318.66665
|
"y":319
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"height":99.6667,
|
"height":99.6667,
|
||||||
@ -299,9 +299,9 @@
|
|||||||
"rotation":0,
|
"rotation":0,
|
||||||
"type":"",
|
"type":"",
|
||||||
"visible":true,
|
"visible":true,
|
||||||
"width":210.667,
|
"width":185,
|
||||||
"x":1174,
|
"x":1021,
|
||||||
"y":400
|
"y":348
|
||||||
}],
|
}],
|
||||||
"opacity":1,
|
"opacity":1,
|
||||||
"type":"objectgroup",
|
"type":"objectgroup",
|
||||||
|
Before Width: | Height: | Size: 3.8 KiB |
BIN
maps/Village/logo-WA.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
BIN
maps/Village/sol_intérieur.png
Normal file
After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 3.0 KiB |
BIN
maps/Village/tileset1-repositioning.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
maps/Village/tileset1.png
Normal file
After Width: | Height: | Size: 29 KiB |
127
maps/tests/Properties/mapProperties.json
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":10,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"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, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":1,
|
||||||
|
"name":"start",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 33, 34, 34, 34, 34, 34, 34, 35, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 49, 50, 50, 50, 50, 50, 50, 51, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46],
|
||||||
|
"height":10,
|
||||||
|
"id":2,
|
||||||
|
"name":"bottom",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19],
|
||||||
|
"height":10,
|
||||||
|
"id":3,
|
||||||
|
"name":"wall",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":4,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":5,
|
||||||
|
"nextobjectid":1,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"mapCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"@GRL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"mapDescription",
|
||||||
|
"type":"string",
|
||||||
|
"value":"Cette carte est tr\u00e8s simple."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"mapLink",
|
||||||
|
"type":"string",
|
||||||
|
"value":"Cette carte se trouve sur internet"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"mapName",
|
||||||
|
"type":"string",
|
||||||
|
"value":"MAP NAME"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"mapImage",
|
||||||
|
"type":"string",
|
||||||
|
"value":"/images/maps/image.png"
|
||||||
|
}],
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.4.3",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":8,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"..\/Validation\/tileset_dungeon.png",
|
||||||
|
"imageheight":256,
|
||||||
|
"imagewidth":256,
|
||||||
|
"margin":0,
|
||||||
|
"name":"dungeon",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"tilesetCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"@TTT GRL"
|
||||||
|
}],
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":64,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns":11,
|
||||||
|
"firstgid":65,
|
||||||
|
"image":"..\/Validation\/Yellow Dungeon Tileset.jpg",
|
||||||
|
"imageheight":128,
|
||||||
|
"imagewidth":352,
|
||||||
|
"margin":0,
|
||||||
|
"name":"YellowDungeon",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"tilesetCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"@YYY GRL"
|
||||||
|
}],
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":44,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":1.4,
|
||||||
|
"width":10
|
||||||
|
}
|
BIN
maps/tests/Validation/16x16_Dungeon.png
Normal file
After Width: | Height: | Size: 21 KiB |
183
maps/tests/Validation/4096.json
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":10,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095, 8095],
|
||||||
|
"height":10,
|
||||||
|
"id":1,
|
||||||
|
"name":"bottom",
|
||||||
|
"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, 302, 303, 304, 0, 0, 0, 0, 0, 0, 0, 320, 321, 322, 0, 0, 0, 0, 0, 0, 0, 338, 339, 340, 0, 0, 0, 0, 0, 0, 0, 356, 357, 358, 0, 0, 212, 213, 214, 0, 0, 0, 0, 0, 0, 0, 230, 231, 232, 0, 0, 0, 0, 0, 0, 0, 248, 249, 250, 0, 0, 0, 0, 0, 0, 0, 266, 267, 268, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":5,
|
||||||
|
"name":"Tapis",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[8083, 8084, 8084, 8084, 8084, 8084, 8084, 8084, 8084, 8085, 8094, 0, 0, 0, 0, 0, 0, 0, 0, 8096, 8094, 0, 0, 0, 0, 0, 0, 0, 0, 8096, 8094, 0, 0, 0, 0, 0, 0, 0, 0, 8096, 8094, 0, 0, 0, 0, 0, 0, 0, 0, 8096, 8094, 0, 0, 0, 0, 0, 0, 0, 0, 8096, 8094, 0, 0, 0, 0, 0, 0, 0, 0, 8096, 8094, 0, 0, 0, 0, 0, 0, 0, 0, 8096, 8094, 0, 0, 0, 0, 0, 0, 0, 0, 8096, 8105, 8106, 8106, 8106, 8106, 8106, 8106, 8106, 8106, 8107],
|
||||||
|
"height":10,
|
||||||
|
"id":3,
|
||||||
|
"name":"wall",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":4,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":6,
|
||||||
|
"nextobjectid":1,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.4.3",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":18,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"4096.png",
|
||||||
|
"imageheight":14368,
|
||||||
|
"imagewidth":600,
|
||||||
|
"margin":0,
|
||||||
|
"name":"4096",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":8082,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns":11,
|
||||||
|
"firstgid":8083,
|
||||||
|
"image":"Yellow Dungeon Tileset.jpg",
|
||||||
|
"imageheight":128,
|
||||||
|
"imagewidth":352,
|
||||||
|
"margin":0,
|
||||||
|
"name":"Yellow Dungeon Tileset",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":44,
|
||||||
|
"tileheight":32,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":0,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":2,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":11,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":12,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":13,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":22,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":23,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":24,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":1.4,
|
||||||
|
"width":10
|
||||||
|
}
|
BIN
maps/tests/Validation/4096.png
Normal file
After Width: | Height: | Size: 468 KiB |
239
maps/tests/Validation/CollidesFalse.json
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":10,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 33, 34, 34, 34, 34, 34, 34, 35, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 49, 50, 50, 50, 50, 50, 50, 51, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46],
|
||||||
|
"height":10,
|
||||||
|
"id":1,
|
||||||
|
"name":"bottom",
|
||||||
|
"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, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 9, 0, 0, 0, 0, 0, 0, 0, 7, 11, 9, 0, 0, 22, 0, 0, 0, 0, 0, 11, 9, 7, 0, 0, 0, 0, 0, 22, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 22, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 8, 22, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 8, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19],
|
||||||
|
"height":10,
|
||||||
|
"id":3,
|
||||||
|
"name":"wall",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":4,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":5,
|
||||||
|
"nextobjectid":1,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.4.3",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":8,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"tileset_dungeon.png",
|
||||||
|
"imageheight":256,
|
||||||
|
"imagewidth":256,
|
||||||
|
"margin":0,
|
||||||
|
"name":"dungeon",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":64,
|
||||||
|
"tileheight":32,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":0,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":2,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":3,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":4,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":6,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":7,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":8,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":9,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":10,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":11,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":12,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":16,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":17,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":18,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":19,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":20,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":21,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":1.4,
|
||||||
|
"width":10
|
||||||
|
}
|
309
maps/tests/Validation/Infini.json
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":10,
|
||||||
|
"infinite":true,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"chunks":[
|
||||||
|
{
|
||||||
|
"data":[46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42],
|
||||||
|
"height":16,
|
||||||
|
"width":16,
|
||||||
|
"x":-32,
|
||||||
|
"y":-16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42],
|
||||||
|
"height":16,
|
||||||
|
"width":16,
|
||||||
|
"x":-16,
|
||||||
|
"y":-16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46],
|
||||||
|
"height":16,
|
||||||
|
"width":16,
|
||||||
|
"x":0,
|
||||||
|
"y":-16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 46, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46],
|
||||||
|
"height":16,
|
||||||
|
"width":16,
|
||||||
|
"x":-32,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46],
|
||||||
|
"height":16,
|
||||||
|
"width":16,
|
||||||
|
"x":-16,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 46, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 0, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46],
|
||||||
|
"height":16,
|
||||||
|
"width":16,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"height":32,
|
||||||
|
"id":2,
|
||||||
|
"name":"bottom",
|
||||||
|
"opacity":1,
|
||||||
|
"startx":-32,
|
||||||
|
"starty":-16,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":48,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chunks":[
|
||||||
|
{
|
||||||
|
"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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 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":16,
|
||||||
|
"width":16,
|
||||||
|
"x":-16,
|
||||||
|
"y":-16
|
||||||
|
}],
|
||||||
|
"height":16,
|
||||||
|
"id":3,
|
||||||
|
"name":"start",
|
||||||
|
"opacity":1,
|
||||||
|
"startx":-16,
|
||||||
|
"starty":-16,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":16,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chunks":[
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":16,
|
||||||
|
"width":16,
|
||||||
|
"x":-32,
|
||||||
|
"y":-16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":16,
|
||||||
|
"width":16,
|
||||||
|
"x":-16,
|
||||||
|
"y":-16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11],
|
||||||
|
"height":16,
|
||||||
|
"width":16,
|
||||||
|
"x":0,
|
||||||
|
"y":-16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":16,
|
||||||
|
"width":16,
|
||||||
|
"x":-32,
|
||||||
|
"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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":16,
|
||||||
|
"width":16,
|
||||||
|
"x":-16,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":16,
|
||||||
|
"width":16,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"height":32,
|
||||||
|
"id":1,
|
||||||
|
"name":"wall",
|
||||||
|
"opacity":1,
|
||||||
|
"startx":-32,
|
||||||
|
"starty":-16,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":48,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":4,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":5,
|
||||||
|
"nextobjectid":1,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.4.3",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":8,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"tileset_dungeon.png",
|
||||||
|
"imageheight":256,
|
||||||
|
"imagewidth":256,
|
||||||
|
"margin":0,
|
||||||
|
"name":"dungeon",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":64,
|
||||||
|
"tileheight":32,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":0,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":2,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":3,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":4,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":8,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":9,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":10,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":11,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":12,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":16,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":17,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":18,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":19,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":20,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":1.4,
|
||||||
|
"width":10
|
||||||
|
}
|
244
maps/tests/Validation/NoCollides.json
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":10,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 33, 34, 34, 34, 34, 34, 34, 35, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 49, 50, 50, 50, 50, 50, 50, 51, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46],
|
||||||
|
"height":10,
|
||||||
|
"id":1,
|
||||||
|
"name":"bottom",
|
||||||
|
"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, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 7, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 8, 0, 0, 0, 0, 22, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 22, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19],
|
||||||
|
"height":10,
|
||||||
|
"id":3,
|
||||||
|
"name":"wall",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":4,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":5,
|
||||||
|
"nextobjectid":1,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.4.3",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":8,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"tileset_dungeon.png",
|
||||||
|
"imageheight":256,
|
||||||
|
"imagewidth":256,
|
||||||
|
"margin":0,
|
||||||
|
"name":"dungeon",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":64,
|
||||||
|
"tileheight":32,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":0,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":2,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":3,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":4,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":6,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"test2",
|
||||||
|
"type":"int",
|
||||||
|
"value":2
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":7,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"test",
|
||||||
|
"type":"int",
|
||||||
|
"value":3
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":8,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":9,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":10,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":11,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":12,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":16,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":17,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":18,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":19,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":20,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":21,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collide",
|
||||||
|
"type":"bool",
|
||||||
|
"value":false
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":1.4,
|
||||||
|
"width":10
|
||||||
|
}
|
149
maps/tests/Validation/NoImage.json
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":10,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13],
|
||||||
|
"height":10,
|
||||||
|
"id":1,
|
||||||
|
"name":"bottom",
|
||||||
|
"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, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 12, 0, 0, 0, 0, 0, 0, 0, 0, 14, 12, 0, 0, 0, 0, 0, 0, 0, 0, 14, 12, 0, 0, 0, 0, 0, 0, 0, 0, 14, 12, 0, 0, 0, 0, 0, 0, 0, 0, 14, 12, 0, 0, 0, 0, 0, 0, 0, 0, 14, 12, 0, 0, 0, 0, 0, 0, 0, 0, 14, 12, 0, 0, 0, 0, 0, 0, 0, 0, 14, 12, 0, 0, 0, 0, 0, 0, 0, 0, 14, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25],
|
||||||
|
"height":10,
|
||||||
|
"id":3,
|
||||||
|
"name":"wall",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":4,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":5,
|
||||||
|
"nextobjectid":1,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.4.3",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":11,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"Yellow Dungeon Tileset.png",
|
||||||
|
"imageheight":128,
|
||||||
|
"imagewidth":352,
|
||||||
|
"margin":0,
|
||||||
|
"name":"Yellow Dungeon Tileset",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":44,
|
||||||
|
"tileheight":32,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":0,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":2,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":11,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":13,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":22,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":23,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":24,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":1.4,
|
||||||
|
"width":10
|
||||||
|
}
|
177
maps/tests/Validation/Validation0.json
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
{ "compressionlevel":-1,
|
||||||
|
"editorsettings":
|
||||||
|
{
|
||||||
|
"export":
|
||||||
|
{
|
||||||
|
"target":"."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"height":10,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 33, 34, 34, 34, 34, 34, 34, 35, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 49, 50, 50, 50, 50, 50, 50, 51, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46],
|
||||||
|
"height":10,
|
||||||
|
"id":3,
|
||||||
|
"name":"bottom",
|
||||||
|
"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, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":1,
|
||||||
|
"name":"start",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19],
|
||||||
|
"height":10,
|
||||||
|
"id":4,
|
||||||
|
"name":"wall",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":5,
|
||||||
|
"name":"top",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":2,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":6,
|
||||||
|
"nextobjectid":1,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.4.3",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":8,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"tileset_dungeon.png",
|
||||||
|
"imageheight":256,
|
||||||
|
"imagewidth":256,
|
||||||
|
"margin":0,
|
||||||
|
"name":"dungeon",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":64,
|
||||||
|
"tileheight":32,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":0,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":2,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":5,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":8,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":10,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":16,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":17,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":18,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":1.4,
|
||||||
|
"width":10
|
||||||
|
}
|