Merge pull request #933 from ClementVieilly75/SoundInMapScript

Sound in map script
This commit is contained in:
David Négrier 2021-05-26 16:25:50 +02:00 committed by GitHub
commit 474323b95f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 417 additions and 14 deletions

View File

@ -8,7 +8,7 @@
### Updates ### Updates
- Added the emote feature to Workadventure. (@Kharhamel, @Tabascoeye) - Added the emote feature to WorkAdventure. (@Kharhamel, @Tabascoeye)
- The emote menu can be opened by clicking on your character. - The emote menu can be opened by clicking on your character.
- Clicking on one of its element will close the menu and play an emote above your character. - Clicking on one of its element will close the menu and play an emote above your character.
- This emote can be seen by other players. - This emote can be seen by other players.
@ -17,7 +17,8 @@
- Mouse wheel support to zoom in / out - Mouse wheel support to zoom in / out
- Pinch support on mobile to zoom in / out - Pinch support on mobile to zoom in / out
- Improved virtual joystick size (adapts to the zoom level) - Improved virtual joystick size (adapts to the zoom level)
- New scripting API features:
- Use `WA.loadSound(): Sound` to load / play / stop a sound
### Bug Fixes ### Bug Fixes

View File

@ -9,6 +9,8 @@ import type { OpenCoWebSiteEvent } from './OpenCoWebSiteEvent';
import type { OpenPopupEvent } from './OpenPopupEvent'; import type { OpenPopupEvent } from './OpenPopupEvent';
import type { OpenTabEvent } from './OpenTabEvent'; import type { OpenTabEvent } from './OpenTabEvent';
import type { UserInputChatEvent } from './UserInputChatEvent'; import type { UserInputChatEvent } from './UserInputChatEvent';
import type {LoadSoundEvent} from "./LoadSoundEvent";
import type {PlaySoundEvent} from "./PlaySoundEvent";
export interface TypedMessageEvent<T> extends MessageEvent { export interface TypedMessageEvent<T> extends MessageEvent {
@ -29,6 +31,9 @@ export type IframeEventMap = {
restorePlayerControls: null restorePlayerControls: null
displayBubble: null displayBubble: null
removeBubble: null removeBubble: null
loadSound: LoadSoundEvent
playSound: PlaySoundEvent
stopSound: null
} }
export interface IframeEvent<T extends keyof IframeEventMap> { export interface IframeEvent<T extends keyof IframeEventMap> {
type: T; type: T;

View File

@ -0,0 +1,11 @@
import * as tg from "generic-type-guard";
export const isLoadSoundEvent =
new tg.IsInterface().withProperties({
url: tg.isString,
}).get();
/**
* A message sent from the iFrame to the game to add a message in the chat.
*/
export type LoadSoundEvent = tg.GuardedType<typeof isLoadSoundEvent>;

View File

@ -0,0 +1,24 @@
import * as tg from "generic-type-guard";
const isSoundConfig =
new tg.IsInterface().withProperties({
volume: tg.isOptional(tg.isNumber),
loop: tg.isOptional(tg.isBoolean),
mute: tg.isOptional(tg.isBoolean),
rate: tg.isOptional(tg.isNumber),
detune: tg.isOptional(tg.isNumber),
seek: tg.isOptional(tg.isNumber),
delay: tg.isOptional(tg.isNumber)
}).get();
export const isPlaySoundEvent =
new tg.IsInterface().withProperties({
url: tg.isString,
config : tg.isOptional(isSoundConfig),
}).get();
/**
* A message sent from the iFrame to the game to add a message in the chat.
*/
export type PlaySoundEvent = tg.GuardedType<typeof isPlaySoundEvent>;

View File

@ -0,0 +1,11 @@
import * as tg from "generic-type-guard";
export const isStopSoundEvent =
new tg.IsInterface().withProperties({
url: tg.isString,
}).get();
/**
* A message sent from the iFrame to the game to add a message in the chat.
*/
export type StopSoundEvent = tg.GuardedType<typeof isStopSoundEvent>;

View File

@ -1,3 +1,4 @@
import { Subject } from "rxjs"; import { Subject } from "rxjs";
import { ChatEvent, isChatEvent } from "./Events/ChatEvent"; import { ChatEvent, isChatEvent } from "./Events/ChatEvent";
import { HtmlUtils } from "../WebRtc/HtmlUtils"; import { HtmlUtils } from "../WebRtc/HtmlUtils";
@ -11,8 +12,9 @@ import { GoToPageEvent, isGoToPageEvent } from "./Events/GoToPageEvent";
import { isOpenCoWebsite, OpenCoWebSiteEvent } from "./Events/OpenCoWebSiteEvent"; import { isOpenCoWebsite, OpenCoWebSiteEvent } from "./Events/OpenCoWebSiteEvent";
import { IframeEventMap, IframeEvent, IframeResponseEvent, IframeResponseEventMap, isIframeEventWrapper, TypedMessageEvent } from "./Events/IframeEvent"; import { IframeEventMap, IframeEvent, IframeResponseEvent, IframeResponseEventMap, isIframeEventWrapper, TypedMessageEvent } from "./Events/IframeEvent";
import type { UserInputChatEvent } from "./Events/UserInputChatEvent"; import type { UserInputChatEvent } from "./Events/UserInputChatEvent";
import {isPlaySoundEvent, PlaySoundEvent} from "./Events/PlaySoundEvent";
import {isStopSoundEvent, StopSoundEvent} from "./Events/StopSoundEvent";
import {isLoadSoundEvent, LoadSoundEvent} from "./Events/LoadSoundEvent";
/** /**
* Listens to messages from iframes and turn those messages into easy to use observables. * Listens to messages from iframes and turn those messages into easy to use observables.
* Also allows to send messages to those iframes. * Also allows to send messages to those iframes.
@ -51,6 +53,15 @@ class IframeListener {
private readonly _removeBubbleStream: Subject<void> = new Subject(); private readonly _removeBubbleStream: Subject<void> = new Subject();
public readonly removeBubbleStream = this._removeBubbleStream.asObservable(); public readonly removeBubbleStream = this._removeBubbleStream.asObservable();
private readonly _playSoundStream: Subject<PlaySoundEvent> = new Subject();
public readonly playSoundStream = this._playSoundStream.asObservable();
private readonly _stopSoundStream: Subject<StopSoundEvent> = new Subject();
public readonly stopSoundStream = this._stopSoundStream.asObservable();
private readonly _loadSoundStream: Subject<LoadSoundEvent> = new Subject();
public readonly loadSoundStream = this._loadSoundStream.asObservable();
private readonly iframes = new Set<HTMLIFrameElement>(); private readonly iframes = new Set<HTMLIFrameElement>();
private readonly scripts = new Map<string, HTMLIFrameElement>(); private readonly scripts = new Map<string, HTMLIFrameElement>();
@ -85,6 +96,15 @@ class IframeListener {
else if (payload.type === 'goToPage' && isGoToPageEvent(payload.data)) { else if (payload.type === 'goToPage' && isGoToPageEvent(payload.data)) {
scriptUtils.goToPage(payload.data.url); scriptUtils.goToPage(payload.data.url);
} }
else if (payload.type === 'playSound' && isPlaySoundEvent(payload.data)) {
this._playSoundStream.next(payload.data);
}
else if (payload.type === 'stopSound' && isStopSoundEvent(payload.data)) {
this._stopSoundStream.next(payload.data);
}
else if (payload.type === 'loadSound' && isLoadSoundEvent(payload.data)) {
this._loadSoundStream.next(payload.data);
}
else if (payload.type === 'openCoWebSite' && isOpenCoWebsite(payload.data)) { else if (payload.type === 'openCoWebSite' && isOpenCoWebsite(payload.data)) {
const scriptUrl = [...this.scripts.keys()].find(key => { const scriptUrl = [...this.scripts.keys()].find(key => {
return this.scripts.get(key)?.contentWindow == message.source return this.scripts.get(key)?.contentWindow == message.source
@ -92,9 +112,11 @@ class IframeListener {
scriptUtils.openCoWebsite(payload.data.url, scriptUrl || foundSrc); scriptUtils.openCoWebsite(payload.data.url, scriptUrl || foundSrc);
} }
else if (payload.type === 'closeCoWebSite') { else if (payload.type === 'closeCoWebSite') {
scriptUtils.closeCoWebSite(); scriptUtils.closeCoWebSite();
} }
else if (payload.type === 'disablePlayerControls') { else if (payload.type === 'disablePlayerControls') {
this._disablePlayerControlStream.next(); this._disablePlayerControlStream.next();
} }

View File

@ -52,6 +52,7 @@ import {mediaManager} from "../../WebRtc/MediaManager";
import type {ItemFactoryInterface} from "../Items/ItemFactoryInterface"; import type {ItemFactoryInterface} from "../Items/ItemFactoryInterface";
import type {ActionableItem} from "../Items/ActionableItem"; import type {ActionableItem} from "../Items/ActionableItem";
import {UserInputManager} from "../UserInput/UserInputManager"; import {UserInputManager} from "../UserInput/UserInputManager";
import {soundManager} from "./SoundManager";
import type {UserMovedMessage} from "../../Messages/generated/messages_pb"; import type {UserMovedMessage} from "../../Messages/generated/messages_pb";
import {ProtobufClientUtils} from "../../Network/ProtobufClientUtils"; import {ProtobufClientUtils} from "../../Network/ProtobufClientUtils";
import {connectionManager} from "../../Connexion/ConnectionManager"; import {connectionManager} from "../../Connexion/ConnectionManager";
@ -874,9 +875,28 @@ ${escapedMessage}
this.userInputManager.disableControls(); this.userInputManager.disableControls();
})); }));
this.iframeSubscriptionList.push(iframeListener.playSoundStream.subscribe((playSoundEvent)=>
{
const url = new URL(playSoundEvent.url, this.MapUrlFile);
soundManager.playSound(this.load,this.sound,url.toString(),playSoundEvent.config);
}))
this.iframeSubscriptionList.push(iframeListener.stopSoundStream.subscribe((stopSoundEvent)=>
{
const url = new URL(stopSoundEvent.url, this.MapUrlFile);
soundManager.stopSound(this.sound,url.toString());
}))
this.iframeSubscriptionList.push(iframeListener.loadSoundStream.subscribe((loadSoundEvent)=>
{
const url = new URL(loadSoundEvent.url, this.MapUrlFile);
soundManager.loadSound(this.load,this.sound,url.toString());
}))
this.iframeSubscriptionList.push(iframeListener.enablePlayerControlStream.subscribe(()=>{ this.iframeSubscriptionList.push(iframeListener.enablePlayerControlStream.subscribe(()=>{
this.userInputManager.restoreControls(); this.userInputManager.restoreControls();
})); }));
let scriptedBubbleSprite : Sprite; let scriptedBubbleSprite : Sprite;
this.iframeSubscriptionList.push(iframeListener.displayBubbleStream.subscribe(()=>{ this.iframeSubscriptionList.push(iframeListener.displayBubbleStream.subscribe(()=>{
scriptedBubbleSprite = new Sprite(this,this.CurrentPlayer.x + 25,this.CurrentPlayer.y,'circleSprite-white'); scriptedBubbleSprite = new Sprite(this,this.CurrentPlayer.x + 25,this.CurrentPlayer.y,'circleSprite-white');

View File

@ -0,0 +1,37 @@
import LoaderPlugin = Phaser.Loader.LoaderPlugin;
import BaseSoundManager = Phaser.Sound.BaseSoundManager;
import BaseSound = Phaser.Sound.BaseSound;
import SoundConfig = Phaser.Types.Sound.SoundConfig;
class SoundManager {
private soundPromises : Map<string,Promise<BaseSound>> = new Map<string, Promise<Phaser.Sound.BaseSound>>();
public loadSound (loadPlugin: LoaderPlugin, soundManager : BaseSoundManager, soundUrl: string) : Promise<BaseSound> {
let soundPromise = this.soundPromises.get(soundUrl);
if (soundPromise !== undefined) {
return soundPromise;
}
soundPromise = new Promise<BaseSound>((res) => {
const sound = soundManager.get(soundUrl);
if (sound !== null) {
return res(sound);
}
loadPlugin.audio(soundUrl, soundUrl);
loadPlugin.once('filecomplete-audio-' + soundUrl, () => res(soundManager.add(soundUrl)));
loadPlugin.start();
});
this.soundPromises.set(soundUrl,soundPromise);
return soundPromise;
}
public async playSound(loadPlugin: LoaderPlugin, soundManager : BaseSoundManager, soundUrl: string, config: SoundConfig|undefined) : Promise<void> {
const sound = await this.loadSound(loadPlugin,soundManager,soundUrl);
if (config === undefined) sound.play();
else sound.play(config);
}
public stopSound(soundManager : BaseSoundManager,soundUrl : string){
soundManager.get(soundUrl).stop();
}
}
export const soundManager = new SoundManager();

View File

@ -9,6 +9,10 @@ import type { ClosePopupEvent } from "./Api/Events/ClosePopupEvent";
import type { OpenTabEvent } from "./Api/Events/OpenTabEvent"; import type { OpenTabEvent } from "./Api/Events/OpenTabEvent";
import type { GoToPageEvent } from "./Api/Events/GoToPageEvent"; import type { GoToPageEvent } from "./Api/Events/GoToPageEvent";
import type { OpenCoWebSiteEvent } from "./Api/Events/OpenCoWebSiteEvent"; import type { OpenCoWebSiteEvent } from "./Api/Events/OpenCoWebSiteEvent";
import type {PlaySoundEvent} from "./Api/Events/PlaySoundEvent";
import type {StopSoundEvent} from "./Api/Events/StopSoundEvent";
import type {LoadSoundEvent} from "./Api/Events/LoadSoundEvent";
import SoundConfig = Phaser.Types.Sound.SoundConfig;
interface WorkAdventureApi { interface WorkAdventureApi {
sendChatMessage(message: string, author: string): void; sendChatMessage(message: string, author: string): void;
@ -24,6 +28,7 @@ interface WorkAdventureApi {
restorePlayerControls(): void; restorePlayerControls(): void;
displayBubble(): void; displayBubble(): void;
removeBubble(): void; removeBubble(): void;
loadSound(url : string): Sound;
} }
declare global { declare global {
@ -57,7 +62,7 @@ interface ButtonDescriptor {
callback: ButtonClickedCallback, callback: ButtonClickedCallback,
} }
class Popup { export class Popup {
constructor(private id: number) { constructor(private id: number) {
} }
@ -74,6 +79,41 @@ class Popup {
} }
} }
export class Sound {
constructor(private url: string) {
window.parent.postMessage({
"type" : 'loadSound',
"data": {
url: this.url,
} as LoadSoundEvent
},'*');
}
public play(config : SoundConfig) {
window.parent.postMessage({
"type" : 'playSound',
"data": {
url: this.url,
config
} as PlaySoundEvent
},'*');
return this.url;
}
public stop() {
window.parent.postMessage({
"type" : 'stopSound',
"data": {
url: this.url,
} as StopSoundEvent
},'*');
return this.url;
}
}
window.WA = { window.WA = {
/** /**
* Send a message in the chat. * Send a message in the chat.
@ -113,7 +153,11 @@ window.WA = {
}, '*'); }, '*');
}, },
goToPage(url: string): void { loadSound(url: string) : Sound {
return new Sound(url);
},
goToPage(url : string) : void{
window.parent.postMessage({ window.parent.postMessage({
"type": 'goToPage', "type": 'goToPage',
"data": { "data": {

View File

@ -5,6 +5,12 @@ var targetObjectTutoBubble ='Tutobubble';
var targetObjectTutoChat ='tutoChat'; var targetObjectTutoChat ='tutoChat';
var targetObjectTutoExplanation ='tutoExplanation'; var targetObjectTutoExplanation ='tutoExplanation';
var popUpExplanation = undefined; var popUpExplanation = undefined;
var enterSoundUrl = "webrtc-in.mp3";
var exitSoundUrl = "webrtc-out.mp3";
var soundConfig = {
volume : 0.2,
loop : false
}
function launchTuto (){ function launchTuto (){
WA.openPopup(targetObjectTutoBubble, textFirstPopup, [ WA.openPopup(targetObjectTutoBubble, textFirstPopup, [
{ {
@ -25,7 +31,8 @@ function launchTuto (){
label: "Got it!", label: "Got it!",
className : "success",callback:(popup2 => { className : "success",callback:(popup2 => {
popup2.close(); popup2.close();
WA.restorePlayerControls(); WA.restorePlayerControl();
WA.loadSound(winSoundUrl).play(soundConfig);
}) })
} }
]) ])
@ -36,13 +43,14 @@ function launchTuto (){
} }
} }
]); ]);
WA.disablePlayerControls(); WA.disablePlayerControl();
} }
WA.onEnterZone('popupZone', () => { WA.onEnterZone('popupZone', () => {
WA.displayBubble(); WA.displayBubble();
WA.loadSound(enterSoundUrl).play(soundConfig);
if (!isFirstTimeTuto) { if (!isFirstTimeTuto) {
isFirstTimeTuto = true; isFirstTimeTuto = true;
launchTuto(); launchTuto();
@ -71,4 +79,5 @@ WA.onEnterZone('popupZone', () => {
WA.onLeaveZone('popupZone', () => { WA.onLeaveZone('popupZone', () => {
if (popUpExplanation !== undefined) popUpExplanation.close(); if (popUpExplanation !== undefined) popUpExplanation.close();
WA.removeBubble(); WA.removeBubble();
WA.loadSound(exitSoundUrl).play(soundConfig);
}) })

BIN
maps/Tuto/webrtc-in.mp3 Normal file

Binary file not shown.

BIN
maps/Tuto/webrtc-out.mp3 Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

BIN
maps/tests/Audience.mp3 Normal file

Binary file not shown.

44
maps/tests/SoundScript.js Normal file
View File

@ -0,0 +1,44 @@
var zonePlaySound = "PlaySound";
var zonePlaySoundLoop = "playSoundLoop";
var stopSound = "StopSound";
var loopConfig ={
volume : 0.5,
loop : true
}
var configBase = {
volume : 0.5,
loop : false
}
var enterSoundUrl = "webrtc-in.mp3";
var exitSoundUrl = "webrtc-out.mp3";
var winSoundUrl = "Win.ogg";
var enterSound;
var exitSound;
var winSound;
loadAllSounds();
winSound.play(configBase);
WA.onEnterZone(zonePlaySound, () => {
enterSound.play(configBase);
})
WA.onEnterZone(zonePlaySoundLoop, () => {
winSound.play(loopConfig);
})
WA.onLeaveZone(zonePlaySoundLoop, () => {
winSound.stop();
})
WA.onEnterZone('popupZone', () => {
});
WA.onLeaveZone('popupZone', () => {
})
function loadAllSounds(){
winSound = WA.loadSound(winSoundUrl);
enterSound = WA.loadSound(enterSoundUrl);
exitSound = WA.loadSound(exitSoundUrl);
}

154
maps/tests/SoundTest.json Normal file
View File

@ -0,0 +1,154 @@
{ "compressionlevel":-1,
"height":20,
"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, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":20,
"id":2,
"name":"start",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":20,
"x":0,
"y":0
},
{
"data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
"height":20,
"id":4,
"name":"floor",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":20,
"x":0,
"y":0
},
{
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":20,
"id":3,
"name":"playSound",
"opacity":1,
"properties":[
{
"name":"zone",
"type":"string",
"value":"PlaySound"
}],
"type":"tilelayer",
"visible":true,
"width":20,
"x":0,
"y":0
},
{
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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":20,
"id":6,
"name":"playSoundLoop",
"opacity":1,
"properties":[
{
"name":"zone",
"type":"string",
"value":"playSoundLoop"
}],
"type":"tilelayer",
"visible":true,
"width":20,
"x":0,
"y":0
},
{
"draworder":"topdown",
"id":5,
"name":"floorLayer",
"objects":[
{
"height":19.296875,
"id":2,
"name":"",
"rotation":0,
"text":
{
"text":"Play Sound",
"wrap":true
},
"type":"",
"visible":true,
"width":107.109375,
"x":258.4453125,
"y":197.018229166667
},
{
"height":19.296875,
"id":3,
"name":"",
"rotation":0,
"text":
{
"text":"Bonjour Monde",
"wrap":true
},
"type":"",
"visible":true,
"width":107.109375,
"x":-348.221354166667,
"y":257.018229166667
},
{
"height":55.296875,
"id":4,
"name":"",
"rotation":0,
"text":
{
"text":"Play Sound Loop\nexit Zone Stop Sound \n",
"wrap":true
},
"type":"",
"visible":true,
"width":176.442708333333,
"x":243.778645833333,
"y":368.3515625
}],
"opacity":1,
"type":"objectgroup",
"visible":true,
"x":0,
"y":0
}],
"nextlayerid":8,
"nextobjectid":5,
"orientation":"orthogonal",
"properties":[
{
"name":"script",
"type":"string",
"value":"SoundScript.js"
}],
"renderorder":"right-down",
"tiledversion":"1.5.0",
"tileheight":32,
"tilesets":[
{
"columns":11,
"firstgid":1,
"image":"tileset1.png",
"imageheight":352,
"imagewidth":352,
"margin":0,
"name":"tileset1",
"spacing":0,
"tilecount":121,
"tileheight":32,
"tilewidth":32
}],
"tilewidth":32,
"type":"map",
"version":1.5,
"width":20
}

BIN
maps/tests/Win.ogg Normal file

Binary file not shown.

View File

@ -42,6 +42,14 @@
<a href="#" class="testLink" data-testmap="script_api.json" target="_blank">Testing scripting API with a script</a> <a href="#" class="testLink" data-testmap="script_api.json" target="_blank">Testing scripting API with a script</a>
</td> </td>
</tr> </tr>
<tr>
<td>
<input type="radio" name="test-scripting-sound"> Success <input type="radio" name="test-scripting-sound"> Failure <input type="radio" name="test-scripting-sound" checked> Pending
</td>
<td>
<a href="#" class="testLink" data-testmap="SoundTest.json" target="_blank">Testing scripting API loadSound() function</a>
</td>
</tr>
<tr> <tr>
<td> <td>
<input type="radio" name="test-autoresize"> Success <input type="radio" name="test-autoresize"> Failure <input type="radio" name="test-autoresize" checked> Pending <input type="radio" name="test-autoresize"> Success <input type="radio" name="test-autoresize"> Failure <input type="radio" name="test-autoresize" checked> Pending

BIN
maps/tests/webrtc-in.mp3 Normal file

Binary file not shown.

BIN
maps/tests/webrtc-out.mp3 Normal file

Binary file not shown.