Merge branch 'develop' of github.com:thecodingmachine/workadventure into resolution
33
.github/workflows/build-and-deploy.yml
vendored
@ -1,7 +1,11 @@
|
||||
name: Build, push and deploy Docker image
|
||||
|
||||
on:
|
||||
- push
|
||||
release:
|
||||
types: [created]
|
||||
pull_request:
|
||||
types: [ labeled, synchronize ]
|
||||
|
||||
|
||||
# Enables BuildKit
|
||||
env:
|
||||
@ -10,7 +14,7 @@ env:
|
||||
jobs:
|
||||
|
||||
build-front:
|
||||
|
||||
if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@ -30,11 +34,11 @@ jobs:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
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
|
||||
|
||||
build-back:
|
||||
|
||||
if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@ -53,11 +57,11 @@ jobs:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
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
|
||||
|
||||
build-pusher:
|
||||
|
||||
if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@ -76,11 +80,11 @@ jobs:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
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
|
||||
|
||||
build-uploader:
|
||||
|
||||
if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@ -99,11 +103,11 @@ jobs:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
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
|
||||
|
||||
build-maps:
|
||||
|
||||
if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@ -123,7 +127,7 @@ jobs:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
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
|
||||
|
||||
deeploy:
|
||||
@ -134,6 +138,7 @@ jobs:
|
||||
- build-maps
|
||||
- build-uploader
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ contains(github.event.pull_request.labels.*.name, 'deploy') }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@ -151,14 +156,14 @@ jobs:
|
||||
JITSI_URL: ${{ secrets.JITSI_URL }}
|
||||
SECRET_JITSI_KEY: ${{ secrets.SECRET_JITSI_KEY }}
|
||||
TURN_STATIC_AUTH_SECRET: ${{ secrets.TURN_STATIC_AUTH_SECRET }}
|
||||
DEPLOY_REF: ${{ env.GITHUB_HEAD_REF_SLUG }}
|
||||
with:
|
||||
namespace: workadventure-${{ env.GITHUB_REF_SLUG }}
|
||||
namespace: workadventure-${{ env.GITHUB_HEAD_REF_SLUG }}
|
||||
|
||||
- name: Add a comment in PR
|
||||
uses: unsplash/comment-on-pr@v1.2.0
|
||||
if: ${{ env.GITHUB_REF_SLUG != 'master' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
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
|
||||
|
10
.github/workflows/cleanup.yml
vendored
@ -1,7 +1,8 @@
|
||||
name: Cleanup images and environments
|
||||
|
||||
on:
|
||||
- delete
|
||||
pull_request:
|
||||
types: [ closed ]
|
||||
|
||||
# Enables BuildKit
|
||||
env:
|
||||
@ -14,13 +15,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
# 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
|
||||
continue-on-error: true
|
||||
uses: thecodingmachine/deeployer-cleanup-action@master
|
||||
env:
|
||||
KUBE_CONFIG_FILE: ${{ secrets.KUBE_CONFIG_FILE }}
|
||||
with:
|
||||
# FIXME: we are not using ${{ env.GITHUB_REF_SLUG }} that resolves to master BUT! we are not using a slugified namespace
|
||||
# so complex namespace names will not be treated correctly
|
||||
namespace: workadventure-${{ github.event.ref }}
|
||||
namespace: workadventure-${{ env.GITHUB_HEAD_REF_SLUG }}
|
||||
|
7
.github/workflows/continuous_integration.yml
vendored
@ -3,8 +3,11 @@
|
||||
name: "Continuous Integration"
|
||||
|
||||
on:
|
||||
- "pull_request"
|
||||
- "push"
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
|
||||
|
10
CHANGELOG.md
Normal file
@ -0,0 +1,10 @@
|
||||
## Version 1.3.0 - in dev
|
||||
|
||||
### New Features
|
||||
|
||||
* Maps can now contain "group" layers (layers that contain other layers) - #899 #779 (@Lurkars @moufmouf)
|
||||
|
||||
### Updates
|
||||
|
||||
|
||||
### Bug Fixes
|
@ -20,7 +20,7 @@ Install Docker.
|
||||
Run:
|
||||
|
||||
```
|
||||
docker-compose up
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
The environment will start.
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
local env = std.extVar("env"),
|
||||
local namespace = env.GITHUB_REF_SLUG,
|
||||
local namespace = env.DEPLOY_REF,
|
||||
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.
|
||||
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",
|
||||
|
@ -30,7 +30,8 @@ services:
|
||||
UPLOADER_URL: /uploader
|
||||
ADMIN_URL: /admin
|
||||
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"
|
||||
# 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
|
||||
|
19
front/dist/index.tmpl.html
vendored
@ -48,20 +48,27 @@
|
||||
<div id="activeCam" class="activeCam">
|
||||
<div id="div-myCamVideo" class="video-container">
|
||||
<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 class="btn-cam-action">
|
||||
<div id="btn-micro" class="btn-micro">
|
||||
<img id="microphone" src="resources/logos/microphone.svg">
|
||||
<img id="microphone-close" src="resources/logos/microphone-close.svg">
|
||||
<div id="btn-monitor" class="btn-monitor">
|
||||
<img id="monitor" src="resources/logos/monitor.svg">
|
||||
<img id="monitor-close" src="resources/logos/monitor-close.svg">
|
||||
</div>
|
||||
<div id="btn-video" class="btn-video">
|
||||
<img id="cinema" src="resources/logos/cinema.svg">
|
||||
<img id="cinema-close" src="resources/logos/cinema-close.svg">
|
||||
</div>
|
||||
<div id="btn-monitor" class="btn-monitor">
|
||||
<img id="monitor" src="resources/logos/monitor.svg">
|
||||
<img id="monitor-close" src="resources/logos/monitor-close.svg">
|
||||
<div id="btn-micro" class="btn-micro">
|
||||
<img id="microphone" src="resources/logos/microphone.svg">
|
||||
<img id="microphone-close" src="resources/logos/microphone-close.svg">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
160
front/dist/resources/html/CustomCharacterScene.html
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
<style>
|
||||
*{
|
||||
font-family: PixelFont-7,monospace!important;
|
||||
}
|
||||
#customizeScene {
|
||||
background: #0000;
|
||||
/*border: 1px solid #ebeeee;*/
|
||||
border-radius: 6px;
|
||||
margin: 10px auto 0;
|
||||
color: #ebeeee;
|
||||
width: 42vw;
|
||||
height: 48vh;
|
||||
/*max-width: 300px;
|
||||
max-height: 48vh;*/
|
||||
overflow: hidden;
|
||||
}
|
||||
#customizeScene h1 {
|
||||
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
||||
border-bottom: 1px solid #a6abaf;
|
||||
border-radius: 6px 6px 0 0;
|
||||
box-sizing: border-box;
|
||||
color: #727678;
|
||||
display: block;
|
||||
height: 43px;
|
||||
padding-top: 10px;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
text-shadow: 0 -1px 0 rgba(0,0,0,0.2), 0 1px 0 #fff;
|
||||
}
|
||||
#customizeScene input {
|
||||
font-size: 70%;
|
||||
background: linear-gradient(top, #d6d7d7, #dee0e0);
|
||||
border: 1px solid #a1a3a3;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px #fff;
|
||||
box-sizing: border-box;
|
||||
color: #696969;
|
||||
height: 30px;
|
||||
transition: box-shadow 0.3s;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
#customizeScene section {
|
||||
margin: 10px;
|
||||
}
|
||||
#customizeScene section.action {
|
||||
text-align: center;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
top: 100%;
|
||||
}
|
||||
#customizeScene section.action.action-move {
|
||||
top: 55%;
|
||||
}
|
||||
#customizeScene button {
|
||||
margin: 2px 10px;
|
||||
background-color: black;;
|
||||
color: #ebeeee;
|
||||
border-radius: 7px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
#customizeScene button#customizeSceneFormCancel {
|
||||
background-color: #aca6a600;
|
||||
color: #292929;
|
||||
}
|
||||
#customizeScene section h6,
|
||||
#customizeScene section h5{
|
||||
margin: 1px;
|
||||
}
|
||||
#customizeScene section.text-center{
|
||||
text-align: center;
|
||||
}
|
||||
#customizeScene section a{
|
||||
font-size: 14px;
|
||||
text-decoration: underline;
|
||||
color: #ebeeee;
|
||||
}
|
||||
#customizeScene section a:hover{
|
||||
font-weight: 700;
|
||||
}
|
||||
#customizeScene section p{
|
||||
text-align: left;
|
||||
font-size: 8px;
|
||||
margin: 10px 10px;
|
||||
}
|
||||
#customizeScene section p.err{
|
||||
color: red;
|
||||
text-align: center;
|
||||
}
|
||||
#customizeScene section p.info{
|
||||
display: none;
|
||||
text-align: center;
|
||||
}
|
||||
#customizeScene section input#customizeSceneLink{
|
||||
background-color: #a1a3a3;
|
||||
}
|
||||
#customizeScene section button.customizeSceneButton{
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
top: -8vh;
|
||||
font-size: 10px;
|
||||
padding: 2px 4px;
|
||||
}
|
||||
#customizeScene section button.customizeSceneButton#customizeSceneButtonLeft{
|
||||
left: 0vw;
|
||||
}
|
||||
#customizeScene section button.customizeSceneButton#customizeSceneButtonRight{
|
||||
right: 0vw;
|
||||
}
|
||||
#customizeScene section button.customizeSceneButton#customizeSceneButtonUp{
|
||||
left: calc(2vw + 40px);
|
||||
transform: rotate(90deg);
|
||||
margin-top: -20px;
|
||||
}
|
||||
#customizeScene section button.customizeSceneButton#customizeSceneButtonDown{
|
||||
right: calc(2vw + 40px);
|
||||
transform: rotate(90deg);
|
||||
margin-top: 20px;
|
||||
}
|
||||
#customizeScene section.action img{
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
#customizeScene section.action a#customizeSceneFormBack img{
|
||||
margin-top: -2px;
|
||||
}
|
||||
#customizeScene section.action button#customizeSceneFormSubmit img{
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
@media only screen and (max-width: 600px) {
|
||||
#customizeScene {
|
||||
max-width: 160px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
@media only screen and (max-height: 400px) {
|
||||
#customizeScene section.action {
|
||||
top: 92%;
|
||||
}
|
||||
#customizeScene section.action.action-move {
|
||||
top: 80%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<form id="customizeScene" hidden>
|
||||
<section class="text-center">
|
||||
<h5>Custom your WOKA</h3>
|
||||
</section>
|
||||
<section class="action action-move">
|
||||
<button class="customizeSceneButton" id="customizeSceneButtonLeft"> < </button>
|
||||
<button class="customizeSceneButton" id="customizeSceneButtonRight"> > </button>
|
||||
<!--<button class="customizeSceneButton" id="customizeSceneButtonUp"> < </button>
|
||||
<button class="customizeSceneButton" id="customizeSceneButtonDown"> > </button>-->
|
||||
</section>
|
||||
<section class="action">
|
||||
<a type="submit" id="customizeSceneFormBack">Back <img src="resources/objects/arrow_up.png"/></a>
|
||||
<button type="submit" id="customizeSceneFormSubmit">Next <img src="resources/objects/arrow_up.png"/></button>
|
||||
</section>
|
||||
</form>
|
129
front/dist/resources/html/EnableCameraScene.html
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
<style>
|
||||
*{
|
||||
font-family: PixelFont-7,monospace!important;
|
||||
}
|
||||
#enableCameraScene {
|
||||
background: #000000;
|
||||
/*border: 1px solid #ebeeee;*/
|
||||
border-radius: 6px;
|
||||
margin: 20px auto 0;
|
||||
color: #ebeeee;
|
||||
max-height: 48vh;
|
||||
width: 42vw;
|
||||
max-width: 300px;
|
||||
overflow: hidden;
|
||||
}
|
||||
#enableCameraScene h1 {
|
||||
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
||||
border-bottom: 1px solid #a6abaf;
|
||||
border-radius: 6px 6px 0 0;
|
||||
box-sizing: border-box;
|
||||
color: #727678;
|
||||
display: block;
|
||||
height: 43px;
|
||||
padding-top: 10px;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
text-shadow: 0 -1px 0 rgba(0,0,0,0.2), 0 1px 0 #fff;
|
||||
}
|
||||
#enableCameraScene input {
|
||||
font-size: 70%;
|
||||
background: linear-gradient(top, #d6d7d7, #dee0e0);
|
||||
border: 1px solid #a1a3a3;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px #fff;
|
||||
box-sizing: border-box;
|
||||
color: #696969;
|
||||
height: 30px;
|
||||
transition: box-shadow 0.3s;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
#enableCameraScene section.title {
|
||||
position: absolute;
|
||||
top: 1vh;
|
||||
width: 100%;
|
||||
}
|
||||
#enableCameraScene section.action{
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 40vh;
|
||||
width: 100%;
|
||||
}
|
||||
#enableCameraScene button {
|
||||
margin: 10px;
|
||||
background-color: black;;
|
||||
color: #ebeeee;
|
||||
border-radius: 7px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
#enableCameraScene button#enableCameraSceneFormCancel {
|
||||
background-color: #c7c7c700;
|
||||
color: #292929;
|
||||
}
|
||||
#enableCameraScene section h6,
|
||||
#enableCameraScene section h5{
|
||||
margin: 1px;
|
||||
}
|
||||
#enableCameraScene section.text-center{
|
||||
text-align: center;
|
||||
}
|
||||
#enableCameraScene section a{
|
||||
font-size: 8px;
|
||||
text-decoration: underline;
|
||||
color: #ebeeee;
|
||||
}
|
||||
#enableCameraScene section a:hover{
|
||||
font-weight: 700;
|
||||
}
|
||||
#enableCameraScene section p{
|
||||
text-align: left;
|
||||
font-size: 8px;
|
||||
margin: 10px 10px;
|
||||
}
|
||||
#enableCameraScene section p.err{
|
||||
color: red;
|
||||
text-align: center;
|
||||
}
|
||||
#enableCameraScene section p.info{
|
||||
display: none;
|
||||
text-align: center;
|
||||
}
|
||||
#enableCameraScene section input#enableCameraSceneLink{
|
||||
background-color: #a1a3a3;
|
||||
}
|
||||
#enableCameraScene section img{
|
||||
width: 160px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
/*@media only screen and (max-width: 800px),
|
||||
only screen and (max-height: 600px) {
|
||||
#enableCameraScene{
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}*/
|
||||
</style>
|
||||
|
||||
<form id="enableCameraScene" hidden>
|
||||
<!-- FIX me -->
|
||||
<section class="title text-center">
|
||||
<h5>Turn on your camera and microphone</h5>
|
||||
</section>
|
||||
<!--<section class="text-center">
|
||||
<video id="myCamVideoSetup" autoplay muted></video>
|
||||
</section>
|
||||
<section class="text-center">
|
||||
<h5>Select your camera</h3>
|
||||
<select id="camera">
|
||||
</select>
|
||||
</section>
|
||||
<section class="text-center">
|
||||
<h5>Select your michrophone</h3>
|
||||
<select id="michrophone">
|
||||
</select>
|
||||
</section>-->
|
||||
<section class="action">
|
||||
<button type="submit" id="enableCameraSceneFormSubmit">Let's go!</button>
|
||||
</section>
|
||||
</form>
|
134
front/dist/resources/html/SelectCompanionScene.html
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
<style>
|
||||
*{
|
||||
font-family: PixelFont-7,monospace!important;
|
||||
}
|
||||
#selectCompanionScene {
|
||||
background: #0000;
|
||||
/*border: 1px solid #ebeeee;*/
|
||||
border-radius: 6px;
|
||||
margin: 10px auto 0;
|
||||
color: #ebeeee;
|
||||
max-height: 40vh;
|
||||
max-width: 300px;
|
||||
width: 40vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
#selectCompanionScene h1 {
|
||||
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
||||
border-bottom: 1px solid #a6abaf;
|
||||
border-radius: 6px 6px 0 0;
|
||||
box-sizing: border-box;
|
||||
color: #727678;
|
||||
display: block;
|
||||
height: 43px;
|
||||
padding-top: 10px;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
text-shadow: 0 -1px 0 rgba(0,0,0,0.2), 0 1px 0 #fff;
|
||||
}
|
||||
#selectCompanionScene input {
|
||||
font-size: 70%;
|
||||
background: linear-gradient(top, #d6d7d7, #dee0e0);
|
||||
border: 1px solid #a1a3a3;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px #fff;
|
||||
box-sizing: border-box;
|
||||
color: #696969;
|
||||
height: 30px;
|
||||
transition: box-shadow 0.3s;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
#selectCompanionScene section {
|
||||
margin: 10px;
|
||||
}
|
||||
#selectCompanionScene section.action {
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
margin-top: 20vh;
|
||||
}
|
||||
#selectCompanionScene button {
|
||||
margin: 10px 4px;
|
||||
background-color: black;;
|
||||
color: #ebeeee;
|
||||
border-radius: 7px;
|
||||
padding-bottom: 4px;
|
||||
width: 100px;
|
||||
}
|
||||
#selectCompanionScene button#selectCompanionSceneFormCancel {
|
||||
background-color: #aca6a600;
|
||||
color: #292929;
|
||||
}
|
||||
#selectCompanionScene section h6,
|
||||
#selectCompanionScene section h5{
|
||||
margin: 1px;
|
||||
}
|
||||
#selectCompanionScene section.text-center{
|
||||
text-align: center;
|
||||
}
|
||||
#selectCompanionScene section a{
|
||||
font-size: 14px;
|
||||
text-decoration: underline;
|
||||
color: #ebeeee;
|
||||
}
|
||||
#selectCompanionScene section a:hover{
|
||||
font-weight: 700;
|
||||
}
|
||||
#selectCompanionScene section p{
|
||||
text-align: left;
|
||||
font-size: 8px;
|
||||
margin: 10px 10px;
|
||||
}
|
||||
#selectCompanionScene section p.err{
|
||||
color: red;
|
||||
text-align: center;
|
||||
}
|
||||
#selectCompanionScene section p.info{
|
||||
display: none;
|
||||
text-align: center;
|
||||
}
|
||||
#selectCompanionScene section input#selectCompanionSceneLink{
|
||||
background-color: #a1a3a3;
|
||||
}
|
||||
#selectCompanionScene section img{
|
||||
width: 160px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
#selectCompanionScene section button.selectCharacterButton{
|
||||
position: absolute;
|
||||
top: 20vh;
|
||||
margin: 0;
|
||||
width: 25px;
|
||||
}
|
||||
#selectCompanionScene section button.selectCharacterButton#selectCharacterButtonLeft{
|
||||
left: 1vw;
|
||||
}
|
||||
#selectCompanionScene section button.selectCharacterButton#selectCharacterButtonRight{
|
||||
right: 1vw;
|
||||
}
|
||||
#selectCompanionScene section button#selectCompanionSceneFormCustomYourOwnSubmit{
|
||||
font-size: 14px;
|
||||
width: auto;
|
||||
margin-top: -2px;
|
||||
background-color: #ffd700;
|
||||
color: black;
|
||||
}
|
||||
@media only screen and (max-width: 800px),
|
||||
only screen and (max-height: 600px) {
|
||||
#selectCompanionScene{
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<form id="selectCompanionScene" hidden>
|
||||
<section class="text-center">
|
||||
<h5>Select your WOKA</h5>
|
||||
<button class="selectCharacterButton" id="selectCharacterButtonLeft"> < </button>
|
||||
<button class="selectCharacterButton" id="selectCharacterButtonRight"> > </button>
|
||||
</section>
|
||||
<section class="action">
|
||||
<a herf="#" id="selectCompanionSceneFormBack">No companion</a>
|
||||
<button type="submit" id="selectCompanionSceneFormSubmit">Continue</button>
|
||||
</section>
|
||||
</form>
|
21
front/dist/resources/html/gameMenu.html
vendored
@ -1,4 +1,10 @@
|
||||
<style>
|
||||
*{
|
||||
font-family: PixelFont-7,monospace!important;
|
||||
}
|
||||
#gameMenu main{
|
||||
margin-top: 15px;
|
||||
}
|
||||
#gameMenu button {
|
||||
background-color: black;
|
||||
color: white;
|
||||
@ -16,6 +22,21 @@
|
||||
width: 32px;
|
||||
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
||||
}
|
||||
@media only screen and (max-height: 700px) {
|
||||
#gameMenu main {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 0;
|
||||
}
|
||||
#gameMenu section{
|
||||
margin: 2px;
|
||||
}
|
||||
section#socialLinks{
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="gameMenu" hidden>
|
||||
|
11
front/dist/resources/html/gameMenuIcon.html
vendored
@ -1,10 +1,12 @@
|
||||
<style>
|
||||
*{
|
||||
font-family: PixelFont-7,monospace!important;
|
||||
}
|
||||
#menuIcon button {
|
||||
background-color: black;
|
||||
color: white;
|
||||
border-radius: 7px;
|
||||
height: 28px;
|
||||
width: 34px;
|
||||
padding: 2px 8px;
|
||||
}
|
||||
#menuIcon button img{
|
||||
width: 14px;
|
||||
@ -14,6 +16,11 @@
|
||||
#menuIcon section {
|
||||
margin: 10px;
|
||||
}
|
||||
@media only screen and (max-height: 700px) {
|
||||
#menuIcon section {
|
||||
margin: 2px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<main id="menuIcon" hidden>
|
||||
<section>
|
||||
|
16
front/dist/resources/html/gameQualityMenu.html
vendored
@ -1,11 +1,14 @@
|
||||
<style>
|
||||
*{
|
||||
font-family: PixelFont-7,monospace!important;
|
||||
}
|
||||
#gameQuality {
|
||||
background: #eceeee;
|
||||
border: 1px solid #42464b;
|
||||
border-radius: 6px;
|
||||
height: 257px;
|
||||
margin: 20px auto 0;
|
||||
width: 298px;
|
||||
width: 50vw;
|
||||
max-width: 300px;
|
||||
}
|
||||
#gameQuality .cautiousText {
|
||||
font-size: 50%;
|
||||
@ -33,7 +36,7 @@
|
||||
color: #696969;
|
||||
height: 30px;
|
||||
transition: box-shadow 0.3s;
|
||||
width: 240px;
|
||||
width: 100%;
|
||||
}
|
||||
#gameQuality section {
|
||||
margin: 10px;
|
||||
@ -42,12 +45,11 @@
|
||||
text-align: center;
|
||||
}
|
||||
#gameQuality button {
|
||||
margin-top: 10px;
|
||||
margin: 10px;
|
||||
background-color: black;
|
||||
color: white;
|
||||
border-radius: 7px;
|
||||
padding-bottom: 4px;
|
||||
width: 60px;
|
||||
}
|
||||
#gameQuality button#gameQualityFormCancel {
|
||||
background-color: #c7c7c700;
|
||||
@ -57,7 +59,7 @@
|
||||
|
||||
<form id="gameQuality" hidden>
|
||||
<section>
|
||||
<h3>Game quality</h3>
|
||||
<h5>Game quality</h3>
|
||||
<p class="cautiousText">(Editing these settings will restart the game)</p>
|
||||
<select id="select-game-quality">
|
||||
<option value="120">High video quality (120 fps)</option>
|
||||
@ -67,7 +69,7 @@
|
||||
</select>
|
||||
</section>
|
||||
<section>
|
||||
<h3>Video quality</h3>
|
||||
<h5>Video quality</h3>
|
||||
<select id="select-video-quality">
|
||||
<option value="30">High video quality (30 fps)</option>
|
||||
<option value="20">Medium video quality (20 fps, recommended)</option>
|
||||
|
3
front/dist/resources/html/gameReport.html
vendored
@ -1,4 +1,7 @@
|
||||
<style>
|
||||
*{
|
||||
font-family: PixelFont-7,monospace!important;
|
||||
}
|
||||
#gameReport {
|
||||
background: #eceeee;
|
||||
border: 1px solid #42464b;
|
||||
|
11
front/dist/resources/html/gameShare.html
vendored
@ -1,11 +1,14 @@
|
||||
<style>
|
||||
*{
|
||||
font-family: PixelFont-7,monospace!important;
|
||||
}
|
||||
#gameShare {
|
||||
background: #eceeee;
|
||||
border: 1px solid #42464b;
|
||||
border-radius: 6px;
|
||||
margin: 20px auto 0;
|
||||
width: 298px;
|
||||
height: 160px;
|
||||
width: 50vw;
|
||||
max-width: 400px;
|
||||
}
|
||||
#gameShare h1 {
|
||||
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
||||
@ -40,7 +43,7 @@
|
||||
margin: 0;
|
||||
}
|
||||
#gameShare button {
|
||||
margin-top: 10px;
|
||||
margin: 10px;
|
||||
background-color: black;
|
||||
color: white;
|
||||
border-radius: 7px;
|
||||
@ -66,7 +69,7 @@
|
||||
}
|
||||
#gameShare section p{
|
||||
font-size: 8px;
|
||||
margin: 0px 70px;
|
||||
margin: 0;
|
||||
}
|
||||
#gameShare section p.err{
|
||||
color: red;
|
||||
|
@ -1,11 +1,17 @@
|
||||
<style>
|
||||
*{
|
||||
font-family: PixelFont-7,monospace!important;
|
||||
}
|
||||
#helpCameraSettings {
|
||||
background: #eceeee;
|
||||
border: 1px solid #42464b;
|
||||
border-radius: 6px;
|
||||
margin: 10px auto 0;
|
||||
margin: 25px auto 0;
|
||||
width: 400px;
|
||||
height: 370px;
|
||||
max-height: calc(48vh - 50px);
|
||||
max-width: 48vw;
|
||||
overflow: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
#helpCameraSettings h1 {
|
||||
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
||||
@ -20,18 +26,6 @@
|
||||
text-align: center;
|
||||
text-shadow: 0 -1px 0 rgba(0,0,0,0.2), 0 1px 0 #fff;
|
||||
}
|
||||
#helpCameraSettings input {
|
||||
font-size: 70%;
|
||||
background: linear-gradient(top, #d6d7d7, #dee0e0);
|
||||
border: 1px solid #a1a3a3;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px #fff;
|
||||
box-sizing: border-box;
|
||||
color: #696969;
|
||||
height: 30px;
|
||||
transition: box-shadow 0.3s;
|
||||
width: 100%;
|
||||
}
|
||||
#helpCameraSettings section {
|
||||
margin: 10px;
|
||||
}
|
||||
@ -40,7 +34,7 @@
|
||||
margin: 0;
|
||||
}
|
||||
#helpCameraSettings button {
|
||||
margin-top: 10px;
|
||||
margin: 10px 4px;
|
||||
background-color: black;
|
||||
color: white;
|
||||
border-radius: 7px;
|
||||
@ -51,9 +45,8 @@
|
||||
color: #292929;
|
||||
}
|
||||
#helpCameraSettings section a{
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
margin: 0 6px;
|
||||
text-decoration: underline;
|
||||
color: black;
|
||||
}
|
||||
#helpCameraSettings section h6,
|
||||
@ -67,6 +60,9 @@
|
||||
font-size: 8px;
|
||||
margin: 0px 20px;
|
||||
}
|
||||
#helpCameraSettings section p a{
|
||||
font-size: 8px;
|
||||
}
|
||||
#helpCameraSettings section p.err{
|
||||
color: #ff0000;
|
||||
}
|
||||
@ -81,6 +77,12 @@
|
||||
width: 200px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
@media only screen and (max-width: 800px),
|
||||
only screen and (max-height: 600px) {
|
||||
#helpCameraSettings{
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<form id="helpCameraSettings" hidden>
|
||||
@ -96,8 +98,12 @@
|
||||
<p>If you prefer to continue without allowing camera and microphone access, click on Continue</p>
|
||||
<p id='browserHelpSetting'></p>
|
||||
</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">
|
||||
<button type="submit" id="helpCameraSettingsFormRefresh">Refresh</button>
|
||||
<a href="#" id="helpCameraSettingsFormRefresh">Refresh</a>
|
||||
<button type="submit" id="helpCameraSettingsFormContinue">Continue</button>
|
||||
</section>
|
||||
</form>
|
||||
|
120
front/dist/resources/html/loginScene.html
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
<style>
|
||||
*{
|
||||
font-family: PixelFont-7,monospace!important;
|
||||
}
|
||||
#loginScene {
|
||||
background: #000000;
|
||||
/*border: 1px solid #ebeeee;*/
|
||||
border-radius: 6px;
|
||||
margin: 20px auto 0;
|
||||
width: 90%;
|
||||
max-width: 200px;
|
||||
color: #ebeeee;
|
||||
max-height: 40vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
#loginScene h1 {
|
||||
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
||||
border-bottom: 1px solid #a6abaf;
|
||||
border-radius: 6px 6px 0 0;
|
||||
box-sizing: border-box;
|
||||
color: #727678;
|
||||
display: block;
|
||||
height: 43px;
|
||||
padding-top: 10px;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
text-shadow: 0 -1px 0 rgba(0,0,0,0.2), 0 1px 0 #fff;
|
||||
}
|
||||
#loginScene input {
|
||||
font-size: 70%;
|
||||
background: linear-gradient(top, #d6d7d7, #dee0e0);
|
||||
border: 1px solid #a1a3a3;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px #fff;
|
||||
box-sizing: border-box;
|
||||
color: #696969;
|
||||
height: 30px;
|
||||
transition: box-shadow 0.3s;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
#loginScene section {
|
||||
margin: 10px;
|
||||
}
|
||||
#loginScene section.action{
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
#loginScene button {
|
||||
margin: 10px;
|
||||
background-color: black;;
|
||||
color: #ebeeee;
|
||||
border-radius: 7px;
|
||||
padding-bottom: 4px;
|
||||
width: 100px;
|
||||
}
|
||||
#loginScene button#loginSceneFormCancel {
|
||||
background-color: #c7c7c700;
|
||||
color: #292929;
|
||||
}
|
||||
#loginScene section h6,
|
||||
#loginScene section h5{
|
||||
margin: 1px;
|
||||
}
|
||||
#loginScene section.text-center{
|
||||
text-align: center;
|
||||
}
|
||||
#loginScene section a{
|
||||
font-size: 8px;
|
||||
text-decoration: underline;
|
||||
color: #ebeeee;
|
||||
}
|
||||
#loginScene section a:hover{
|
||||
font-weight: 700;
|
||||
}
|
||||
#loginScene section p{
|
||||
text-align: left;
|
||||
font-size: 8px;
|
||||
margin: 10px 10px;
|
||||
}
|
||||
#loginScene section p.err{
|
||||
color: red;
|
||||
text-align: center;
|
||||
}
|
||||
#loginScene section p.info{
|
||||
display: none;
|
||||
text-align: center;
|
||||
}
|
||||
#loginScene section input#loginSceneLink{
|
||||
background-color: #a1a3a3;
|
||||
}
|
||||
#loginScene section img{
|
||||
width: 160px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
@media only screen and (max-width: 800px),
|
||||
only screen and (max-height: 600px) {
|
||||
#loginScene{
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<form id="loginScene" hidden>
|
||||
<section class="text-center">
|
||||
<img src="resources/logos/logo.png">
|
||||
</section>
|
||||
<section class="text-center">
|
||||
<h5>Enter your name</h5>
|
||||
<p class="info">9 chars maximum</p>
|
||||
<p class="err" id="errorLoginScene"></p>
|
||||
</section>
|
||||
<section>
|
||||
<input type="text" name="email" id="loginSceneName">
|
||||
<p>By continuing, you are agreeing our <a href="https://workadventu.re/terms-of-use" target="_blank">terms of use</a>, <a href="https://workadventu.re/privacy-policy" target="_blank">privacy policy</a> and <a href="https://workadventu.re/cookie-policy" target="_blank">cookie policy</a>.</p>
|
||||
</section>
|
||||
<section class="action">
|
||||
<button type="submit" id="loginSceneFormSubmit">Continue</button>
|
||||
</section>
|
||||
</form>
|
142
front/dist/resources/html/selectCharacterScene.html
vendored
Normal file
@ -0,0 +1,142 @@
|
||||
<style>
|
||||
*{
|
||||
font-family: PixelFont-7,monospace!important;
|
||||
}
|
||||
#selectCharacterScene {
|
||||
background: #0000;
|
||||
/*border: 1px solid #ebeeee;*/
|
||||
border-radius: 6px;
|
||||
margin: 10px auto 0;
|
||||
color: #ebeeee;
|
||||
max-height: 48vh;
|
||||
max-width: 300px;
|
||||
width: 40vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
#selectCharacterScene h1 {
|
||||
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
|
||||
border-bottom: 1px solid #a6abaf;
|
||||
border-radius: 6px 6px 0 0;
|
||||
box-sizing: border-box;
|
||||
color: #727678;
|
||||
display: block;
|
||||
height: 43px;
|
||||
padding-top: 10px;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
text-shadow: 0 -1px 0 rgba(0,0,0,0.2), 0 1px 0 #fff;
|
||||
}
|
||||
#selectCharacterScene input {
|
||||
font-size: 70%;
|
||||
background: linear-gradient(top, #d6d7d7, #dee0e0);
|
||||
border: 1px solid #a1a3a3;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px #fff;
|
||||
box-sizing: border-box;
|
||||
color: #696969;
|
||||
height: 30px;
|
||||
transition: box-shadow 0.3s;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
#selectCharacterScene section {
|
||||
margin: 10px;
|
||||
}
|
||||
#selectCharacterScene section.action {
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
margin-top: 28vh;
|
||||
}
|
||||
#selectCharacterScene button {
|
||||
margin: 10px 0px;
|
||||
background-color: black;;
|
||||
color: #ebeeee;
|
||||
border-radius: 7px;
|
||||
padding-bottom: 4px;
|
||||
width: 100px;
|
||||
}
|
||||
#selectCharacterScene button#selectCharacterSceneFormCancel {
|
||||
background-color: #aca6a600;
|
||||
color: #292929;
|
||||
}
|
||||
#selectCharacterScene section h6,
|
||||
#selectCharacterScene section h5{
|
||||
margin: 1px;
|
||||
}
|
||||
#selectCharacterScene section.text-center{
|
||||
text-align: center;
|
||||
}
|
||||
#selectCharacterScene section a{
|
||||
font-size: 8px;
|
||||
text-decoration: underline;
|
||||
color: #ebeeee;
|
||||
}
|
||||
#selectCharacterScene section a:hover{
|
||||
font-weight: 700;
|
||||
}
|
||||
#selectCharacterScene section p{
|
||||
text-align: left;
|
||||
font-size: 8px;
|
||||
margin: 10px 10px;
|
||||
}
|
||||
#selectCharacterScene section p.err{
|
||||
color: red;
|
||||
text-align: center;
|
||||
}
|
||||
#selectCharacterScene section p.info{
|
||||
display: none;
|
||||
text-align: center;
|
||||
}
|
||||
#selectCharacterScene section input#selectCharacterSceneLink{
|
||||
background-color: #a1a3a3;
|
||||
}
|
||||
#selectCharacterScene section img{
|
||||
width: 160px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
#selectCharacterScene section button.selectCharacterButton{
|
||||
position: absolute;
|
||||
top: 20vh;
|
||||
margin: 0;
|
||||
width: 25px;
|
||||
}
|
||||
#selectCharacterScene section button.selectCharacterButton#selectCharacterButtonLeft{
|
||||
display: none;
|
||||
left: 1vw;
|
||||
}
|
||||
#selectCharacterScene section button.selectCharacterButton#selectCharacterButtonRight{
|
||||
display: none;
|
||||
right: 1vw;
|
||||
}
|
||||
#selectCharacterScene section button#selectCharacterSceneFormCustomYourOwnSubmit{
|
||||
font-size: 14px;
|
||||
width: auto;
|
||||
margin-top: -2px;
|
||||
background-color: #ffd700;
|
||||
color: black;
|
||||
}
|
||||
@media only screen and (max-width: 800px),
|
||||
only screen and (max-height: 600px) {
|
||||
#selectCharacterScene{
|
||||
overflow-y: scroll;
|
||||
}
|
||||
#selectCharacterScene section button.selectCharacterButton#selectCharacterButtonRight{
|
||||
display: block;
|
||||
}
|
||||
#selectCharacterScene section button.selectCharacterButton#selectCharacterButtonLeft{
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<form id="selectCharacterScene" hidden>
|
||||
<section class="text-center">
|
||||
<h5>Select your WOKA</h5>
|
||||
<button class="selectCharacterButton" id="selectCharacterButtonLeft"> < </button>
|
||||
<button class="selectCharacterButton" id="selectCharacterButtonRight"> > </button>
|
||||
</section>
|
||||
<section class="action">
|
||||
<button type="submit" id="selectCharacterSceneFormSubmit">Continue</button>
|
||||
<button type="submit" id="selectCharacterSceneFormCustomYourOwnSubmit">Custom your WOKA</button>
|
||||
</section>
|
||||
</form>
|
@ -1,4 +1,7 @@
|
||||
<style>
|
||||
*{
|
||||
font-family: PixelFont-7,monospace!important;
|
||||
}
|
||||
#warningMain {
|
||||
border-radius: 5px;
|
||||
height: 100px;
|
||||
|
BIN
front/dist/resources/objects/play_button.png
vendored
Before Width: | Height: | Size: 969 B |
49
front/dist/resources/style/cowebsite-mobile.scss
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
@media (max-aspect-ratio: 1/1) {
|
||||
|
||||
#main-container {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
|
||||
#cowebsite {
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
|
||||
&.loading {
|
||||
transform: translateY(-90%);
|
||||
}
|
||||
&.hidden {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
main {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
aside {
|
||||
height: 30px;
|
||||
cursor: ns-resize;
|
||||
flex-direction: column;
|
||||
|
||||
img {
|
||||
cursor: ns-resize;
|
||||
}
|
||||
}
|
||||
|
||||
.top-right-btn {
|
||||
&#cowebsite-close {
|
||||
right: 0;
|
||||
}
|
||||
&#cowebsite-fullscreen {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
48
front/dist/resources/style/cowebsite.scss
vendored
@ -87,51 +87,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (max-aspect-ratio: 1/1) {
|
||||
|
||||
#main-container {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
|
||||
#cowebsite {
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
|
||||
&.loading {
|
||||
transform: translateY(-90%);
|
||||
}
|
||||
&.hidden {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
main {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
aside {
|
||||
height: 30px;
|
||||
cursor: ns-resize;
|
||||
flex-direction: column;
|
||||
|
||||
img {
|
||||
cursor: ns-resize;
|
||||
}
|
||||
}
|
||||
|
||||
.top-right-btn {
|
||||
&#cowebsite-close {
|
||||
right: 0px;
|
||||
}
|
||||
&#cowebsite-fullscreen {
|
||||
right: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
2
front/dist/resources/style/index.scss
vendored
@ -1,2 +1,4 @@
|
||||
@import "cowebsite.scss";
|
||||
@import "cowebsite-mobile.scss";
|
||||
@import "style.css";
|
||||
@import "mobile-style.scss";
|
49
front/dist/resources/style/mobile-style.scss
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
@media screen and (max-width: 700px),
|
||||
screen and (max-height: 700px){
|
||||
video#myCamVideo {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 20%;
|
||||
min-width: 200px;
|
||||
position: absolute;
|
||||
display: block;
|
||||
right: 0;
|
||||
height: 80%;
|
||||
|
||||
&> div {
|
||||
max-height: 120px;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.video-container{
|
||||
min-width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-cam-action {
|
||||
min-width: 150px;
|
||||
|
||||
&:hover{
|
||||
transform: translateY(20px);
|
||||
}
|
||||
div {
|
||||
margin: 0 1%;
|
||||
&:hover {
|
||||
background-color: #666;
|
||||
}
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.main-section {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
min-width: 400px;
|
||||
|
||||
& > div {
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
}
|
114
front/dist/resources/style/style.css
vendored
@ -53,6 +53,7 @@ body .message-info.warning{
|
||||
padding-top: 32px;
|
||||
font-size: 28px;
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.video-container img{
|
||||
@ -97,7 +98,7 @@ body .message-info.warning{
|
||||
}
|
||||
|
||||
.video-container button.report:hover {
|
||||
width: 150px;
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.video-container button.report img{
|
||||
@ -125,6 +126,7 @@ body .message-info.warning{
|
||||
|
||||
.video-container video{
|
||||
height: 100%;
|
||||
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
||||
}
|
||||
|
||||
.video-container video:focus{
|
||||
@ -140,6 +142,7 @@ body .message-info.warning{
|
||||
right: 15px;
|
||||
bottom: 30px;
|
||||
border-radius: 15px 15px 15px 15px;
|
||||
max-height: 20%;
|
||||
}
|
||||
|
||||
video#myCamVideo{
|
||||
@ -151,19 +154,60 @@ video#myCamVideo{
|
||||
/*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 {
|
||||
pointer-events: all;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
width: 450px;
|
||||
height: 150px;
|
||||
display: inline-flex;
|
||||
bottom: 10px;
|
||||
right: 15px;
|
||||
width: 15vw;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
}
|
||||
/*btn animation*/
|
||||
.btn-cam-action div{
|
||||
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
||||
position: absolute;
|
||||
/*position: absolute;*/
|
||||
border: solid 0px black;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
@ -172,7 +216,8 @@ video#myCamVideo{
|
||||
border-radius: 48px;
|
||||
transform: translateY(20px);
|
||||
transition-timing-function: ease-in-out;
|
||||
bottom: 20px;
|
||||
margin-bottom: 20px;
|
||||
margin: 0 4%;
|
||||
}
|
||||
.btn-cam-action div.disabled {
|
||||
background: #d75555;
|
||||
@ -191,17 +236,17 @@ video#myCamVideo{
|
||||
.btn-micro{
|
||||
pointer-events: auto;
|
||||
transition: all .3s;
|
||||
right: 44px;
|
||||
/*right: 44px;*/
|
||||
}
|
||||
.btn-video{
|
||||
pointer-events: auto;
|
||||
transition: all .25s;
|
||||
right: 134px;
|
||||
/*right: 134px;*/
|
||||
}
|
||||
.btn-monitor{
|
||||
pointer-events: auto;
|
||||
transition: all .2s;
|
||||
right: 224px;
|
||||
/*right: 224px;*/
|
||||
}
|
||||
.btn-copy{
|
||||
pointer-events: auto;
|
||||
@ -338,24 +383,6 @@ body {
|
||||
|
||||
|
||||
}
|
||||
@media (max-aspect-ratio: 1/1) {
|
||||
.game-overlay {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.sidebar > div {
|
||||
max-width: 21%;
|
||||
}
|
||||
|
||||
.sidebar > div:hover {
|
||||
max-width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
#game {
|
||||
width: 100%;
|
||||
@ -513,7 +540,7 @@ input[type=range]:focus::-ms-fill-upper {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
pointer-events: all;
|
||||
/* TODO: DO WE NEED FLEX HERE???? WE WANT A SIDEBAR OF EXACTLY 25% (note: flex useful for direction!!!) */
|
||||
}
|
||||
|
||||
@ -549,7 +576,7 @@ input[type=range]:focus::-ms-fill-upper {
|
||||
.sidebar {
|
||||
flex: 0 0 25%;
|
||||
display: flex;
|
||||
pointer-events: none;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.sidebar > div {
|
||||
@ -563,6 +590,10 @@ input[type=range]:focus::-ms-fill-upper {
|
||||
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 */
|
||||
.media-container {
|
||||
display: flex;
|
||||
@ -1046,7 +1077,7 @@ div.modal-report-user{
|
||||
|
||||
.discussion .messages{
|
||||
position: absolute;
|
||||
height: calc(100% - 360px);
|
||||
height: calc(100% - 390px);
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
max-width: calc(100% - 40px);
|
||||
@ -1127,17 +1158,34 @@ div.action{
|
||||
animation-iteration-count: infinite;
|
||||
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{
|
||||
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
||||
padding: 10px;
|
||||
background-color: #2d2d2dba;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
max-width: 250px;
|
||||
margin-left: calc(50% - 125px);
|
||||
max-width: 350px;
|
||||
margin-left: calc(50% - 175px);
|
||||
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{
|
||||
font-family: 'Press Start 2P';
|
||||
text-align: left;
|
||||
|
186
front/dist/static/images/favicons/manifest.json
vendored
@ -1,41 +1,149 @@
|
||||
{
|
||||
"name": "App",
|
||||
"icons": [
|
||||
{
|
||||
"src": "\/android-icon-36x36.png",
|
||||
"sizes": "36x36",
|
||||
"type": "image\/png",
|
||||
"density": "0.75"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-48x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image\/png",
|
||||
"density": "1.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image\/png",
|
||||
"density": "1.5"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image\/png",
|
||||
"density": "2.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image\/png",
|
||||
"density": "3.0"
|
||||
},
|
||||
{
|
||||
"src": "\/android-icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image\/png",
|
||||
"density": "4.0"
|
||||
}
|
||||
]
|
||||
"short_name": "WA",
|
||||
"name": "WorkAdventure",
|
||||
"icons": [
|
||||
{
|
||||
"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",
|
||||
"type": "image\/png",
|
||||
"density": "0.75"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/favicons/android-icon-48x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image\/png",
|
||||
"density": "1.0"
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"type": "image\/png",
|
||||
"density": "1.5"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/favicons/android-icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image\/png",
|
||||
"density": "2.0"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/favicons/android-icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image\/png",
|
||||
"density": "3.0"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/favicons/android-icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image\/png",
|
||||
"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"
|
||||
}]
|
||||
}
|
@ -33,7 +33,7 @@
|
||||
"phaser": "3.24.1",
|
||||
"phaser3-rex-plugins": "^1.1.42",
|
||||
"queue-typescript": "^1.0.1",
|
||||
"quill": "^1.3.7",
|
||||
"quill": "1.3.6",
|
||||
"rxjs": "^6.6.3",
|
||||
"simple-peer": "^9.6.2",
|
||||
"socket.io-client": "^2.3.0",
|
||||
|
@ -2,7 +2,6 @@ import {HtmlUtils} from "../WebRtc/HtmlUtils";
|
||||
import {UserInputManager} from "../Phaser/UserInput/UserInputManager";
|
||||
import {RoomConnection} from "../Connexion/RoomConnection";
|
||||
import {PlayGlobalMessageInterface} from "../Connexion/ConnexionModels";
|
||||
import {ADMIN_URL} from "../Enum/EnvironmentVariable";
|
||||
import {AdminMessageEventTypes} from "../Connexion/AdminMessagesService";
|
||||
|
||||
export const CLASS_CONSOLE_MESSAGE = 'main-console';
|
||||
@ -162,42 +161,46 @@ export class ConsoleGlobalMessageManager {
|
||||
this.divMessageConsole.appendChild(section);
|
||||
|
||||
(async () => {
|
||||
// Start loading CSS
|
||||
const cssPromise = ConsoleGlobalMessageManager.loadCss();
|
||||
// Import quill
|
||||
const Quill:any = await import("quill"); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
// Wait for CSS to be loaded
|
||||
await cssPromise;
|
||||
try{
|
||||
// Start loading CSS
|
||||
const cssPromise = ConsoleGlobalMessageManager.loadCss();
|
||||
// Import quill
|
||||
const {default: Quill}:any = await import("quill"); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
// Wait for CSS to be loaded
|
||||
await cssPromise;
|
||||
|
||||
const toolbarOptions = [
|
||||
['bold', 'italic', 'underline', 'strike'], // toggled buttons
|
||||
['blockquote', 'code-block'],
|
||||
const toolbarOptions = [
|
||||
['bold', 'italic', 'underline', 'strike'], // toggled buttons
|
||||
['blockquote', 'code-block'],
|
||||
|
||||
[{'header': 1}, {'header': 2}], // custom button values
|
||||
[{'list': 'ordered'}, {'list': 'bullet'}],
|
||||
[{'script': 'sub'}, {'script': 'super'}], // superscript/subscript
|
||||
[{'indent': '-1'}, {'indent': '+1'}], // outdent/indent
|
||||
[{'direction': 'rtl'}], // text direction
|
||||
[{'header': 1}, {'header': 2}], // custom button values
|
||||
[{'list': 'ordered'}, {'list': 'bullet'}],
|
||||
[{'script': 'sub'}, {'script': 'super'}], // superscript/subscript
|
||||
[{'indent': '-1'}, {'indent': '+1'}], // outdent/indent
|
||||
[{'direction': 'rtl'}], // text direction
|
||||
|
||||
[{'size': ['small', false, 'large', 'huge']}], // custom dropdown
|
||||
[{'header': [1, 2, 3, 4, 5, 6, false]}],
|
||||
[{'size': ['small', false, 'large', 'huge']}], // custom dropdown
|
||||
[{'header': [1, 2, 3, 4, 5, 6, false]}],
|
||||
|
||||
[{'color': []}, {'background': []}], // dropdown with defaults from theme
|
||||
[{'font': []}],
|
||||
[{'align': []}],
|
||||
[{'color': []}, {'background': []}], // dropdown with defaults from theme
|
||||
[{'font': []}],
|
||||
[{'align': []}],
|
||||
|
||||
['clean'],
|
||||
['clean'],
|
||||
|
||||
['link', 'image', 'video']
|
||||
// remove formatting button
|
||||
];
|
||||
['link', 'image', 'video']
|
||||
// remove formatting button
|
||||
];
|
||||
|
||||
new Quill(`#${INPUT_CONSOLE_MESSAGE}`, {
|
||||
theme: 'snow',
|
||||
modules: {
|
||||
toolbar: toolbarOptions
|
||||
},
|
||||
});
|
||||
new Quill(`#${INPUT_CONSOLE_MESSAGE}`, {
|
||||
theme: 'snow',
|
||||
modules: {
|
||||
toolbar: toolbarOptions
|
||||
},
|
||||
});
|
||||
}catch(err){
|
||||
console.error(err);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,8 @@ import {
|
||||
SendJitsiJwtMessage,
|
||||
CharacterLayerMessage,
|
||||
PingMessage,
|
||||
SendUserMessage, BanUserMessage
|
||||
SendUserMessage,
|
||||
BanUserMessage
|
||||
} from "../Messages/generated/messages_pb"
|
||||
|
||||
import {UserSimplePeerInterface} from "../WebRtc/SimplePeer";
|
||||
@ -169,7 +170,10 @@ export class RoomConnection implements RoomConnection {
|
||||
} else if (message.hasWorldfullmessage()) {
|
||||
worldFullMessageStream.onMessage();
|
||||
this.closed = true;
|
||||
} else if (message.hasWebrtcsignaltoclientmessage()) {
|
||||
} else if (message.hasWorldconnexionmessage()) {
|
||||
worldFullMessageStream.onMessage(message.getWorldconnexionmessage()?.getMessage());
|
||||
this.closed = true;
|
||||
}else if (message.hasWebrtcsignaltoclientmessage()) {
|
||||
this.dispatch(EventMessage.WEBRTC_SIGNAL, message.getWebrtcsignaltoclientmessage());
|
||||
} else if (message.hasWebrtcscreensharingsignaltoclientmessage()) {
|
||||
this.dispatch(EventMessage.WEBRTC_SCREEN_SHARING_SIGNAL, message.getWebrtcscreensharingsignaltoclientmessage());
|
||||
|
@ -2,12 +2,12 @@ import {Subject} from "rxjs";
|
||||
|
||||
class WorldFullMessageStream {
|
||||
|
||||
private _stream:Subject<void> = new Subject();
|
||||
private _stream:Subject<string|null> = new Subject<string|null>();
|
||||
public stream = this._stream.asObservable();
|
||||
|
||||
|
||||
onMessage() {
|
||||
this._stream.next();
|
||||
onMessage(message? :string) {
|
||||
this._stream.next(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,8 @@ const MAX_EXTRAPOLATION_TIME = 100; // Extrapolate a maximum of 250ms if no new
|
||||
export const MAX_USERNAME_LENGTH = parseInt(process.env.MAX_USERNAME_LENGTH || '') || 8;
|
||||
export const MAX_PER_GROUP = parseInt(process.env.MAX_PER_GROUP || '4');
|
||||
|
||||
export const isMobile = ():boolean => ( ( window.innerWidth <= 800 ) || ( window.innerHeight <= 600 ) );
|
||||
|
||||
export {
|
||||
DEBUG_MODE,
|
||||
START_ROOM_URL,
|
||||
|
53
front/src/Phaser/Components/TextUtils.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import {ITiledMapObject} from "../Map/ITiledMap";
|
||||
import Text = Phaser.GameObjects.Text;
|
||||
import {GameScene} from "../Game/GameScene";
|
||||
import TextStyle = Phaser.GameObjects.TextStyle;
|
||||
|
||||
export class TextUtils {
|
||||
public static createTextFromITiledMapObject(scene: GameScene, object: ITiledMapObject): void {
|
||||
if (object.text === undefined) {
|
||||
throw new Error('This object has not textual representation.');
|
||||
}
|
||||
const options: {
|
||||
fontStyle?: string,
|
||||
fontSize?: string,
|
||||
fontFamily?: string,
|
||||
color?: string,
|
||||
align?: string,
|
||||
wordWrap?: {
|
||||
width: number,
|
||||
useAdvancedWrap?: boolean
|
||||
}
|
||||
} = {};
|
||||
if (object.text.italic) {
|
||||
options.fontStyle = 'italic';
|
||||
}
|
||||
// Note: there is no support for "strikeout" and "underline"
|
||||
let fontSize: number = 16;
|
||||
if (object.text.pixelsize) {
|
||||
fontSize = object.text.pixelsize;
|
||||
}
|
||||
options.fontSize = fontSize + 'px';
|
||||
if (object.text.fontfamily) {
|
||||
options.fontFamily = '"'+object.text.fontfamily+'"';
|
||||
}
|
||||
let color = '#000000';
|
||||
if (object.text.color !== undefined) {
|
||||
color = object.text.color;
|
||||
}
|
||||
options.color = color;
|
||||
if (object.text.wrap === true) {
|
||||
options.wordWrap = {
|
||||
width: object.width,
|
||||
//useAdvancedWrap: true
|
||||
}
|
||||
}
|
||||
if (object.text.halign !== undefined) {
|
||||
options.align = object.text.halign;
|
||||
}
|
||||
|
||||
console.warn(options);
|
||||
const textElem = scene.add.text(object.x, object.y, object.text.text, options);
|
||||
textElem.setAngle(object.rotation);
|
||||
}
|
||||
}
|
@ -89,10 +89,7 @@ export class GameManager {
|
||||
console.log('starting '+ (this.currentGameSceneName || this.startRoom.id))
|
||||
scenePlugin.start(this.currentGameSceneName || this.startRoom.id);
|
||||
scenePlugin.launch(MenuSceneName);
|
||||
|
||||
if (!localUserStore.getHelpCameraSettingsShown()) {
|
||||
scenePlugin.launch(HelpCameraSettingsSceneName);//700
|
||||
}
|
||||
scenePlugin.launch(HelpCameraSettingsSceneName);//700
|
||||
}
|
||||
|
||||
public gameSceneIsCreated(scene: GameScene) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import {ITiledMap} from "../Map/ITiledMap";
|
||||
import {ITiledMap, ITiledMapLayer} from "../Map/ITiledMap";
|
||||
import {LayersIterator} from "../Map/LayersIterator";
|
||||
|
||||
export type PropertyChangeCallback = (newValue: string | number | boolean | undefined, oldValue: string | number | boolean | undefined, allProps: Map<string, string | boolean | number>) => void;
|
||||
|
||||
@ -10,8 +11,10 @@ export class GameMap {
|
||||
private key: number|undefined;
|
||||
private lastProperties = new Map<string, string|boolean|number>();
|
||||
private callbacks = new Map<string, Array<PropertyChangeCallback>>();
|
||||
public readonly layersIterator: LayersIterator;
|
||||
|
||||
public constructor(private map: ITiledMap) {
|
||||
this.layersIterator = new LayersIterator(map);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,7 +58,7 @@ export class GameMap {
|
||||
private getProperties(key: number): Map<string, string|boolean|number> {
|
||||
const properties = new Map<string, string|boolean|number>();
|
||||
|
||||
for (const layer of this.map.layers) {
|
||||
for (const layer of this.layersIterator) {
|
||||
if (layer.type !== 'tilelayer') {
|
||||
continue;
|
||||
}
|
||||
|
@ -18,7 +18,15 @@ import {
|
||||
RESOLUTION,
|
||||
ZOOM_LEVEL
|
||||
} from "../../Enum/EnvironmentVariable";
|
||||
import {ITiledMap, ITiledMapLayer, ITiledMapLayerProperty, ITiledMapObject, ITiledTileSet} from "../Map/ITiledMap";
|
||||
import {
|
||||
ITiledMap,
|
||||
ITiledMapLayer,
|
||||
ITiledMapLayerProperty,
|
||||
ITiledMapObject,
|
||||
ITiledText,
|
||||
ITiledMapTileLayer,
|
||||
ITiledTileSet
|
||||
} from "../Map/ITiledMap";
|
||||
import {AddPlayerInterface} from "./AddPlayerInterface";
|
||||
import {PlayerAnimationDirections} from "../Player/Animation";
|
||||
import {PlayerMovement} from "./PlayerMovement";
|
||||
@ -78,6 +86,7 @@ import DOMElement = Phaser.GameObjects.DOMElement;
|
||||
import {Subscription} from "rxjs";
|
||||
import {worldFullMessageStream} from "../../Connexion/WorldFullMessageStream";
|
||||
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
|
||||
import {TextUtils} from "../Components/TextUtils";
|
||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||
import {PinchManager} from "../UserInput/PinchManager";
|
||||
import {joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey} from "../Components/MobileJoystick";
|
||||
@ -137,7 +146,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
pendingEvents: Queue<InitUserPositionEventInterface|AddPlayerEventInterface|RemovePlayerEventInterface|UserMovedEventInterface|GroupCreatedUpdatedEventInterface|DeleteGroupEventInterface> = new Queue<InitUserPositionEventInterface|AddPlayerEventInterface|RemovePlayerEventInterface|UserMovedEventInterface|GroupCreatedUpdatedEventInterface|DeleteGroupEventInterface>();
|
||||
private initPosition: PositionInterface|null = null;
|
||||
private playersPositionInterpolator = new PlayersPositionInterpolator();
|
||||
public connection!: RoomConnection;
|
||||
public connection: RoomConnection|undefined;
|
||||
private simplePeer!: SimplePeer;
|
||||
private GlobalMessageManager!: GlobalMessageManager;
|
||||
public ConsoleGlobalMessageManager!: ConsoleGlobalMessageManager;
|
||||
@ -201,7 +210,6 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
|
||||
//hook preload scene
|
||||
preload(): void {
|
||||
addLoader(this);
|
||||
const localUser = localUserStore.getLocalUser();
|
||||
const textures = localUser?.textures;
|
||||
if (textures) {
|
||||
@ -261,6 +269,9 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
|
||||
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 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.
|
||||
@ -369,7 +380,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
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();
|
||||
if (!playerName) {
|
||||
@ -392,8 +403,9 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
|
||||
//add layer on map
|
||||
this.Layers = new Array<Phaser.Tilemaps.StaticTilemapLayer>();
|
||||
|
||||
let depth = -2;
|
||||
for (const layer of this.mapFile.layers) {
|
||||
for (const layer of this.gameMap.layersIterator) {
|
||||
if (layer.type === 'tilelayer') {
|
||||
this.addLayer(this.Map.createStaticLayer(layer.name, this.Terrains, 0, 0).setDepth(depth));
|
||||
|
||||
@ -409,9 +421,16 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
if (layer.type === 'objectgroup' && layer.name === 'floorLayer') {
|
||||
depth = 10000;
|
||||
}
|
||||
if (layer.type === 'objectgroup') {
|
||||
for (const object of layer.objects) {
|
||||
if (object.text) {
|
||||
TextUtils.createTextFromITiledMapObject(this, object);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (depth === -2) {
|
||||
throw new Error('Your map MUST contain a layer of type "objectgroup" whose name is "floorLayer" that represents the layer characters are drawn at.');
|
||||
throw new Error('Your map MUST contain a layer of type "objectgroup" whose name is "floorLayer" that represents the layer characters are drawn at. This layer cannot be contained in a group.');
|
||||
}
|
||||
|
||||
this.initStartXAndStartY();
|
||||
@ -424,8 +443,8 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
|
||||
|
||||
//create input to move
|
||||
mediaManager.setUserInputManager(this.userInputManager);
|
||||
this.userInputManager = new UserInputManager(this);
|
||||
mediaManager.setUserInputManager(this.userInputManager);
|
||||
|
||||
if (localUserStore.getFullscreen()) {
|
||||
document.querySelector('body')?.requestFullscreen();
|
||||
@ -718,7 +737,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
if (JITSI_PRIVATE_MODE && !jitsiUrl) {
|
||||
const adminTag = allProps.get("jitsiRoomAdminTag") as string|undefined;
|
||||
|
||||
this.connection.emitQueryJitsiJwtMessage(roomName, adminTag);
|
||||
this.connection?.emitQueryJitsiJwtMessage(roomName, adminTag);
|
||||
} else {
|
||||
this.startJitsi(roomName, undefined);
|
||||
}
|
||||
@ -741,9 +760,9 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
});
|
||||
this.gameMap.onPropertyChange('silent', (newValue, oldValue) => {
|
||||
if (newValue === undefined || newValue === false || newValue === '') {
|
||||
this.connection.setSilent(false);
|
||||
this.connection?.setSilent(false);
|
||||
} else {
|
||||
this.connection.setSilent(true);
|
||||
this.connection?.setSilent(true);
|
||||
}
|
||||
});
|
||||
this.gameMap.onPropertyChange('playAudio', (newValue, oldValue, allProps) => {
|
||||
@ -898,7 +917,7 @@ ${escapedMessage}
|
||||
audioManager.unloadAudio();
|
||||
// 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.simplePeer.closeAllConnections();
|
||||
this.simplePeer?.closeAllConnections();
|
||||
this.simplePeer?.unregister();
|
||||
this.messageSubscription?.unsubscribe();
|
||||
this.userInputManager.destroy();
|
||||
@ -964,13 +983,14 @@ ${escapedMessage}
|
||||
}
|
||||
|
||||
private initPositionFromLayerName(layerName: string) {
|
||||
for (const layer of this.mapFile.layers) {
|
||||
if (layerName === layer.name && layer.type === 'tilelayer' && (layerName === defaultStartLayerName || this.isStartLayer(layer))) {
|
||||
for (const layer of this.gameMap.layersIterator) {
|
||||
if ((layerName === layer.name || layer.name.endsWith('/'+layerName)) && layer.type === 'tilelayer' && (layerName === defaultStartLayerName || this.isStartLayer(layer))) {
|
||||
const startPosition = this.startUser(layer);
|
||||
this.startX = startPosition.x + this.mapFile.tilewidth/2;
|
||||
this.startY = startPosition.y + this.mapFile.tileheight/2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private getExitUrl(layer: ITiledMapLayer): string|undefined {
|
||||
@ -993,7 +1013,7 @@ ${escapedMessage}
|
||||
}
|
||||
|
||||
private getProperty(layer: ITiledMapLayer|ITiledMap, name: string): string|boolean|number|undefined {
|
||||
const properties: ITiledMapLayerProperty[] = layer.properties;
|
||||
const properties: ITiledMapLayerProperty[]|undefined = layer.properties;
|
||||
if (!properties) {
|
||||
return undefined;
|
||||
}
|
||||
@ -1005,7 +1025,7 @@ ${escapedMessage}
|
||||
}
|
||||
|
||||
private getProperties(layer: ITiledMapLayer|ITiledMap, name: string): (string|number|boolean|undefined)[] {
|
||||
const properties: ITiledMapLayerProperty[] = layer.properties;
|
||||
const properties: ITiledMapLayerProperty[]|undefined = layer.properties;
|
||||
if (!properties) {
|
||||
return [];
|
||||
}
|
||||
@ -1019,7 +1039,7 @@ ${escapedMessage}
|
||||
await gameManager.loadMap(room, this.scene);
|
||||
}
|
||||
|
||||
private startUser(layer: ITiledMapLayer): PositionInterface {
|
||||
private startUser(layer: ITiledMapTileLayer): PositionInterface {
|
||||
const tiles = layer.data;
|
||||
if (typeof(tiles) === 'string') {
|
||||
throw new Error('The content of a JSON map must be filled as a JSON array, not as a string');
|
||||
@ -1175,7 +1195,7 @@ ${escapedMessage}
|
||||
this.lastMoveEventSent = event;
|
||||
this.lastSentTick = this.currentTick;
|
||||
const camera = this.cameras.main;
|
||||
this.connection.sharePosition(event.x, event.y, event.direction, event.moving, {
|
||||
this.connection?.sharePosition(event.x, event.y, event.direction, event.moving, {
|
||||
left: camera.scrollX,
|
||||
top: camera.scrollY,
|
||||
right: camera.scrollX + camera.width,
|
||||
@ -1188,7 +1208,7 @@ ${escapedMessage}
|
||||
* @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 {
|
||||
mediaManager.setLastUpdateScene();
|
||||
mediaManager.updateScene();
|
||||
this.currentTick = time;
|
||||
this.CurrentPlayer.moveUser(delta);
|
||||
|
||||
@ -1241,7 +1261,7 @@ ${escapedMessage}
|
||||
* Put all the players on the map on map load.
|
||||
*/
|
||||
private doInitUsersPosition(usersPosition: MessageUserPositionInterface[]): void {
|
||||
const currentPlayerId = this.connection.getUserId();
|
||||
const currentPlayerId = this.connection?.getUserId();
|
||||
this.removeAllRemotePlayers();
|
||||
// load map
|
||||
usersPosition.forEach((userPosition : MessageUserPositionInterface) => {
|
||||
@ -1385,7 +1405,7 @@ ${escapedMessage}
|
||||
* Sends to the server an event emitted by one of the ActionableItems.
|
||||
*/
|
||||
emitActionableEvent(itemId: number, eventName: string, state: unknown, parameters: unknown) {
|
||||
this.connection.emitActionableEvent(itemId, eventName, state, parameters);
|
||||
this.connection?.emitActionableEvent(itemId, eventName, state, parameters);
|
||||
}
|
||||
|
||||
public onResize(): void {
|
||||
@ -1393,7 +1413,7 @@ ${escapedMessage}
|
||||
|
||||
// Send new viewport to server
|
||||
const camera = this.cameras.main;
|
||||
this.connection.setViewport({
|
||||
this.connection?.setViewport({
|
||||
left: camera.scrollX,
|
||||
top: camera.scrollY,
|
||||
right: camera.scrollX + camera.width,
|
||||
@ -1448,7 +1468,7 @@ ${escapedMessage}
|
||||
const jitsiUrl = allProps.get("jitsiUrl") as string|undefined;
|
||||
|
||||
jitsiFactory.start(roomName, this.playerName, jwt, jitsiConfig, jitsiInterfaceConfig, jitsiUrl);
|
||||
this.connection.setSilent(true);
|
||||
this.connection?.setSilent(true);
|
||||
mediaManager.hideGameOverlay();
|
||||
|
||||
//permit to stop jitsi when user close iframe
|
||||
@ -1477,15 +1497,25 @@ ${escapedMessage}
|
||||
}
|
||||
|
||||
//todo: put this into an 'orchestrator' scene (EntryScene?)
|
||||
private showWorldFullError(): void {
|
||||
private showWorldFullError(message: string|null): void {
|
||||
this.cleanupClosingScene();
|
||||
this.scene.stop(ReconnectingSceneName);
|
||||
this.scene.remove(ReconnectingSceneName);
|
||||
this.userInputManager.disableControls();
|
||||
this.scene.start(ErrorSceneName, {
|
||||
title: 'Connection rejected',
|
||||
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'
|
||||
});
|
||||
//FIX ME to use status code
|
||||
if(message == undefined){
|
||||
this.scene.start(ErrorSceneName, {
|
||||
title: 'Connection rejected',
|
||||
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'
|
||||
});
|
||||
}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) {
|
||||
|
@ -1,54 +1,33 @@
|
||||
import {EnableCameraSceneName} from "./EnableCameraScene";
|
||||
import {TextField} from "../Components/TextField";
|
||||
import Image = Phaser.GameObjects.Image;
|
||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
||||
import {loadAllLayers, loadCustomTexture} from "../Entity/PlayerTexturesLoadingManager";
|
||||
import {loadAllLayers} from "../Entity/PlayerTexturesLoadingManager";
|
||||
import Sprite = Phaser.GameObjects.Sprite;
|
||||
import Container = Phaser.GameObjects.Container;
|
||||
import {gameManager} from "../Game/GameManager";
|
||||
import {ResizableScene} from "./ResizableScene";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import {addLoader} from "../Components/Loader";
|
||||
import {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures";
|
||||
import {AbstractCharacterScene} from "./AbstractCharacterScene";
|
||||
import {areCharacterLayersValid} from "../../Connexion/LocalUser";
|
||||
import { MenuScene } from "../Menu/MenuScene";
|
||||
import { SelectCharacterSceneName } from "./SelectCharacterScene";
|
||||
import { RESOLUTION } from "../../Enum/EnvironmentVariable";
|
||||
|
||||
export const CustomizeSceneName = "CustomizeScene";
|
||||
|
||||
enum CustomizeTextures{
|
||||
icon = "icon",
|
||||
arrowRight = "arrow_right",
|
||||
mainFont = "main_font",
|
||||
arrowUp = "arrow_up",
|
||||
}
|
||||
export const CustomizeSceneKey = "CustomizeScene";
|
||||
const customizeSceneKey = 'customizeScene';
|
||||
|
||||
export class CustomizeScene extends AbstractCharacterScene {
|
||||
|
||||
private textField!: TextField;
|
||||
private enterField!: TextField;
|
||||
|
||||
private arrowRight!: Image;
|
||||
private arrowLeft!: Image;
|
||||
|
||||
private arrowDown!: Image;
|
||||
private arrowUp!: Image;
|
||||
|
||||
private Rectangle!: Rectangle;
|
||||
|
||||
private mobileTapUP!: Rectangle;
|
||||
private mobileTapDOWN!: Rectangle;
|
||||
private mobileTapLEFT!: Rectangle;
|
||||
private mobileTapRIGHT!: Rectangle;
|
||||
|
||||
private mobileTapENTER!: Rectangle;
|
||||
|
||||
private logo!: Image;
|
||||
|
||||
private selectedLayers: number[] = [0];
|
||||
private containersRow: Container[][] = [];
|
||||
private activeRow:number = 0;
|
||||
private layers: BodyResourceDescriptionInterface[][] = [];
|
||||
|
||||
private customizeSceneElement!: Phaser.GameObjects.DOMElement;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
key: CustomizeSceneName
|
||||
@ -56,7 +35,7 @@ export class CustomizeScene extends AbstractCharacterScene {
|
||||
}
|
||||
|
||||
preload() {
|
||||
addLoader(this);
|
||||
this.load.html(customizeSceneKey, 'resources/html/CustomCharacterScene.html');
|
||||
|
||||
this.layers = loadAllLayers(this.load);
|
||||
this.loadCustomSceneSelectCharacters().then((bodyResourceDescriptions) => {
|
||||
@ -68,105 +47,44 @@ export class CustomizeScene extends AbstractCharacterScene {
|
||||
});
|
||||
});
|
||||
|
||||
this.load.image(CustomizeTextures.arrowRight, "resources/objects/arrow_right.png");
|
||||
this.load.image(CustomizeTextures.icon, "resources/logos/tcm_full.png");
|
||||
this.load.image(CustomizeTextures.arrowUp, "resources/objects/arrow_up.png");
|
||||
this.load.bitmapFont(CustomizeTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
||||
//this function must stay at the end of preload function
|
||||
addLoader(this);
|
||||
}
|
||||
|
||||
create() {
|
||||
this.textField = new TextField(this, this.game.renderer.width / 2, 30, 'Customize your own Avatar!');
|
||||
const middleX = this.getMiddleX();
|
||||
this.customizeSceneElement = this.add.dom(middleX, 0).createFromCache(customizeSceneKey);
|
||||
MenuScene.revealMenusAfterInit(this.customizeSceneElement, customizeSceneKey);
|
||||
|
||||
this.enterField = new TextField(this, this.game.renderer.width / 2, 60, 'Start the game by pressing ENTER\n\n or touching the center rectangle');
|
||||
this.customizeSceneElement.addListener('click');
|
||||
this.customizeSceneElement.on('click', (event:MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if((event?.target as HTMLInputElement).id === 'customizeSceneButtonLeft') {
|
||||
this.moveCursorHorizontally(-1);
|
||||
}else if((event?.target as HTMLInputElement).id === 'customizeSceneButtonRight') {
|
||||
this.moveCursorHorizontally(1);
|
||||
}else if((event?.target as HTMLInputElement).id === 'customizeSceneButtonDown') {
|
||||
this.moveCursorVertically(1);
|
||||
}else if((event?.target as HTMLInputElement).id === 'customizeSceneButtonUp') {
|
||||
this.moveCursorVertically(-1);
|
||||
}else if((event?.target as HTMLInputElement).id === 'customizeSceneFormBack') {
|
||||
if(this.activeRow > 0){
|
||||
this.moveCursorVertically(-1);
|
||||
}else{
|
||||
this.backToPreviousScene();
|
||||
}
|
||||
}else if((event?.target as HTMLButtonElement).id === 'customizeSceneFormSubmit') {
|
||||
if(this.activeRow < 5){
|
||||
this.moveCursorVertically(1);
|
||||
}else{
|
||||
this.nextSceneToCamera();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, CustomizeTextures.icon);
|
||||
this.add.existing(this.logo);
|
||||
|
||||
|
||||
this.arrowRight = new Image(this, this.game.renderer.width*0.9, this.game.renderer.height/2, CustomizeTextures.arrowRight);
|
||||
this.add.existing(this.arrowRight);
|
||||
this.mobileTapRIGHT = this.add
|
||||
.rectangle(
|
||||
this.game.renderer.width*0.9,
|
||||
this.game.renderer.height/2,
|
||||
32,
|
||||
32,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
this.moveCursorHorizontally(1);
|
||||
});
|
||||
|
||||
this.arrowLeft = new Image(this, this.game.renderer.width/9, this.game.renderer.height/2, CustomizeTextures.arrowRight);
|
||||
this.arrowLeft.flipX = true;
|
||||
this.add.existing(this.arrowLeft);
|
||||
this.mobileTapLEFT = this.add
|
||||
.rectangle(
|
||||
this.game.renderer.width/9,
|
||||
this.game.renderer.height/2,
|
||||
32,
|
||||
32,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
this.moveCursorHorizontally(-1);
|
||||
});
|
||||
|
||||
this.Rectangle = this.add.rectangle(this.cameras.main.worldView.x + this.cameras.main.width / 2, this.cameras.main.worldView.y + this.cameras.main.height / 2, 32, 33)
|
||||
this.Rectangle = this.add.rectangle(this.cameras.main.worldView.x + this.cameras.main.width / 2, this.cameras.main.worldView.y + this.cameras.main.height / 3, 32, 33)
|
||||
this.Rectangle.setStrokeStyle(2, 0xFFFFFF);
|
||||
this.add.existing(this.Rectangle);
|
||||
this.mobileTapENTER = this.add
|
||||
.rectangle(
|
||||
this.cameras.main.worldView.x + this.cameras.main.width / 2,
|
||||
this.cameras.main.worldView.y + this.cameras.main.height / 2,
|
||||
32,
|
||||
32,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
const layers: string[] = [];
|
||||
let i = 0;
|
||||
for (const layerItem of this.selectedLayers) {
|
||||
if (layerItem !== undefined) {
|
||||
layers.push(this.layers[i][layerItem].name);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
gameManager.setCharacterLayers(layers);
|
||||
|
||||
this.scene.sleep(CustomizeSceneName);
|
||||
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
||||
});
|
||||
|
||||
this.arrowDown = new Image(this, this.game.renderer.width - 30, 100, CustomizeTextures.arrowUp);
|
||||
this.arrowDown.flipY = true;
|
||||
this.add.existing(this.arrowDown);
|
||||
this.mobileTapDOWN = this.add
|
||||
.rectangle(
|
||||
this.game.renderer.width - 30,
|
||||
100,
|
||||
32,
|
||||
32,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
this.moveCursorVertically(1);
|
||||
});
|
||||
|
||||
this.arrowUp = new Image(this, this.game.renderer.width - 30, 60, CustomizeTextures.arrowUp);
|
||||
this.add.existing(this.arrowUp);
|
||||
this.mobileTapUP = this.add
|
||||
.rectangle(
|
||||
this.game.renderer.width - 30,
|
||||
60,
|
||||
32,
|
||||
32,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
this.moveCursorVertically(-1);
|
||||
});
|
||||
|
||||
this.createCustomizeLayer(0, 0, 0);
|
||||
this.createCustomizeLayer(0, 0, 1);
|
||||
@ -177,22 +95,10 @@ export class CustomizeScene extends AbstractCharacterScene {
|
||||
|
||||
this.moveLayers();
|
||||
this.input.keyboard.on('keyup-ENTER', () => {
|
||||
const layers: string[] = [];
|
||||
let i = 0;
|
||||
for (const layerItem of this.selectedLayers) {
|
||||
if (layerItem !== undefined) {
|
||||
layers.push(this.layers[i][layerItem].name);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!areCharacterLayersValid(layers)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gameManager.setCharacterLayers(layers);
|
||||
|
||||
this.scene.sleep(CustomizeSceneName);
|
||||
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
||||
this.nextSceneToCamera();
|
||||
});
|
||||
this.input.keyboard.on('keyup-BACKSPACE', () => {
|
||||
this.backToPreviousScene();
|
||||
});
|
||||
|
||||
this.input.keyboard.on('keyup-RIGHT', () => this.moveCursorHorizontally(1));
|
||||
@ -222,6 +128,27 @@ export class CustomizeScene extends AbstractCharacterScene {
|
||||
}
|
||||
|
||||
private moveCursorVertically(index:number): void {
|
||||
|
||||
if(index === -1 && this.activeRow === 5){
|
||||
const button = this.customizeSceneElement.getChildByID('customizeSceneFormSubmit') as HTMLButtonElement;
|
||||
button.innerHTML = `Next <img src="resources/objects/arrow_up.png"/>`;
|
||||
}
|
||||
|
||||
if(index === 1 && this.activeRow === 4){
|
||||
const button = this.customizeSceneElement.getChildByID('customizeSceneFormSubmit') as HTMLButtonElement;
|
||||
button.innerText = 'Finish';
|
||||
}
|
||||
|
||||
if(index === -1 && this.activeRow === 1){
|
||||
const button = this.customizeSceneElement.getChildByID('customizeSceneFormBack') as HTMLButtonElement;
|
||||
button.innerText = `Return`;
|
||||
}
|
||||
|
||||
if(index === 1 && this.activeRow === 0){
|
||||
const button = this.customizeSceneElement.getChildByID('customizeSceneFormBack') as HTMLButtonElement;
|
||||
button.innerHTML = `Back <img src="resources/objects/arrow_up.png"/>`;
|
||||
}
|
||||
|
||||
this.activeRow += index;
|
||||
if (this.activeRow < 0) {
|
||||
this.activeRow = 0
|
||||
@ -236,11 +163,6 @@ export class CustomizeScene extends AbstractCharacterScene {
|
||||
localUserStore.setCustomCursorPosition(this.activeRow, this.selectedLayers);
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
super.update(time, delta);
|
||||
this.enterField.setVisible(!!(Math.floor(time / 500) % 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x, the layer's vertical position
|
||||
* @param y, the layer's horizontal position
|
||||
@ -298,7 +220,7 @@ export class CustomizeScene extends AbstractCharacterScene {
|
||||
*/
|
||||
private moveLayers(): void {
|
||||
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2;
|
||||
const screenCenterY = this.cameras.main.worldView.y + this.cameras.main.height / 2;
|
||||
const screenCenterY = this.cameras.main.worldView.y + this.cameras.main.height / 3;
|
||||
const screenWidth = this.game.renderer.width;
|
||||
const screenHeight = this.game.renderer.height;
|
||||
for (let i = 0; i < this.containersRow.length; i++) {
|
||||
@ -337,39 +259,63 @@ export class CustomizeScene extends AbstractCharacterScene {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
this.moveLayers();
|
||||
|
||||
this.Rectangle.x = this.cameras.main.worldView.x + this.cameras.main.width / 2;
|
||||
this.mobileTapENTER.x = this.cameras.main.worldView.x + this.cameras.main.width / 2;
|
||||
this.Rectangle.y = this.cameras.main.worldView.y + this.cameras.main.height / 2;
|
||||
this.mobileTapENTER.y = this.cameras.main.worldView.y + this.cameras.main.height / 2;
|
||||
|
||||
this.textField.x = this.game.renderer.width/2;
|
||||
|
||||
this.logo.x = this.game.renderer.width - 30;
|
||||
this.logo.y = this.game.renderer.height - 20;
|
||||
|
||||
this.arrowUp.x = this.game.renderer.width - 30;
|
||||
this.mobileTapUP.x = this.game.renderer.width - 30;
|
||||
this.arrowUp.y = 60;
|
||||
this.mobileTapUP.y = 60;
|
||||
|
||||
this.arrowDown.x = this.game.renderer.width - 30;
|
||||
this.mobileTapDOWN.x = this.game.renderer.width - 30;
|
||||
this.arrowDown.y = 100;
|
||||
this.mobileTapDOWN.y = 100;
|
||||
|
||||
this.arrowLeft.x = this.game.renderer.width/9;
|
||||
this.mobileTapLEFT.x = this.game.renderer.width/9;
|
||||
this.arrowLeft.y = this.game.renderer.height/2;
|
||||
this.mobileTapLEFT.y = this.game.renderer.height/2;
|
||||
|
||||
this.arrowRight.x = this.game.renderer.width*0.9;
|
||||
this.mobileTapRIGHT.x = this.game.renderer.width*0.9;
|
||||
this.arrowRight.y = this.game.renderer.height/2;
|
||||
this.mobileTapRIGHT.y = this.game.renderer.height/2;
|
||||
|
||||
this.Rectangle.y = this.cameras.main.worldView.y + this.cameras.main.height / 3;
|
||||
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.customizeSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
protected getMiddleX() : number{
|
||||
return (this.game.renderer.width / RESOLUTION) -
|
||||
(
|
||||
this.customizeSceneElement
|
||||
&& this.customizeSceneElement.node
|
||||
&& this.customizeSceneElement.node.getBoundingClientRect().width > 0
|
||||
? (this.customizeSceneElement.node.getBoundingClientRect().width / (2*RESOLUTION))
|
||||
: 150
|
||||
);
|
||||
}
|
||||
|
||||
private nextSceneToCamera(){
|
||||
const layers: string[] = [];
|
||||
let i = 0;
|
||||
for (const layerItem of this.selectedLayers) {
|
||||
if (layerItem !== undefined) {
|
||||
layers.push(this.layers[i][layerItem].name);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!areCharacterLayersValid(layers)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gameManager.setCharacterLayers(layers);
|
||||
this.scene.sleep(CustomizeSceneName);
|
||||
this.scene.remove(SelectCharacterSceneName);
|
||||
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
||||
}
|
||||
|
||||
private backToPreviousScene(){
|
||||
this.scene.sleep(CustomizeSceneName);
|
||||
this.scene.run(SelectCharacterSceneName);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||
import {PinchManager} from "../UserInput/PinchManager";
|
||||
import MouseWheelToUpDown from "phaser3-rex-plugins/plugins/mousewheeltoupdown.js";
|
||||
import Zone = Phaser.GameObjects.Zone;
|
||||
import { MenuScene } from "../Menu/MenuScene";
|
||||
|
||||
export const EnableCameraSceneName = "EnableCameraScene";
|
||||
enum LoginTextures {
|
||||
@ -20,12 +22,11 @@ enum LoginTextures {
|
||||
arrowUp = "arrow_up"
|
||||
}
|
||||
|
||||
const enableCameraSceneKey = 'enableCameraScene';
|
||||
|
||||
export class EnableCameraScene extends Phaser.Scene {
|
||||
private textField!: TextField;
|
||||
private pressReturnField!: TextField;
|
||||
private cameraNameField!: TextField;
|
||||
private logo!: Image;
|
||||
private arrowLeft!: Image;
|
||||
private arrowRight!: Image;
|
||||
private arrowDown!: Image;
|
||||
@ -39,7 +40,9 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
private microphoneNameField!: TextField;
|
||||
private repositionCallback!: (this: Window, ev: UIEvent) => void;
|
||||
|
||||
private mobileTapRectangle!: Rectangle;
|
||||
private enableCameraSceneElement!: Phaser.GameObjects.DOMElement;
|
||||
|
||||
private mobileTapZone!: Zone;
|
||||
private cursorKeys!: any;
|
||||
constructor() {
|
||||
super({
|
||||
@ -49,8 +52,10 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
preload() {
|
||||
|
||||
this.load.html(enableCameraSceneKey, 'resources/html/EnableCameraScene.html');
|
||||
|
||||
this.load.image(LoginTextures.playButton, "resources/objects/play_button.png");
|
||||
this.load.image(LoginTextures.icon, "resources/logos/tcm_full.png");
|
||||
this.load.image(LoginTextures.arrowRight, "resources/objects/arrow_right.png");
|
||||
this.load.image(LoginTextures.arrowUp, "resources/objects/arrow_up.png");
|
||||
// Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap
|
||||
@ -58,6 +63,17 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
create() {
|
||||
|
||||
const middleX = this.getMiddleX();
|
||||
this.enableCameraSceneElement = this.add.dom(middleX, 0).createFromCache(enableCameraSceneKey);
|
||||
MenuScene.revealMenusAfterInit(this.enableCameraSceneElement, enableCameraSceneKey);
|
||||
|
||||
const continuingButton = this.enableCameraSceneElement.getChildByID('enableCameraSceneFormSubmit') as HTMLButtonElement;
|
||||
continuingButton.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
this.login();
|
||||
});
|
||||
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
new PinchManager(this);
|
||||
}
|
||||
@ -66,19 +82,12 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
const mouseWheelToUpDown = new MouseWheelToUpDown(this);
|
||||
this.cursorKeys = mouseWheelToUpDown.createCursorKeys();
|
||||
|
||||
this.textField = new TextField(this, this.scale.width / 2, 20, 'Turn on your camera and microphone');
|
||||
/* FIX ME */
|
||||
this.textField = new TextField(this, this.scale.width / 2, 20, '');
|
||||
|
||||
this.pressReturnField = new TextField(this, this.scale.width / 2, this.scale.height - 30, 'Touch here\n\n or \n\nPress enter to start');
|
||||
// For mobile purposes - we need a big enough touchable area.
|
||||
this.mobileTapRectangle = this.add
|
||||
.rectangle(
|
||||
this.game.renderer.width / 2,
|
||||
this.game.renderer.height - 30,
|
||||
200,
|
||||
50,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
this.mobileTapZone = this.add.zone(this.scale.width / 2,this.scale.height - 30,200,50)
|
||||
.setInteractive().on("pointerdown", () => {
|
||||
this.login();
|
||||
});
|
||||
|
||||
@ -108,9 +117,6 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
this.arrowDown.setInteractive().on('pointerdown', this.nextMic.bind(this));
|
||||
this.add.existing(this.arrowDown);
|
||||
|
||||
this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, LoginTextures.icon);
|
||||
this.add.existing(this.logo);
|
||||
|
||||
this.input.keyboard.on('keyup-ENTER', () => {
|
||||
this.login();
|
||||
});
|
||||
@ -221,11 +227,9 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
this.textField.x = this.game.renderer.width / 2;
|
||||
this.mobileTapRectangle.x = this.game.renderer.width / 2;
|
||||
this.mobileTapZone.x = this.game.renderer.width / 2;
|
||||
this.cameraNameField.x = this.game.renderer.width / 2;
|
||||
this.microphoneNameField.x = this.game.renderer.width / 2;
|
||||
this.pressReturnField.x = this.game.renderer.width / 2;
|
||||
this.pressReturnField.x = this.game.renderer.width / 2;
|
||||
|
||||
this.cameraNameField.y = bounds.top / RESOLUTION - 8;
|
||||
|
||||
@ -245,23 +249,19 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
|
||||
this.arrowUp.x = this.microphoneNameField.x - this.microphoneNameField.width / 2 - 16;
|
||||
this.arrowUp.y = this.microphoneNameField.y;
|
||||
|
||||
this.pressReturnField.y = Math.max(this.game.renderer.height - 30, this.microphoneNameField.y + 20);
|
||||
this.logo.x = this.game.renderer.width - 30;
|
||||
this.logo.y = Math.max(this.game.renderer.height - 20, this.microphoneNameField.y + 30);
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
this.pressReturnField.setVisible(!!(Math.floor(time / 500) % 2));
|
||||
if (this.cursorKeys.up.isDown) {
|
||||
this.cameras.main.zoom *= 1.2;
|
||||
} else if(this.cursorKeys.down.isDown) {
|
||||
this.cameras.main.zoom *= 0.8;
|
||||
}
|
||||
|
||||
this.soundMeterSprite.setVolume(this.soundMeter.getVolume());
|
||||
mediaManager.updateScene();
|
||||
|
||||
mediaManager.setLastUpdateScene();
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.enableCameraSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
private login(): void {
|
||||
@ -287,4 +287,15 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
}
|
||||
this.updateWebCamName();
|
||||
}
|
||||
|
||||
private getMiddleX() : number{
|
||||
return (this.game.renderer.width / RESOLUTION) -
|
||||
(
|
||||
this.enableCameraSceneElement
|
||||
&& this.enableCameraSceneElement.node
|
||||
&& this.enableCameraSceneElement.node.getBoundingClientRect().width > 0
|
||||
? (this.enableCameraSceneElement.node.getBoundingClientRect().width / (2*RESOLUTION))
|
||||
: (300 / RESOLUTION)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,10 @@ export class EntryScene extends Scene {
|
||||
this.scene.start(nextSceneName);
|
||||
}).catch((err) => {
|
||||
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 {
|
||||
ErrorScene.showError(err, this.scene);
|
||||
}
|
||||
|
@ -1,30 +1,19 @@
|
||||
import {gameManager} from "../Game/GameManager";
|
||||
import {TextField} from "../Components/TextField";
|
||||
import {TextInput} from "../Components/TextInput";
|
||||
import Image = Phaser.GameObjects.Image;
|
||||
import {SelectCharacterSceneName} from "./SelectCharacterScene";
|
||||
import {ResizableScene} from "./ResizableScene";
|
||||
import {isUserNameValid, maxUserNameLength} from "../../Connexion/LocalUser";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||
import {PinchManager} from "../UserInput/PinchManager";
|
||||
import {MenuScene} from "../Menu/MenuScene";
|
||||
import { isUserNameValid } from "../../Connexion/LocalUser";
|
||||
import { RESOLUTION } from "../../Enum/EnvironmentVariable";
|
||||
|
||||
//todo: put this constants in a dedicated file
|
||||
export const LoginSceneName = "LoginScene";
|
||||
enum LoginTextures {
|
||||
icon = "icon",
|
||||
mainFont = "main_font"
|
||||
}
|
||||
|
||||
const loginSceneKey = 'loginScene';
|
||||
|
||||
export class LoginScene extends ResizableScene {
|
||||
private nameInput!: TextInput;
|
||||
private textField!: TextField;
|
||||
private infoTextField!: TextField;
|
||||
private pressReturnField!: TextField;
|
||||
private logo!: Image;
|
||||
|
||||
private loginSceneElement!: Phaser.GameObjects.DOMElement;
|
||||
private name: string = '';
|
||||
private mobileTapRectangle!: Rectangle;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
@ -34,81 +23,82 @@ export class LoginScene extends ResizableScene {
|
||||
}
|
||||
|
||||
preload() {
|
||||
//this.load.image(LoginTextures.playButton, "resources/objects/play_button.png");
|
||||
this.load.image(LoginTextures.icon, "resources/logos/tcm_full.png");
|
||||
// Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap
|
||||
this.load.bitmapFont(LoginTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
||||
this.load.html(loginSceneKey, 'resources/html/loginScene.html');
|
||||
}
|
||||
|
||||
create() {
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
new PinchManager(this);
|
||||
}
|
||||
const middleX = this.getMiddleX();
|
||||
this.loginSceneElement = this.add.dom(middleX, 0).createFromCache(loginSceneKey);
|
||||
MenuScene.revealMenusAfterInit(this.loginSceneElement, loginSceneKey);
|
||||
|
||||
this.nameInput = new TextInput(this, this.game.renderer.width / 2, 70, maxUserNameLength, this.name,(text: string) => {
|
||||
this.name = text;
|
||||
localUserStore.setName(text);
|
||||
})
|
||||
.setInteractive()
|
||||
.on('pointerdown', () => {
|
||||
this.nameInput.focus();
|
||||
})
|
||||
|
||||
this.textField = new TextField(this, this.game.renderer.width / 2, 50, 'Enter your name:')
|
||||
.setInteractive()
|
||||
.on('pointerdown', () => {
|
||||
this.nameInput.focus();
|
||||
})
|
||||
// For mobile purposes - we need a big enough touchable area.
|
||||
this.mobileTapRectangle = this.add.rectangle(
|
||||
this.game.renderer.width / 2,
|
||||
130,
|
||||
this.game.renderer.width / 2,
|
||||
60,
|
||||
).setInteractive()
|
||||
.on('pointerdown', () => {
|
||||
this.login(this.name)
|
||||
})
|
||||
this.pressReturnField = new TextField(this, this.game.renderer.width / 2, 130, 'Touch here\n\n or \n\nPress enter to start')
|
||||
|
||||
this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, LoginTextures.icon);
|
||||
this.add.existing(this.logo);
|
||||
|
||||
const infoText = "Commands: \n - Arrows or W, A, S, D to move\n - SHIFT to run";
|
||||
this.infoTextField = new TextField(this, 10, this.game.renderer.height - 35, infoText, false);
|
||||
|
||||
this.input.keyboard.on('keyup-ENTER', () => {
|
||||
if (isUserNameValid(this.name)) {
|
||||
this.login(this.name);
|
||||
const pErrorElement = this.loginSceneElement.getChildByID('errorLoginScene') as HTMLInputElement;
|
||||
const inputElement = this.loginSceneElement.getChildByID('loginSceneName') as HTMLInputElement;
|
||||
inputElement.value = localUserStore.getName() ?? '';
|
||||
inputElement.focus();
|
||||
inputElement.addEventListener('keypress', (event: KeyboardEvent) => {
|
||||
if(inputElement.value.length > 7){
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
pErrorElement.innerHTML = '';
|
||||
if(inputElement.value && !isUserNameValid(inputElement.value)){
|
||||
pErrorElement.innerHTML = 'Invalid user name: only letters and numbers are allowed. No spaces.';
|
||||
}
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
this.login(inputElement);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
const continuingButton = this.loginSceneElement.getChildByID('loginSceneFormSubmit') as HTMLButtonElement;
|
||||
continuingButton.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
this.login(inputElement);
|
||||
});
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
if (this.name == '') {
|
||||
this.pressReturnField?.setVisible(false);
|
||||
} else {
|
||||
this.pressReturnField?.setVisible(!!(Math.floor(time / 500) % 2));
|
||||
private login(inputElement: HTMLInputElement): void {
|
||||
const pErrorElement = this.loginSceneElement.getChildByID('errorLoginScene') as HTMLInputElement;
|
||||
this.name = inputElement.value;
|
||||
if (this.name === '') {
|
||||
pErrorElement.innerHTML = 'The name is empty';
|
||||
return
|
||||
}
|
||||
if(!isUserNameValid(this.name)){
|
||||
pErrorElement.innerHTML = 'Invalid user name: only letters and numbers are allowed. No spaces.';
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private login(name: string): void {
|
||||
if (this.name === '') return
|
||||
gameManager.setPlayerName(name);
|
||||
gameManager.setPlayerName(this.name);
|
||||
|
||||
this.scene.stop(LoginSceneName)
|
||||
gameManager.tryResumingGame(this, SelectCharacterSceneName);
|
||||
this.scene.remove(LoginSceneName)
|
||||
}
|
||||
|
||||
public onResize(ev: UIEvent): void {
|
||||
this.textField.x = this.game.renderer.width / 2;
|
||||
this.nameInput.setX(this.game.renderer.width / 2 - 64);
|
||||
this.pressReturnField.x = this.game.renderer.width / 2;
|
||||
this.mobileTapRectangle.x = this.game.renderer.width / 2;
|
||||
this.logo.x = this.game.renderer.width - 30;
|
||||
this.logo.y = this.game.renderer.height - 20;
|
||||
this.infoTextField.y = this.game.renderer.height - 35;
|
||||
update(time: number, delta: number): void {
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.loginSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
public onResize(ev: UIEvent): void {
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.loginSceneElement,
|
||||
x: middleX,
|
||||
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 / 2) : 0);
|
||||
}
|
||||
}
|
||||
|
76
front/src/Phaser/Login/SelectCharacterMobileScene.ts
Normal file
@ -0,0 +1,76 @@
|
||||
import {gameManager} from "../Game/GameManager";
|
||||
import {TextField} from "../Components/TextField";
|
||||
import Image = Phaser.GameObjects.Image;
|
||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
||||
import {EnableCameraSceneName} from "./EnableCameraScene";
|
||||
import {CustomizeSceneName} from "./CustomizeScene";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import {loadAllDefaultModels} from "../Entity/PlayerTexturesLoadingManager";
|
||||
import {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures";
|
||||
import {AbstractCharacterScene} from "./AbstractCharacterScene";
|
||||
import {areCharacterLayersValid} from "../../Connexion/LocalUser";
|
||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||
import {PinchManager} from "../UserInput/PinchManager";
|
||||
import {MenuScene} from "../Menu/MenuScene";
|
||||
import { SelectCharacterScene, SelectCharacterSceneName } from "./SelectCharacterScene";
|
||||
|
||||
export class SelectCharacterMobileScene extends SelectCharacterScene {
|
||||
|
||||
create(){
|
||||
super.create();
|
||||
this.selectedRectangle.destroy();
|
||||
}
|
||||
|
||||
protected defineSetupPlayer(numero: number){
|
||||
const deltaX = 30;
|
||||
const deltaY = 2;
|
||||
let [playerX, playerY] = this.getCharacterPosition();
|
||||
let playerVisible = true;
|
||||
let playerScale = 1.5;
|
||||
let playserOpactity = 1;
|
||||
|
||||
if( this.currentSelectUser !== numero ){
|
||||
playerVisible = false;
|
||||
}
|
||||
if( numero === (this.currentSelectUser + 1) ){
|
||||
playerY -= deltaY;
|
||||
playerX += deltaX;
|
||||
playerScale = 0.8;
|
||||
playserOpactity = 0.6;
|
||||
playerVisible = true;
|
||||
}
|
||||
if( numero === (this.currentSelectUser + 2) ){
|
||||
playerY -= deltaY;
|
||||
playerX += (deltaX * 2);
|
||||
playerScale = 0.8;
|
||||
playserOpactity = 0.6;
|
||||
playerVisible = true;
|
||||
}
|
||||
if( numero === (this.currentSelectUser - 1) ){
|
||||
playerY -= deltaY;
|
||||
playerX -= deltaX;
|
||||
playerScale = 0.8;
|
||||
playserOpactity = 0.6;
|
||||
playerVisible = true;
|
||||
}
|
||||
if( numero === (this.currentSelectUser - 2) ){
|
||||
playerY -= deltaY;
|
||||
playerX -= (deltaX * 2);
|
||||
playerScale = 0.8;
|
||||
playserOpactity = 0.6;
|
||||
playerVisible = true;
|
||||
}
|
||||
return {playerX, playerY, playerScale, playserOpactity, playerVisible}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pixel position by on column and row number
|
||||
*/
|
||||
protected getCharacterPosition(): [number, number] {
|
||||
return [
|
||||
this.game.renderer.width / 2,
|
||||
this.game.renderer.height / 3
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
import {gameManager} from "../Game/GameManager";
|
||||
import {TextField} from "../Components/TextField";
|
||||
import Image = Phaser.GameObjects.Image;
|
||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
||||
import {EnableCameraSceneName} from "./EnableCameraScene";
|
||||
@ -12,268 +11,265 @@ import {AbstractCharacterScene} from "./AbstractCharacterScene";
|
||||
import {areCharacterLayersValid} from "../../Connexion/LocalUser";
|
||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||
import {PinchManager} from "../UserInput/PinchManager";
|
||||
|
||||
import {MenuScene} from "../Menu/MenuScene";
|
||||
import { SelectCharacterMobileScene } from "./SelectCharacterMobileScene";
|
||||
|
||||
//todo: put this constants in a dedicated file
|
||||
export const SelectCharacterSceneName = "SelectCharacterScene";
|
||||
enum LoginTextures {
|
||||
playButton = "play_button",
|
||||
icon = "icon",
|
||||
mainFont = "main_font",
|
||||
customizeButton = "customize_button",
|
||||
customizeButtonSelected = "customize_button_selected"
|
||||
}
|
||||
|
||||
const selectCharacterKey = 'selectCharacterScene';
|
||||
|
||||
export class SelectCharacterScene extends AbstractCharacterScene {
|
||||
private readonly nbCharactersPerRow = 6;
|
||||
private textField!: TextField;
|
||||
private pressReturnField!: TextField;
|
||||
private logo!: Image;
|
||||
private customizeButton!: Image;
|
||||
private customizeButtonSelected!: Image;
|
||||
protected readonly nbCharactersPerRow = 6;
|
||||
protected selectedPlayer!: Phaser.Physics.Arcade.Sprite|null; // null if we are selecting the "customize" option
|
||||
protected players: Array<Phaser.Physics.Arcade.Sprite> = new Array<Phaser.Physics.Arcade.Sprite>();
|
||||
protected playerModels!: BodyResourceDescriptionInterface[];
|
||||
|
||||
private selectedRectangle!: Rectangle;
|
||||
private selectedRectangleXPos = 0; // Number of the character selected in the rows
|
||||
private selectedRectangleYPos = 0; // Number of the character selected in the columns
|
||||
private selectedPlayer!: Phaser.Physics.Arcade.Sprite|null; // null if we are selecting the "customize" option
|
||||
private players: Array<Phaser.Physics.Arcade.Sprite> = new Array<Phaser.Physics.Arcade.Sprite>();
|
||||
private mobileTapRectangle!: Rectangle;
|
||||
private playerModels!: BodyResourceDescriptionInterface[];
|
||||
protected selectedRectangle!: Rectangle;
|
||||
|
||||
protected selectCharacterSceneElement!: Phaser.GameObjects.DOMElement;
|
||||
protected currentSelectUser = 0;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
key: SelectCharacterSceneName
|
||||
key: SelectCharacterSceneName,
|
||||
});
|
||||
}
|
||||
|
||||
preload() {
|
||||
addLoader(this);
|
||||
this.load.html(selectCharacterKey, 'resources/html/selectCharacterScene.html');
|
||||
|
||||
this.loadSelectSceneCharacters().then((bodyResourceDescriptions) => {
|
||||
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
|
||||
this.playerModels.push(bodyResourceDescription);
|
||||
});
|
||||
})
|
||||
|
||||
this.load.image(LoginTextures.playButton, "resources/objects/play_button.png");
|
||||
this.load.image(LoginTextures.icon, "resources/logos/tcm_full.png");
|
||||
// Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap
|
||||
this.load.bitmapFont(LoginTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
||||
this.playerModels = loadAllDefaultModels(this.load);
|
||||
this.load.image(LoginTextures.customizeButton, 'resources/objects/customize.png');
|
||||
this.load.image(LoginTextures.customizeButtonSelected, 'resources/objects/customize_selected.png');
|
||||
|
||||
//this function must stay at the end of preload function
|
||||
addLoader(this);
|
||||
}
|
||||
|
||||
create() {
|
||||
|
||||
const middleX = this.getMiddleX();
|
||||
this.selectCharacterSceneElement = this.add.dom(middleX, 0).createFromCache(selectCharacterKey);
|
||||
MenuScene.revealMenusAfterInit(this.selectCharacterSceneElement, selectCharacterKey);
|
||||
|
||||
this.selectCharacterSceneElement.addListener('click');
|
||||
this.selectCharacterSceneElement.on('click', (event:MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if((event?.target as HTMLInputElement).id === 'selectCharacterButtonLeft') {
|
||||
this.moveToLeft();
|
||||
}else if((event?.target as HTMLInputElement).id === 'selectCharacterButtonRight') {
|
||||
this.moveToRight();
|
||||
}else if((event?.target as HTMLInputElement).id === 'selectCharacterSceneFormSubmit') {
|
||||
this.nextSceneToCameraScene();
|
||||
}else if((event?.target as HTMLInputElement).id === 'selectCharacterSceneFormCustomYourOwnSubmit') {
|
||||
this.nextSceneToCustomizeScene();
|
||||
}
|
||||
});
|
||||
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
new PinchManager(this);
|
||||
}
|
||||
this.textField = new TextField(this, this.game.renderer.width / 2, 50, 'Select your character');
|
||||
this.pressReturnField = new TextField(
|
||||
this,
|
||||
this.game.renderer.width / 2,
|
||||
90 + 32 * Math.ceil( this.playerModels.length / this.nbCharactersPerRow) + 60,
|
||||
'Touch here\n\n or \n\nPress enter to start');
|
||||
// For mobile purposes - we need a big enough touchable area.
|
||||
this.mobileTapRectangle = this.add
|
||||
.rectangle(
|
||||
this.game.renderer.width / 2,
|
||||
275,
|
||||
this.game.renderer.width / 2,
|
||||
50,
|
||||
)
|
||||
.setInteractive()
|
||||
.on("pointerdown", () => {
|
||||
this.nextScene();
|
||||
});
|
||||
|
||||
const rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16;
|
||||
|
||||
this.selectedRectangle = this.add.rectangle(rectangleXStart, 90, 32, 32).setStrokeStyle(2, 0xFFFFFF);
|
||||
|
||||
this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, LoginTextures.icon);
|
||||
this.add.existing(this.logo);
|
||||
|
||||
this.input.keyboard.on('keyup-ENTER', () => {
|
||||
return this.nextScene();
|
||||
});
|
||||
|
||||
this.input.keyboard.on('keydown-RIGHT', () => {
|
||||
if(this.selectedRectangleYPos * this.nbCharactersPerRow + (this.selectedRectangleXPos + 2))
|
||||
if (
|
||||
this.selectedRectangleXPos < this.nbCharactersPerRow - 1
|
||||
&& ((this.selectedRectangleYPos * this.nbCharactersPerRow) + (this.selectedRectangleXPos + 1) + 1) <= this.playerModels.length
|
||||
) {
|
||||
this.selectedRectangleXPos++;
|
||||
}
|
||||
this.updateSelectedPlayer();
|
||||
});
|
||||
this.input.keyboard.on('keydown-LEFT', () => {
|
||||
if (
|
||||
this.selectedRectangleXPos > 0
|
||||
&& ((this.selectedRectangleYPos * this.nbCharactersPerRow) + (this.selectedRectangleXPos - 1) + 1) <= this.playerModels.length
|
||||
) {
|
||||
this.selectedRectangleXPos--;
|
||||
}
|
||||
this.updateSelectedPlayer();
|
||||
});
|
||||
this.input.keyboard.on('keydown-DOWN', () => {
|
||||
if (
|
||||
this.selectedRectangleYPos < Math.ceil(this.playerModels.length / this.nbCharactersPerRow)
|
||||
&& (
|
||||
(((this.selectedRectangleYPos + 1) * this.nbCharactersPerRow) + this.selectedRectangleXPos + 1) <= this.playerModels.length // check if player isn't empty
|
||||
|| (this.selectedRectangleYPos + 1) === Math.ceil(this.playerModels.length / this.nbCharactersPerRow) // check if is custom rectangle
|
||||
)
|
||||
) {
|
||||
this.selectedRectangleYPos++;
|
||||
}
|
||||
this.updateSelectedPlayer();
|
||||
});
|
||||
this.input.keyboard.on('keydown-UP', () => {
|
||||
if (
|
||||
this.selectedRectangleYPos > 0
|
||||
&& (((this.selectedRectangleYPos - 1) * this.nbCharactersPerRow) + this.selectedRectangleXPos + 1) <= this.playerModels.length
|
||||
) {
|
||||
this.selectedRectangleYPos--;
|
||||
}
|
||||
this.updateSelectedPlayer();
|
||||
});
|
||||
this.selectedRectangle.setDepth(2);
|
||||
|
||||
/*create user*/
|
||||
this.createCurrentPlayer();
|
||||
|
||||
const playerNumber = localUserStore.getPlayerCharacterIndex();
|
||||
if (playerNumber && playerNumber !== -1) {
|
||||
this.selectedRectangleXPos = playerNumber % this.nbCharactersPerRow;
|
||||
this.selectedRectangleYPos = Math.floor(playerNumber / this.nbCharactersPerRow);
|
||||
this.updateSelectedPlayer();
|
||||
} else if (playerNumber === -1) {
|
||||
this.selectedRectangleYPos = Math.ceil(this.playerModels.length / this.nbCharactersPerRow);
|
||||
this.updateSelectedPlayer();
|
||||
}
|
||||
|
||||
this.input.keyboard.on('keyup-ENTER', () => {
|
||||
return this.nextSceneToCameraScene();
|
||||
});
|
||||
|
||||
this.input.keyboard.on('keydown-RIGHT', () => {
|
||||
this.moveToRight();
|
||||
});
|
||||
this.input.keyboard.on('keydown-LEFT', () => {
|
||||
this.moveToLeft();
|
||||
});
|
||||
this.input.keyboard.on('keydown-UP', () => {
|
||||
this.moveToUp();
|
||||
});
|
||||
this.input.keyboard.on('keydown-DOWN', () => {
|
||||
this.moveToDown();
|
||||
});
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
this.pressReturnField.setVisible(!!(Math.floor(time / 500) % 2));
|
||||
}
|
||||
|
||||
private nextScene(): void {
|
||||
protected nextSceneToCameraScene(): void {
|
||||
if (this.selectedPlayer !== null && !areCharacterLayersValid([this.selectedPlayer.texture.key])) {
|
||||
return;
|
||||
}
|
||||
this.scene.stop(SelectCharacterSceneName);
|
||||
if (this.selectedPlayer !== null) {
|
||||
gameManager.setCharacterLayers([this.selectedPlayer.texture.key]);
|
||||
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
||||
} else {
|
||||
this.scene.run(CustomizeSceneName);
|
||||
if(!this.selectedPlayer){
|
||||
return;
|
||||
}
|
||||
this.scene.stop(SelectCharacterSceneName);
|
||||
gameManager.setCharacterLayers([this.selectedPlayer.texture.key]);
|
||||
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
||||
this.scene.remove(SelectCharacterSceneName);
|
||||
}
|
||||
|
||||
protected nextSceneToCustomizeScene(): void {
|
||||
if (this.selectedPlayer !== null && !areCharacterLayersValid([this.selectedPlayer.texture.key])) {
|
||||
return;
|
||||
}
|
||||
this.scene.sleep(SelectCharacterSceneName);
|
||||
this.scene.run(CustomizeSceneName);
|
||||
}
|
||||
|
||||
createCurrentPlayer(): void {
|
||||
for (let i = 0; i <this.playerModels.length; i++) {
|
||||
const playerResource = this.playerModels[i];
|
||||
|
||||
const col = i % this.nbCharactersPerRow;
|
||||
const row = Math.floor(i / this.nbCharactersPerRow);
|
||||
|
||||
const [x, y] = this.getCharacterPosition(col, row);
|
||||
const player = this.physics.add.sprite(x, y, playerResource.name, 0);
|
||||
player.setBounce(0.2);
|
||||
player.setCollideWorldBounds(true);
|
||||
const [middleX, middleY] = this.getCharacterPosition();
|
||||
const player = this.physics.add.sprite(middleX, middleY, playerResource.name, 0);
|
||||
this.setUpPlayer(player, i);
|
||||
this.anims.create({
|
||||
key: playerResource.name,
|
||||
frames: this.anims.generateFrameNumbers(playerResource.name, {start: 0, end: 2,}),
|
||||
frameRate: 10,
|
||||
frames: this.anims.generateFrameNumbers(playerResource.name, {start: 0, end: 11}),
|
||||
frameRate: 8,
|
||||
repeat: -1
|
||||
});
|
||||
player.setInteractive().on("pointerdown", () => {
|
||||
this.selectedRectangleXPos = col;
|
||||
this.selectedRectangleYPos = row;
|
||||
this.updateSelectedPlayer();
|
||||
if(this.currentSelectUser === i){
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser = i;
|
||||
this.moveUser();
|
||||
});
|
||||
this.players.push(player);
|
||||
}
|
||||
|
||||
const maxRow = Math.ceil( this.playerModels.length / this.nbCharactersPerRow);
|
||||
this.customizeButton = new Image(this, this.game.renderer.width / 2, 90 + 32 * maxRow + 6, LoginTextures.customizeButton);
|
||||
this.customizeButton.setOrigin(0.5, 0.5);
|
||||
this.add.existing(this.customizeButton);
|
||||
this.customizeButtonSelected = new Image(this, this.game.renderer.width / 2, 90 + 32 * maxRow + 6, LoginTextures.customizeButtonSelected);
|
||||
this.customizeButtonSelected.setOrigin(0.5, 0.5);
|
||||
this.customizeButtonSelected.setVisible(false);
|
||||
this.add.existing(this.customizeButtonSelected);
|
||||
this.selectedPlayer = this.players[this.currentSelectUser];
|
||||
this.selectedPlayer.play(this.playerModels[this.currentSelectUser].name);
|
||||
}
|
||||
|
||||
this.customizeButton.setInteractive().on("pointerdown", () => {
|
||||
this.selectedRectangleYPos = Math.ceil(this.playerModels.length / this.nbCharactersPerRow);
|
||||
this.updateSelectedPlayer();
|
||||
this.nextScene();
|
||||
});
|
||||
this.customizeButtonSelected.setInteractive().on("pointerdown", () => {
|
||||
this.nextScene();
|
||||
});
|
||||
protected moveUser(){
|
||||
for(let i = 0; i < this.players.length; i++){
|
||||
const player = this.players[i];
|
||||
this.setUpPlayer(player, i);
|
||||
}
|
||||
this.updateSelectedPlayer();
|
||||
}
|
||||
|
||||
this.selectedPlayer = this.players[0];
|
||||
this.selectedPlayer.play(this.playerModels[0].name);
|
||||
protected moveToLeft(){
|
||||
if(this.currentSelectUser === 0){
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser -= 1;
|
||||
this.moveUser();
|
||||
}
|
||||
|
||||
protected moveToRight(){
|
||||
if(this.currentSelectUser === (this.players.length - 1)){
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser += 1;
|
||||
this.moveUser();
|
||||
}
|
||||
|
||||
protected moveToUp(){
|
||||
if(this.currentSelectUser < this.nbCharactersPerRow){
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser -= this.nbCharactersPerRow;
|
||||
this.moveUser();
|
||||
}
|
||||
|
||||
protected moveToDown(){
|
||||
if((this.currentSelectUser + this.nbCharactersPerRow) > (this.players.length - 1)){
|
||||
return;
|
||||
}
|
||||
this.currentSelectUser += this.nbCharactersPerRow;
|
||||
this.moveUser();
|
||||
}
|
||||
|
||||
protected defineSetupPlayer(numero: number){
|
||||
const deltaX = 32;
|
||||
const deltaY = 32;
|
||||
let [playerX, playerY] = this.getCharacterPosition(); // player X and player y are middle of the
|
||||
|
||||
playerX = ( (playerX - (deltaX * 2.5)) + ((deltaX) * (numero % this.nbCharactersPerRow)) ); // calcul position on line users
|
||||
playerY = ( (playerY - (deltaY * 2)) + ((deltaY) * ( Math.floor(numero / this.nbCharactersPerRow) )) ); // calcul position on column users
|
||||
|
||||
const playerVisible = true;
|
||||
const playerScale = 1;
|
||||
const playserOpactity = 1;
|
||||
|
||||
// if selected
|
||||
if( numero === this.currentSelectUser ){
|
||||
this.selectedRectangle.setX(playerX);
|
||||
this.selectedRectangle.setY(playerY);
|
||||
}
|
||||
|
||||
return {playerX, playerY, playerScale, playserOpactity, playerVisible}
|
||||
}
|
||||
|
||||
protected setUpPlayer(player: Phaser.Physics.Arcade.Sprite, numero: number){
|
||||
|
||||
const {playerX, playerY, playerScale, playserOpactity, playerVisible} = this.defineSetupPlayer(numero);
|
||||
player.setBounce(0.2);
|
||||
player.setCollideWorldBounds(true);
|
||||
player.setVisible( playerVisible );
|
||||
player.setScale(playerScale, playerScale);
|
||||
player.setAlpha(playserOpactity);
|
||||
player.setX(playerX);
|
||||
player.setY(playerY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pixel position by on column and row number
|
||||
*/
|
||||
private getCharacterPosition(x: number, y: number): [number, number] {
|
||||
protected getCharacterPosition(): [number, number] {
|
||||
return [
|
||||
this.game.renderer.width / 2 + 16 + (x - this.nbCharactersPerRow / 2) * 32,
|
||||
y * 32 + 90
|
||||
this.game.renderer.width / 2,
|
||||
this.game.renderer.height / 2.5
|
||||
];
|
||||
}
|
||||
|
||||
private updateSelectedPlayer(): void {
|
||||
this.selectedPlayer?.anims.pause();
|
||||
// If we selected the customize button
|
||||
if (this.selectedRectangleYPos === Math.ceil(this.playerModels.length / this.nbCharactersPerRow)) {
|
||||
this.selectedPlayer = null;
|
||||
this.selectedRectangle.setVisible(false);
|
||||
this.customizeButtonSelected.setVisible(true);
|
||||
this.customizeButton.setVisible(false);
|
||||
localUserStore.setPlayerCharacterIndex(-1);
|
||||
return;
|
||||
}
|
||||
this.customizeButtonSelected.setVisible(false);
|
||||
this.customizeButton.setVisible(true);
|
||||
const [x, y] = this.getCharacterPosition(this.selectedRectangleXPos, this.selectedRectangleYPos);
|
||||
this.selectedRectangle.setVisible(true);
|
||||
this.selectedRectangle.setX(x);
|
||||
this.selectedRectangle.setY(y);
|
||||
this.selectedRectangle.setSize(32, 32);
|
||||
const playerNumber = this.selectedRectangleXPos + this.selectedRectangleYPos * this.nbCharactersPerRow;
|
||||
const player = this.players[playerNumber];
|
||||
player.play(this.playerModels[playerNumber].name);
|
||||
protected updateSelectedPlayer(): void {
|
||||
this.selectedPlayer?.anims.pause(this.selectedPlayer?.anims.currentAnim.frames[0]);
|
||||
const player = this.players[this.currentSelectUser];
|
||||
player.play(this.playerModels[this.currentSelectUser].name);
|
||||
this.selectedPlayer = player;
|
||||
localUserStore.setPlayerCharacterIndex(playerNumber);
|
||||
localUserStore.setPlayerCharacterIndex(this.currentSelectUser);
|
||||
}
|
||||
|
||||
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 {
|
||||
this.textField.x = this.game.renderer.width / 2;
|
||||
this.pressReturnField.x = this.game.renderer.width / 2;
|
||||
this.logo.x = this.game.renderer.width - 30;
|
||||
this.logo.y = this.game.renderer.height - 20;
|
||||
this.customizeButton.x = this.game.renderer.width / 2;
|
||||
this.customizeButtonSelected.x = this.game.renderer.width / 2;
|
||||
//move position of user
|
||||
this.moveUser();
|
||||
|
||||
for (let i = 0; i <this.playerModels.length; i++) {
|
||||
const player = this.players[i];
|
||||
|
||||
const col = i % this.nbCharactersPerRow;
|
||||
const row = Math.floor(i / this.nbCharactersPerRow);
|
||||
|
||||
const [x, y] = this.getCharacterPosition(col, row);
|
||||
player.x = x;
|
||||
player.y = y;
|
||||
}
|
||||
this.updateSelectedPlayer();
|
||||
const middleX = this.getMiddleX();
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -3,35 +3,26 @@ import Rectangle = Phaser.GameObjects.Rectangle;
|
||||
import { addLoader } from "../Components/Loader";
|
||||
import { gameManager} from "../Game/GameManager";
|
||||
import { ResizableScene } from "./ResizableScene";
|
||||
import { TextField } from "../Components/TextField";
|
||||
import { EnableCameraSceneName } from "./EnableCameraScene";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
import { CompanionResourceDescriptionInterface } from "../Companion/CompanionTextures";
|
||||
import { getAllCompanionResources } from "../Companion/CompanionTexturesLoadingManager";
|
||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
||||
import {PinchManager} from "../UserInput/PinchManager";
|
||||
import { MenuScene } from "../Menu/MenuScene";
|
||||
import { RESOLUTION } from "../../Enum/EnvironmentVariable";
|
||||
|
||||
export const SelectCompanionSceneName = "SelectCompanionScene";
|
||||
|
||||
enum LoginTextures {
|
||||
playButton = "play_button",
|
||||
icon = "icon",
|
||||
mainFont = "main_font"
|
||||
}
|
||||
const selectCompanionSceneKey = 'selectCompanionScene';
|
||||
|
||||
export class SelectCompanionScene extends ResizableScene {
|
||||
private logo!: Image;
|
||||
private textField!: TextField;
|
||||
private pressReturnField!: TextField;
|
||||
private readonly nbCharactersPerRow = 7;
|
||||
|
||||
private selectedRectangle!: Rectangle;
|
||||
|
||||
private selectedCompanion!: Phaser.Physics.Arcade.Sprite;
|
||||
private companions: Array<Phaser.Physics.Arcade.Sprite> = new Array<Phaser.Physics.Arcade.Sprite>();
|
||||
private companionModels: Array<CompanionResourceDescriptionInterface|null> = [null];
|
||||
private companionModels: Array<CompanionResourceDescriptionInterface> = [];
|
||||
|
||||
private confirmTouchArea!: Rectangle;
|
||||
private selectCompanionSceneElement!: Phaser.GameObjects.DOMElement;
|
||||
private currentCompanion = 0;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
@ -40,210 +31,222 @@ export class SelectCompanionScene extends ResizableScene {
|
||||
}
|
||||
|
||||
preload() {
|
||||
addLoader(this);
|
||||
this.load.html(selectCompanionSceneKey, 'resources/html/SelectCompanionScene.html');
|
||||
|
||||
getAllCompanionResources(this.load).forEach(model => {
|
||||
this.companionModels.push(model);
|
||||
});
|
||||
|
||||
this.load.image(LoginTextures.icon, "resources/logos/tcm_full.png");
|
||||
this.load.image(LoginTextures.playButton, "resources/objects/play_button.png");
|
||||
|
||||
// Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap
|
||||
this.load.bitmapFont(LoginTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
||||
|
||||
//this function must stay at the end of preload function
|
||||
addLoader(this);
|
||||
}
|
||||
|
||||
create() {
|
||||
|
||||
const middleX = this.getMiddleX();
|
||||
this.selectCompanionSceneElement = this.add.dom(middleX, 0).createFromCache(selectCompanionSceneKey);
|
||||
MenuScene.revealMenusAfterInit(this.selectCompanionSceneElement, selectCompanionSceneKey);
|
||||
|
||||
this.selectCompanionSceneElement.addListener('click');
|
||||
this.selectCompanionSceneElement.on('click', (event:MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if((event?.target as HTMLInputElement).id === 'selectCharacterButtonLeft') {
|
||||
this.moveToLeft();
|
||||
}else if((event?.target as HTMLInputElement).id === 'selectCharacterButtonRight') {
|
||||
this.moveToRight();
|
||||
}else if((event?.target as HTMLInputElement).id === 'selectCompanionSceneFormSubmit') {
|
||||
this.nextScene();
|
||||
}else if((event?.target as HTMLInputElement).id === 'selectCompanionSceneFormBack') {
|
||||
this._nextScene();
|
||||
}
|
||||
});
|
||||
|
||||
if (touchScreenManager.supportTouchScreen) {
|
||||
new PinchManager(this);
|
||||
}
|
||||
|
||||
this.textField = new TextField(this, this.game.renderer.width / 2, 50, 'Select your companion');
|
||||
|
||||
const confirmTouchAreaY = 115 + 32 * Math.ceil(this.companionModels.length / this.nbCharactersPerRow);
|
||||
this.pressReturnField = new TextField(
|
||||
this,
|
||||
this.game.renderer.width / 2,
|
||||
confirmTouchAreaY,
|
||||
'Touch here\n\n or \n\n press enter to start'
|
||||
);
|
||||
this.confirmTouchArea = this.add
|
||||
.rectangle(this.game.renderer.width / 2, confirmTouchAreaY, 200, 50)
|
||||
.setInteractive()
|
||||
.on("pointerdown", this.nextScene.bind(this));
|
||||
|
||||
const rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16;
|
||||
this.selectedRectangle = this.add.rectangle(rectangleXStart, 90, 32, 32).setStrokeStyle(2, 0xFFFFFF);
|
||||
|
||||
this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, LoginTextures.icon);
|
||||
this.add.existing(this.logo);
|
||||
|
||||
// input events
|
||||
this.input.keyboard.on('keyup-ENTER', this.nextScene.bind(this));
|
||||
|
||||
this.input.keyboard.on('keydown-RIGHT', this.selectNext.bind(this));
|
||||
this.input.keyboard.on('keydown-LEFT', this.selectPrevious.bind(this));
|
||||
this.input.keyboard.on('keydown-DOWN', this.jumpToNextRow.bind(this));
|
||||
this.input.keyboard.on('keydown-UP', this.jumpToPreviousRow.bind(this));
|
||||
this.input.keyboard.on('keydown-RIGHT', this.moveToRight.bind(this));
|
||||
this.input.keyboard.on('keydown-LEFT', this.moveToLeft.bind(this));
|
||||
|
||||
if(localUserStore.getCompanion()){
|
||||
const companionIndex = this.companionModels.findIndex((companion) => companion.name === localUserStore.getCompanion());
|
||||
if(companionIndex > -1 || companionIndex < this.companions.length){
|
||||
this.currentCompanion = companionIndex;
|
||||
this.selectedCompanion = this.companions[companionIndex];
|
||||
}
|
||||
}
|
||||
|
||||
localUserStore.setCompanion(null);
|
||||
gameManager.setCompanion(null);
|
||||
|
||||
this.createCurrentCompanion();
|
||||
this.selectCompanion(this.getCompanionIndex());
|
||||
this.updateSelectedCompanion();
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
this.pressReturnField.setVisible(!!(Math.floor(time / 500) % 2));
|
||||
}
|
||||
|
||||
private jumpToPreviousRow(): void {
|
||||
const index = this.companions.indexOf(this.selectedCompanion) - this.nbCharactersPerRow;
|
||||
if (index >= 0) {
|
||||
this.selectCompanion(index);
|
||||
}
|
||||
}
|
||||
|
||||
private jumpToNextRow(): void {
|
||||
const index = this.companions.indexOf(this.selectedCompanion) + this.nbCharactersPerRow;
|
||||
if (index < this.companions.length) {
|
||||
this.selectCompanion(index);
|
||||
}
|
||||
}
|
||||
|
||||
private selectPrevious(): void {
|
||||
const index = this.companions.indexOf(this.selectedCompanion);
|
||||
this.selectCompanion(index - 1);
|
||||
}
|
||||
|
||||
private selectNext(): void {
|
||||
const index = this.companions.indexOf(this.selectedCompanion);
|
||||
this.selectCompanion(index + 1);
|
||||
}
|
||||
|
||||
private selectCompanion(index?: number): void {
|
||||
if (typeof index === 'undefined') {
|
||||
index = this.companions.indexOf(this.selectedCompanion);
|
||||
}
|
||||
|
||||
// make sure index is inside possible range
|
||||
index = Math.min(this.companions.length - 1, Math.max(0, index));
|
||||
|
||||
if (this.selectedCompanion === this.companions[index]) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedCompanion.anims.pause();
|
||||
this.selectedCompanion = this.companions[index];
|
||||
|
||||
this.redrawSelectedRectangle();
|
||||
|
||||
const model = this.companionModels[index];
|
||||
|
||||
if (model !== null) {
|
||||
this.selectedCompanion.anims.play(model.name);
|
||||
}
|
||||
}
|
||||
|
||||
private redrawSelectedRectangle(): void {
|
||||
this.selectedRectangle.setVisible(true);
|
||||
this.selectedRectangle.setX(this.selectedCompanion.x);
|
||||
this.selectedRectangle.setY(this.selectedCompanion.y);
|
||||
this.selectedRectangle.setSize(32, 32);
|
||||
}
|
||||
|
||||
private storeCompanionSelection(): string|null {
|
||||
const index = this.companions.indexOf(this.selectedCompanion);
|
||||
const model = this.companionModels[index];
|
||||
const companion = model === null ? null : model.name;
|
||||
|
||||
localUserStore.setCompanion(companion);
|
||||
|
||||
return companion;
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.selectCompanionSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
private nextScene(): void {
|
||||
const companion = this.storeCompanionSelection();
|
||||
localUserStore.setCompanion(this.companionModels[this.currentCompanion].name);
|
||||
gameManager.setCompanion(this.companionModels[this.currentCompanion].name);
|
||||
|
||||
this._nextScene();
|
||||
}
|
||||
|
||||
private _nextScene(){
|
||||
// next scene
|
||||
this.scene.stop(SelectCompanionSceneName);
|
||||
|
||||
gameManager.setCompanion(companion);
|
||||
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
||||
|
||||
this.scene.remove(SelectCompanionSceneName);
|
||||
}
|
||||
|
||||
private createCurrentCompanion(): void {
|
||||
for (let i = 0; i < this.companionModels.length; i++) {
|
||||
const companionResource = this.companionModels[i];
|
||||
|
||||
const col = i % this.nbCharactersPerRow;
|
||||
const row = Math.floor(i / this.nbCharactersPerRow);
|
||||
|
||||
const [x, y] = this.getCharacterPosition(col, row);
|
||||
|
||||
let name = "null";
|
||||
if (companionResource !== null) {
|
||||
name = companionResource.name;
|
||||
}
|
||||
|
||||
const companion = this.physics.add.sprite(x, y, name, 0);
|
||||
companion.setBounce(0.2);
|
||||
companion.setCollideWorldBounds(true);
|
||||
|
||||
if (companionResource !== null) {
|
||||
this.anims.create({
|
||||
key: name,
|
||||
frames: this.anims.generateFrameNumbers(name, {start: 0, end: 2,}),
|
||||
frameRate: 10,
|
||||
repeat: -1
|
||||
});
|
||||
}
|
||||
const companionResource = this.companionModels[i]
|
||||
const [middleX, middleY] = this.getCompanionPosition();
|
||||
const companion = this.physics.add.sprite(middleX, middleY, companionResource.name, 0);
|
||||
this.setUpCompanion(companion, i);
|
||||
this.anims.create({
|
||||
key: companionResource.name,
|
||||
frames: this.anims.generateFrameNumbers(companionResource.name, {start: 0, end: 2,}),
|
||||
frameRate: 10,
|
||||
repeat: -1
|
||||
});
|
||||
|
||||
companion.setInteractive().on("pointerdown", () => {
|
||||
this.selectCompanion(i);
|
||||
this.currentCompanion = i;
|
||||
this.moveCompanion();
|
||||
});
|
||||
|
||||
this.companions.push(companion);
|
||||
}
|
||||
|
||||
this.selectedCompanion = this.companions[0];
|
||||
}
|
||||
|
||||
private getCharacterPosition(x: number, y: number): [number, number] {
|
||||
return [
|
||||
this.game.renderer.width / 2 + 16 + (x - this.nbCharactersPerRow / 2) * 32,
|
||||
y * 32 + 90
|
||||
];
|
||||
this.selectedCompanion = this.companions[this.currentCompanion];
|
||||
}
|
||||
|
||||
public onResize(ev: UIEvent): void {
|
||||
this.textField.x = this.game.renderer.width / 2;
|
||||
this.pressReturnField.x = this.game.renderer.width / 2;
|
||||
this.logo.x = this.game.renderer.width - 30;
|
||||
this.logo.y = this.game.renderer.height - 20;
|
||||
this.moveCompanion();
|
||||
|
||||
for (let i = 0; i < this.companionModels.length; i++) {
|
||||
const companion = this.companions[i];
|
||||
|
||||
const col = i % this.nbCharactersPerRow;
|
||||
const row = Math.floor(i / this.nbCharactersPerRow);
|
||||
|
||||
const [x, y] = this.getCharacterPosition(col, row);
|
||||
companion.x = x;
|
||||
companion.y = y;
|
||||
}
|
||||
|
||||
this.redrawSelectedRectangle();
|
||||
const middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.selectCompanionSceneElement,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
private getCompanionIndex(): number {
|
||||
const companion = localUserStore.getCompanion();
|
||||
private updateSelectedCompanion(): void {
|
||||
this.selectedCompanion?.anims.pause();
|
||||
const companion = this.companions[this.currentCompanion];
|
||||
companion.play(this.companionModels[this.currentCompanion].name);
|
||||
this.selectedCompanion = companion;
|
||||
}
|
||||
|
||||
if (companion === null) {
|
||||
return 0;
|
||||
private moveCompanion(){
|
||||
for(let i = 0; i < this.companions.length; i++){
|
||||
const companion = this.companions[i];
|
||||
this.setUpCompanion(companion, i);
|
||||
}
|
||||
this.updateSelectedCompanion();
|
||||
}
|
||||
|
||||
return this.companionModels.findIndex(model => model !== null && model.name === companion);
|
||||
private moveToLeft(){
|
||||
if(this.currentCompanion === 0){
|
||||
return;
|
||||
}
|
||||
this.currentCompanion -= 1;
|
||||
this.moveCompanion();
|
||||
}
|
||||
|
||||
private moveToRight(){
|
||||
if(this.currentCompanion === (this.companions.length - 1)){
|
||||
return;
|
||||
}
|
||||
this.currentCompanion += 1;
|
||||
this.moveCompanion();
|
||||
}
|
||||
|
||||
private defineSetupCompanion(numero: number){
|
||||
const deltaX = 30;
|
||||
const deltaY = 2;
|
||||
let [companionX, companionY] = this.getCompanionPosition();
|
||||
let companionVisible = true;
|
||||
let companionScale = 1.5;
|
||||
let companionOpactity = 1;
|
||||
if( this.currentCompanion !== numero ){
|
||||
companionVisible = false;
|
||||
}
|
||||
if( numero === (this.currentCompanion + 1) ){
|
||||
companionY -= deltaY;
|
||||
companionX += deltaX;
|
||||
companionScale = 0.8;
|
||||
companionOpactity = 0.6;
|
||||
companionVisible = true;
|
||||
}
|
||||
if( numero === (this.currentCompanion + 2) ){
|
||||
companionY -= deltaY;
|
||||
companionX += (deltaX * 2);
|
||||
companionScale = 0.8;
|
||||
companionOpactity = 0.6;
|
||||
companionVisible = true;
|
||||
}
|
||||
if( numero === (this.currentCompanion - 1) ){
|
||||
companionY -= deltaY;
|
||||
companionX -= deltaX;
|
||||
companionScale = 0.8;
|
||||
companionOpactity = 0.6;
|
||||
companionVisible = true;
|
||||
}
|
||||
if( numero === (this.currentCompanion - 2) ){
|
||||
companionY -= deltaY;
|
||||
companionX -= (deltaX * 2);
|
||||
companionScale = 0.8;
|
||||
companionOpactity = 0.6;
|
||||
companionVisible = true;
|
||||
}
|
||||
return {companionX, companionY, companionScale, companionOpactity, companionVisible}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pixel position by on column and row number
|
||||
*/
|
||||
private getCompanionPosition(): [number, number] {
|
||||
return [
|
||||
this.game.renderer.width / 2,
|
||||
this.game.renderer.height / 3
|
||||
];
|
||||
}
|
||||
|
||||
private setUpCompanion(companion: Phaser.Physics.Arcade.Sprite, numero: number){
|
||||
|
||||
const {companionX, companionY, companionScale, companionOpactity, companionVisible} = this.defineSetupCompanion(numero);
|
||||
companion.setBounce(0.2);
|
||||
companion.setCollideWorldBounds(true);
|
||||
companion.setVisible( companionVisible );
|
||||
companion.setScale(companionScale, companionScale);
|
||||
companion.setAlpha(companionOpactity);
|
||||
companion.setX(companionX);
|
||||
companion.setY(companionY);
|
||||
}
|
||||
|
||||
private getMiddleX() : number{
|
||||
return (this.game.renderer.width / RESOLUTION) -
|
||||
(
|
||||
this.selectCompanionSceneElement
|
||||
&& this.selectCompanionSceneElement.node
|
||||
&& this.selectCompanionSceneElement.node.getBoundingClientRect().width > 0
|
||||
? (this.selectCompanionSceneElement.node.getBoundingClientRect().width / (2*RESOLUTION))
|
||||
: 150
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ export interface ITiledMap {
|
||||
* Map orientation (orthogonal)
|
||||
*/
|
||||
orientation: string;
|
||||
properties: ITiledMapLayerProperty[];
|
||||
properties?: ITiledMapLayerProperty[];
|
||||
|
||||
/**
|
||||
* Render order (right-down)
|
||||
@ -24,6 +24,11 @@ export interface ITiledMap {
|
||||
tilewidth: number;
|
||||
tilesets: ITiledTileSet[];
|
||||
version: number;
|
||||
compressionlevel?: number;
|
||||
infinite?: boolean;
|
||||
nextlayerid?: number;
|
||||
tiledversion?: string;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
export interface ITiledMapLayerProperty {
|
||||
@ -38,19 +43,35 @@ export interface ITiledMapLayerProperty {
|
||||
value: boolean
|
||||
}*/
|
||||
|
||||
export interface ITiledMapLayer {
|
||||
export type ITiledMapLayer = ITiledMapGroupLayer | ITiledMapObjectLayer | ITiledMapTileLayer;
|
||||
|
||||
export interface ITiledMapGroupLayer {
|
||||
id?: number,
|
||||
name: string;
|
||||
opacity: number;
|
||||
properties?: ITiledMapLayerProperty[];
|
||||
|
||||
type: "group";
|
||||
visible: boolean;
|
||||
x: number;
|
||||
y: number;
|
||||
/**
|
||||
* Layers for group layer
|
||||
*/
|
||||
layers: ITiledMapLayer[];
|
||||
}
|
||||
|
||||
export interface ITiledMapTileLayer {
|
||||
id?: number,
|
||||
data: number[]|string;
|
||||
height: number;
|
||||
name: string;
|
||||
opacity: number;
|
||||
properties: ITiledMapLayerProperty[];
|
||||
encoding: string;
|
||||
properties?: ITiledMapLayerProperty[];
|
||||
encoding?: string;
|
||||
compression?: string;
|
||||
|
||||
/**
|
||||
* Type of layer (tilelayer, objectgroup)
|
||||
*/
|
||||
type: string;
|
||||
type: "tilelayer";
|
||||
visible: boolean;
|
||||
width: number;
|
||||
x: number;
|
||||
@ -59,7 +80,28 @@ export interface ITiledMapLayer {
|
||||
/**
|
||||
* Draw order (topdown (default), index)
|
||||
*/
|
||||
draworder: string;
|
||||
draworder?: string;
|
||||
}
|
||||
|
||||
export interface ITiledMapObjectLayer {
|
||||
id?: number,
|
||||
height: number;
|
||||
name: string;
|
||||
opacity: number;
|
||||
properties?: ITiledMapLayerProperty[];
|
||||
encoding?: string;
|
||||
compression?: string;
|
||||
|
||||
type: "objectgroup";
|
||||
visible: boolean;
|
||||
width: number;
|
||||
x: number;
|
||||
y: number;
|
||||
|
||||
/**
|
||||
* Draw order (topdown (default), index)
|
||||
*/
|
||||
draworder?: string;
|
||||
objects: ITiledMapObject[];
|
||||
}
|
||||
|
||||
@ -94,6 +136,20 @@ export interface ITiledMapObject {
|
||||
* Polyline points
|
||||
*/
|
||||
polyline: {x: number, y: number}[];
|
||||
|
||||
text?: ITiledText
|
||||
}
|
||||
|
||||
export interface ITiledText {
|
||||
text: string,
|
||||
wrap?: boolean,
|
||||
fontfamily?: string,
|
||||
pixelsize?: number,
|
||||
color?: string,
|
||||
underline?: boolean,
|
||||
italic?: boolean,
|
||||
strikeout?: boolean,
|
||||
halign?: "center"|"right"|"justify"|"left"
|
||||
}
|
||||
|
||||
export interface ITiledTileSet {
|
||||
|
44
front/src/Phaser/Map/LayersIterator.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import {ITiledMap, ITiledMapLayer} from "./ITiledMap";
|
||||
|
||||
/**
|
||||
* Iterates over the layers of a map, flattening the grouped layers
|
||||
*/
|
||||
export class LayersIterator implements IterableIterator<ITiledMapLayer> {
|
||||
|
||||
private layers: ITiledMapLayer[] = [];
|
||||
private pointer: number = 0;
|
||||
|
||||
constructor(private map: ITiledMap) {
|
||||
this.initLayersList(map.layers, '');
|
||||
}
|
||||
|
||||
private initLayersList(layers : ITiledMapLayer[], prefix : string) {
|
||||
for (const layer of layers) {
|
||||
if (layer.type === 'group') {
|
||||
this.initLayersList(layer.layers, prefix + layer.name + '/');
|
||||
} else {
|
||||
const layerWithNewName = { ...layer };
|
||||
layerWithNewName.name = prefix+layerWithNewName.name;
|
||||
this.layers.push(layerWithNewName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public next(): IteratorResult<ITiledMapLayer> {
|
||||
if (this.pointer < this.layers.length) {
|
||||
return {
|
||||
done: false,
|
||||
value: this.layers[this.pointer++]
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
done: true,
|
||||
value: null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Symbol.iterator](): IterableIterator<ITiledMapLayer> {
|
||||
return new LayersIterator(this.map);
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import {mediaManager} from "../../WebRtc/MediaManager";
|
||||
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import { RESOLUTION } from "../../Enum/EnvironmentVariable";
|
||||
|
||||
export const HelpCameraSettingsSceneName = 'HelpCameraSettingsScene';
|
||||
const helpCameraSettings = 'helpCameraSettings';
|
||||
@ -20,16 +21,18 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
create(){
|
||||
localUserStore.setHelpCameraSettingsShown();
|
||||
this.createHelpCameraSettings();
|
||||
}
|
||||
|
||||
private createHelpCameraSettings() : void {
|
||||
const middleX = (window.innerWidth / 3) - (370*0.85);
|
||||
const middleX = this.getMiddleX();
|
||||
this.helpCameraSettingsElement = this.add.dom(middleX, -800, undefined, {overflow: 'scroll'}).createFromCache(helpCameraSettings);
|
||||
this.revealMenusAfterInit(this.helpCameraSettingsElement, helpCameraSettings);
|
||||
this.helpCameraSettingsElement.addListener('click');
|
||||
this.helpCameraSettingsElement.on('click', (event:MouseEvent) => {
|
||||
if((event?.target as HTMLInputElement).id === 'mailto') {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
if((event?.target as HTMLInputElement).id === 'helpCameraSettingsFormRefresh') {
|
||||
window.location.reload();
|
||||
@ -38,27 +41,30 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
||||
}
|
||||
});
|
||||
|
||||
if(!mediaManager.constraintsMedia.audio || !mediaManager.constraintsMedia.video){
|
||||
if(!localUserStore.getHelpCameraSettingsShown() && (!mediaManager.constraintsMedia.audio || !mediaManager.constraintsMedia.video)){
|
||||
this.openHelpCameraSettingsOpened();
|
||||
localUserStore.setHelpCameraSettingsShown();
|
||||
}
|
||||
|
||||
mediaManager.setHelpCameraSettingsCallBack(() => {
|
||||
this.openHelpCameraSettingsOpened();
|
||||
});
|
||||
}
|
||||
|
||||
private openHelpCameraSettingsOpened(): void{
|
||||
HtmlUtils.getElementByIdOrFail<HTMLDivElement>('webRtcSetup').style.display = 'none';
|
||||
this.helpCameraSettingsOpened = true;
|
||||
let middleY = (window.innerHeight / 3) - (495);
|
||||
if(middleY < 0){
|
||||
middleY = 0;
|
||||
}
|
||||
let middleX = (window.innerWidth / 3) - (370*0.85);
|
||||
if(middleX < 0){
|
||||
middleX = 0;
|
||||
}
|
||||
if(window.navigator.userAgent.includes('Firefox')){
|
||||
HtmlUtils.getElementByIdOrFail<HTMLParagraphElement>('browserHelpSetting').innerHTML ='<img src="/resources/objects/help-setting-camera-permission-firefox.png"/>';
|
||||
}else if(window.navigator.userAgent.includes('Chrome')){
|
||||
HtmlUtils.getElementByIdOrFail<HTMLParagraphElement>('browserHelpSetting').innerHTML ='<img src="/resources/objects/help-setting-camera-permission-chrome.png"/>';
|
||||
try{
|
||||
if(window.navigator.userAgent.includes('Firefox')){
|
||||
HtmlUtils.getElementByIdOrFail<HTMLParagraphElement>('browserHelpSetting').innerHTML ='<img src="/resources/objects/help-setting-camera-permission-firefox.png"/>';
|
||||
}else if(window.navigator.userAgent.includes('Chrome')){
|
||||
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 middleX = this.getMiddleX();
|
||||
this.tweens.add({
|
||||
targets: this.helpCameraSettingsElement,
|
||||
y: middleY,
|
||||
@ -70,13 +76,15 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
private closeHelpCameraSettingsOpened(): void{
|
||||
const helpCameraSettingsInfo = this.helpCameraSettingsElement.getChildByID('helpCameraSettings') as HTMLParagraphElement;
|
||||
const middleX = this.getMiddleX();
|
||||
/*const helpCameraSettingsInfo = this.helpCameraSettingsElement.getChildByID('helpCameraSettings') as HTMLParagraphElement;
|
||||
helpCameraSettingsInfo.innerText = '';
|
||||
helpCameraSettingsInfo.style.display = 'none';
|
||||
helpCameraSettingsInfo.style.display = 'none';*/
|
||||
this.helpCameraSettingsOpened = false;
|
||||
this.tweens.add({
|
||||
targets: this.helpCameraSettingsElement,
|
||||
y: -400,
|
||||
y: -1000,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: 'Power3',
|
||||
overflow: 'scroll'
|
||||
@ -91,5 +99,51 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
||||
}, 250);
|
||||
}
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
if(this.helpCameraSettingsOpened){
|
||||
const middleX = this.getMiddleX();
|
||||
const middleY = this.getMiddleY();
|
||||
this.tweens.add({
|
||||
targets: this.helpCameraSettingsElement,
|
||||
x: middleX,
|
||||
y: middleY,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public onResize(ev: UIEvent): void {
|
||||
const middleX = this.getMiddleX();
|
||||
const middleY = this.getMiddleY();
|
||||
this.tweens.add({
|
||||
targets: this.helpCameraSettingsElement,
|
||||
x: middleX,
|
||||
y: middleY,
|
||||
duration: 1000,
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
private getMiddleX() : number{
|
||||
return (this.game.renderer.width / RESOLUTION) -
|
||||
(
|
||||
this.helpCameraSettingsElement
|
||||
&& this.helpCameraSettingsElement.node
|
||||
&& this.helpCameraSettingsElement.node.getBoundingClientRect().width > 0
|
||||
? (this.helpCameraSettingsElement.node.getBoundingClientRect().width / 4)
|
||||
: (400 / 2)
|
||||
);
|
||||
}
|
||||
|
||||
private getMiddleY() : number{
|
||||
const middleY = ((window.innerHeight) - (
|
||||
(this.helpCameraSettingsElement
|
||||
&& this.helpCameraSettingsElement.node
|
||||
&& this.helpCameraSettingsElement.node.getBoundingClientRect().height > 0
|
||||
? this.helpCameraSettingsElement.node.getBoundingClientRect().height : 400 /*FIXME to use a const will be injected in HTMLElement*/)*2)) / 2;
|
||||
return (middleY > 0 ? middleY / RESOLUTION : 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ const gameMenuIconKey = 'gameMenuIcon';
|
||||
const gameSettingsMenuKey = 'gameSettingsMenu';
|
||||
const gameShare = 'gameShare';
|
||||
|
||||
const closedSideMenuX = -200;
|
||||
const closedSideMenuX = -1000;
|
||||
const openedSideMenuX = 0;
|
||||
|
||||
/**
|
||||
@ -118,7 +118,8 @@ export class MenuScene extends Phaser.Scene {
|
||||
this.closeAll();
|
||||
this.sideMenuOpened = true;
|
||||
this.menuButton.getChildByID('openMenuButton').innerHTML = 'X';
|
||||
if (gameManager.getCurrentGameScene(this).connection && gameManager.getCurrentGameScene(this).connection.isAdmin()) {
|
||||
const connection = gameManager.getCurrentGameScene(this).connection;
|
||||
if (connection && connection.isAdmin()) {
|
||||
const adminSection = this.menuElement.getChildByID('adminConsoleSection') as HTMLElement;
|
||||
adminSection.hidden = false;
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ export class ReportMenu extends Phaser.GameObjects.DOMElement {
|
||||
gamePError.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
gameManager.getCurrentGameScene(this.scene).connection.emitReportPlayerMessage(
|
||||
gameManager.getCurrentGameScene(this.scene).connection?.emitReportPlayerMessage(
|
||||
this.userId,
|
||||
gameTextArea.value
|
||||
);
|
||||
|
@ -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.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',
|
||||
fontSize: '10px'
|
||||
});
|
||||
|
@ -346,7 +346,7 @@ class LayoutManager {
|
||||
userInputManager.addSpaceEventListner(callBack);
|
||||
}
|
||||
|
||||
public removeActionButton(id: string, userInputManager: UserInputManager){
|
||||
public removeActionButton(id: string, userInputManager?: UserInputManager){
|
||||
//delete previous element
|
||||
const previousDiv = this.actionButtonInformation.get(id);
|
||||
if(previousDiv){
|
||||
@ -354,10 +354,45 @@ class LayoutManager {
|
||||
this.actionButtonInformation.delete(id);
|
||||
}
|
||||
const previousEventCallback = this.actionButtonTrigger.get(id);
|
||||
if(previousEventCallback){
|
||||
if(previousEventCallback && userInputManager){
|
||||
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();
|
||||
|
@ -4,6 +4,8 @@ import {discussionManager, SendMessageCallback} from "./DiscussionManager";
|
||||
import {UserInputManager} from "../Phaser/UserInput/UserInputManager";
|
||||
import {localUserStore} from "../Connexion/LocalUserStore";
|
||||
import {UserSimplePeerInterface} from "./SimplePeer";
|
||||
import {SoundMeter} from "../Phaser/Components/SoundMeter";
|
||||
|
||||
declare const navigator:any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
let videoConstraint: boolean|MediaTrackConstraints = {
|
||||
@ -26,6 +28,7 @@ export type StartScreenSharingCallback = (media: MediaStream) => void;
|
||||
export type StopScreenSharingCallback = (media: MediaStream) => void;
|
||||
export type ReportCallback = (message: string) => 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)
|
||||
export class MediaManager {
|
||||
@ -40,6 +43,7 @@ export class MediaManager {
|
||||
microphoneClose: HTMLImageElement;
|
||||
microphone: HTMLImageElement;
|
||||
webrtcInAudio: HTMLAudioElement;
|
||||
mySoundMeterElement: HTMLDivElement;
|
||||
private webrtcOutAudio: HTMLAudioElement;
|
||||
constraintsMedia : MediaStreamConstraints = {
|
||||
audio: audioConstraint,
|
||||
@ -49,6 +53,8 @@ export class MediaManager {
|
||||
startScreenSharingCallBacks : Set<StartScreenSharingCallback> = new Set<StartScreenSharingCallback>();
|
||||
stopScreenSharingCallBacks : Set<StopScreenSharingCallback> = new Set<StopScreenSharingCallback>();
|
||||
showReportModalCallBacks : Set<ShowReportCallBack> = new Set<ShowReportCallBack>();
|
||||
helpCameraSettingsCallBacks : Set<HelpCameraSettingsCallBack> = new Set<HelpCameraSettingsCallBack>();
|
||||
|
||||
private microphoneBtn: HTMLDivElement;
|
||||
private cinemaBtn: HTMLDivElement;
|
||||
private monitorBtn: HTMLDivElement;
|
||||
@ -63,6 +69,12 @@ export class MediaManager {
|
||||
|
||||
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() {
|
||||
|
||||
this.myCamVideo = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideo');
|
||||
@ -121,10 +133,16 @@ export class MediaManager {
|
||||
this.pingCameraStatus();
|
||||
|
||||
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.updateSoudMeter();
|
||||
}
|
||||
|
||||
public blurCamera() {
|
||||
@ -225,6 +243,10 @@ export class MediaManager {
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
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) => {
|
||||
console.error(err);
|
||||
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.monitor.style.display = "none";
|
||||
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(() => {
|
||||
console.info('Error get camera, trying with video option at null');
|
||||
return this.getLocalStream().catch((err) => {
|
||||
console.info('Error get camera, trying with video option at null =>', err);
|
||||
this.disableCameraStyle();
|
||||
return this.getLocalStream().then((stream : MediaStream) => {
|
||||
this.hasCamera = false;
|
||||
return stream;
|
||||
}).catch((err) => {
|
||||
this.disableMicrophoneStyle();
|
||||
console.info("error get media ", this.constraintsMedia.video, this.constraintsMedia.audio, err);
|
||||
throw err;
|
||||
});
|
||||
@ -425,6 +456,13 @@ export class MediaManager {
|
||||
return navigator.mediaDevices.getUserMedia(this.constraintsMedia).then((stream : MediaStream) => {
|
||||
this.localStream = stream;
|
||||
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;
|
||||
}).catch((err: Error) => {
|
||||
throw err;
|
||||
@ -451,6 +489,7 @@ export class MediaManager {
|
||||
track.stop();
|
||||
}
|
||||
}
|
||||
this.mySoundMeter?.stop();
|
||||
}
|
||||
|
||||
setCamera(id: string): Promise<MediaStream> {
|
||||
@ -496,6 +535,13 @@ export class MediaManager {
|
||||
</button>
|
||||
<video id="${userId}" autoplay></video>
|
||||
<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>
|
||||
`;
|
||||
|
||||
@ -585,6 +631,12 @@ export class MediaManager {
|
||||
throw `Unable to find video for ${userId}`;
|
||||
}
|
||||
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){
|
||||
// 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);
|
||||
this.remoteVideo.delete(userId);
|
||||
|
||||
this.soundMeters.get(userId)?.stop();
|
||||
this.soundMeters.delete(userId);
|
||||
this.soundMeterElements.delete(userId);
|
||||
|
||||
//permit to remove user in discussion part
|
||||
this.removeParticipant(userId);
|
||||
}
|
||||
@ -717,6 +773,7 @@ export class MediaManager {
|
||||
}
|
||||
|
||||
public setUserInputManager(userInputManager : UserInputManager){
|
||||
this.userInputManager = userInputManager;
|
||||
discussionManager.setUserInputManager(userInputManager);
|
||||
}
|
||||
//check if user is active
|
||||
@ -739,6 +796,57 @@ export class MediaManager {
|
||||
public setShowReportModalCallBacks(callback: ShowReportCallBack){
|
||||
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();
|
||||
|
@ -82,15 +82,11 @@ export class SimplePeer {
|
||||
});
|
||||
|
||||
mediaManager.showGameOverlay();
|
||||
mediaManager.getCamera().then(() => {
|
||||
|
||||
mediaManager.getCamera().finally(() => {
|
||||
//receive message start
|
||||
this.Connection.receiveWebrtcStart((message: UserSimplePeerInterface) => {
|
||||
this.receiveWebrtcStart(message);
|
||||
});
|
||||
|
||||
}).catch((err) => {
|
||||
console.error("err", err);
|
||||
});
|
||||
|
||||
this.Connection.disconnectMessage((data: WebRtcDisconnectMessageInterface): void => {
|
||||
|
@ -2,7 +2,7 @@ import 'phaser';
|
||||
import GameConfig = Phaser.Types.Core.GameConfig;
|
||||
import "../dist/resources/style/index.scss";
|
||||
|
||||
import {DEBUG_MODE, RESOLUTION} from "./Enum/EnvironmentVariable";
|
||||
import {DEBUG_MODE, isMobile, RESOLUTION} from "./Enum/EnvironmentVariable";
|
||||
import {LoginScene} from "./Phaser/Login/LoginScene";
|
||||
import {ReconnectingScene} from "./Phaser/Reconnecting/ReconnectingScene";
|
||||
import {SelectCharacterScene} from "./Phaser/Login/SelectCharacterScene";
|
||||
@ -17,6 +17,7 @@ import {HelpCameraSettingsScene} from "./Phaser/Menu/HelpCameraSettingsScene";
|
||||
import {localUserStore} from "./Connexion/LocalUserStore";
|
||||
import {ErrorScene} from "./Phaser/Reconnecting/ErrorScene";
|
||||
import {iframeListener} from "./Api/IframeListener";
|
||||
import { SelectCharacterMobileScene } from './Phaser/Login/SelectCharacterMobileScene';
|
||||
import {HdpiManager} from "./Phaser/Services/HdpiManager";
|
||||
import {waScaleManager} from "./Phaser/Services/WaScaleManager";
|
||||
|
||||
@ -83,7 +84,16 @@ const config: GameConfig = {
|
||||
autoRound: true,
|
||||
resizeInterval: 999999999999
|
||||
},
|
||||
scene: [EntryScene, LoginScene, SelectCharacterScene, SelectCompanionScene, EnableCameraScene, ReconnectingScene, ErrorScene, CustomizeScene, MenuScene, HelpCameraSettingsScene],
|
||||
scene: [EntryScene,
|
||||
LoginScene,
|
||||
isMobile() ? SelectCharacterMobileScene : SelectCharacterScene,
|
||||
SelectCompanionScene,
|
||||
EnableCameraScene,
|
||||
ReconnectingScene,
|
||||
ErrorScene,
|
||||
CustomizeScene,
|
||||
MenuScene,
|
||||
HelpCameraSettingsScene],
|
||||
//resolution: window.devicePixelRatio / 2,
|
||||
fps: fps,
|
||||
dom: {
|
||||
|
147
front/tests/Phaser/Map/LayersIteratorTest.ts
Normal file
@ -0,0 +1,147 @@
|
||||
import "jasmine";
|
||||
import {Room} from "../../../src/Connexion/Room";
|
||||
import {LayersIterator} from "../../../src/Phaser/Map/LayersIterator";
|
||||
|
||||
describe("Layers iterator", () => {
|
||||
it("should iterate maps with no group", () => {
|
||||
const layersIterator = new LayersIterator({
|
||||
"compressionlevel":-1,
|
||||
"height":2,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[0, 0, 0, 0],
|
||||
"height":2,
|
||||
"id":1,
|
||||
"name":"Tile Layer 1",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":2,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0],
|
||||
"height":2,
|
||||
"id":1,
|
||||
"name":"Tile Layer 2",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":2,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":2,
|
||||
"nextobjectid":1,
|
||||
"orientation":"orthogonal",
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"2021.03.23",
|
||||
"tileheight":32,
|
||||
"tilesets":[],
|
||||
"tilewidth":32,
|
||||
"type":"map",
|
||||
"version":1.5,
|
||||
"width":2
|
||||
})
|
||||
|
||||
const layers = [];
|
||||
for (const layer of layersIterator) {
|
||||
layers.push(layer.name);
|
||||
}
|
||||
expect(layers).toEqual(['Tile Layer 1', 'Tile Layer 2']);
|
||||
});
|
||||
|
||||
it("should iterate maps with recursive groups", () => {
|
||||
const layersIterator = new LayersIterator({
|
||||
"compressionlevel":-1,
|
||||
"height":2,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"id":6,
|
||||
"layers":[
|
||||
{
|
||||
"id":5,
|
||||
"layers":[
|
||||
{
|
||||
"data":[0, 0, 0, 0],
|
||||
"height":2,
|
||||
"id":10,
|
||||
"name":"Tile3",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":2,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0],
|
||||
"height":2,
|
||||
"id":9,
|
||||
"name":"Tile2",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":2,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"name":"Group 3",
|
||||
"opacity":1,
|
||||
"type":"group",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"id":7,
|
||||
"layers":[
|
||||
{
|
||||
"data":[0, 0, 0, 0],
|
||||
"height":2,
|
||||
"id":8,
|
||||
"name":"Tile1",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":2,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"name":"Group 2",
|
||||
"opacity":1,
|
||||
"type":"group",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"name":"Group 1",
|
||||
"opacity":1,
|
||||
"type":"group",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":11,
|
||||
"nextobjectid":1,
|
||||
"orientation":"orthogonal",
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"2021.03.23",
|
||||
"tileheight":32,
|
||||
"tilesets":[],
|
||||
"tilewidth":32,
|
||||
"type":"map",
|
||||
"version":1.5,
|
||||
"width":2
|
||||
})
|
||||
|
||||
const layers = [];
|
||||
for (const layer of layersIterator) {
|
||||
layers.push(layer.name);
|
||||
}
|
||||
expect(layers).toEqual(['Group 1/Group 3/Tile3', 'Group 1/Group 3/Tile2', 'Group 1/Group 2/Tile1']);
|
||||
});
|
||||
});
|
@ -1942,7 +1942,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
|
||||
assign-symbols "^1.0.0"
|
||||
is-extendable "^1.0.1"
|
||||
|
||||
extend@^3.0.2:
|
||||
extend@^3.0.1, extend@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
|
||||
@ -4026,15 +4026,15 @@ quill-delta@^3.6.2:
|
||||
extend "^3.0.2"
|
||||
fast-diff "1.1.2"
|
||||
|
||||
quill@^1.3.7:
|
||||
version "1.3.7"
|
||||
resolved "https://registry.yarnpkg.com/quill/-/quill-1.3.7.tgz#da5b2f3a2c470e932340cdbf3668c9f21f9286e8"
|
||||
integrity sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==
|
||||
quill@1.3.6:
|
||||
version "1.3.6"
|
||||
resolved "https://registry.yarnpkg.com/quill/-/quill-1.3.6.tgz#99f4de1fee85925a0d7d4163b6d8328f23317a4d"
|
||||
integrity sha512-K0mvhimWZN6s+9OQ249CH2IEPZ9JmkFuCQeHAOQax3EZ2nDJ3wfGh59mnlQaZV2i7u8eFarx6wAtvQKgShojug==
|
||||
dependencies:
|
||||
clone "^2.1.1"
|
||||
deep-equal "^1.0.1"
|
||||
eventemitter3 "^2.0.3"
|
||||
extend "^3.0.2"
|
||||
extend "^3.0.1"
|
||||
parchment "^1.1.4"
|
||||
quill-delta "^3.6.2"
|
||||
|
||||
@ -4647,9 +4647,9 @@ sprintf-js@~1.0.2:
|
||||
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
||||
|
||||
ssri@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
|
||||
integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"
|
||||
integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==
|
||||
dependencies:
|
||||
figgy-pudding "^3.5.1"
|
||||
|
||||
|
@ -260,15 +260,15 @@
|
||||
"name":"floorLayer",
|
||||
"objects":[
|
||||
{
|
||||
"height":199.667,
|
||||
"height":140,
|
||||
"id":1,
|
||||
"name":"Tutobubble",
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":245.667,
|
||||
"x":1170,
|
||||
"y":350
|
||||
"width":185,
|
||||
"x":1022,
|
||||
"y":308
|
||||
},
|
||||
{
|
||||
"height":86.9996666666667,
|
||||
@ -277,9 +277,9 @@
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":245.667,
|
||||
"x":1171,
|
||||
"y":412
|
||||
"width":187,
|
||||
"x":1019,
|
||||
"y":361
|
||||
},
|
||||
{
|
||||
"height":84.6667,
|
||||
@ -288,9 +288,9 @@
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":210.667,
|
||||
"x":1030.5,
|
||||
"y":318.66665
|
||||
"width":184.5,
|
||||
"x":1023,
|
||||
"y":319
|
||||
},
|
||||
{
|
||||
"height":99.6667,
|
||||
@ -299,9 +299,9 @@
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":210.667,
|
||||
"x":1174,
|
||||
"y":400
|
||||
"width":185,
|
||||
"x":1021,
|
||||
"y":348
|
||||
}],
|
||||
"opacity":1,
|
||||
"type":"objectgroup",
|
||||
|
Before Width: | Height: | Size: 3.8 KiB |
BIN
maps/Village/logo-WA.png
Normal file
After Width: | Height: | Size: 5.1 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
|
||||
}
|
BIN
maps/tests/Validation/Yellow Dungeon Tileset.jpg
Normal file
After Width: | Height: | Size: 28 KiB |
64
maps/tests/Validation/dungeon.tsx
Normal file
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<tileset version="1.4" tiledversion="1.4.3" name="dungeon" tilewidth="32" tileheight="32" tilecount="64" columns="8">
|
||||
<image source="tileset_dungeon.png" width="256" height="256"/>
|
||||
<tile id="0">
|
||||
<properties>
|
||||
<property name="collides" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
<tile id="1">
|
||||
<properties>
|
||||
<property name="collides" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
<tile id="2">
|
||||
<properties>
|
||||
<property name="collides" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
<tile id="3">
|
||||
<properties>
|
||||
<property name="collides" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
<tile id="8">
|
||||
<properties>
|
||||
<property name="collides" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
<tile id="9">
|
||||
<properties>
|
||||
<property name="collides" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
<tile id="10">
|
||||
<properties>
|
||||
<property name="collides" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
<tile id="11">
|
||||
<properties>
|
||||
<property name="collides" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
<tile id="16">
|
||||
<properties>
|
||||
<property name="collides" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
<tile id="17">
|
||||
<properties>
|
||||
<property name="collides" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
<tile id="18">
|
||||
<properties>
|
||||
<property name="collides" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
<tile id="19">
|
||||
<properties>
|
||||
<property name="collides" type="bool" value="true"/>
|
||||
</properties>
|
||||
</tile>
|
||||
</tileset>
|