/* * Copyright (c) 2015-2020. PT Docentron Trd Indoensia. All rights reserved. * This material may not be reproduced, displayed, modified or distributed without * the express prior written permission of the copyright holder. */ // ------------------------------------------------------------------- // Doncetnron Game API Overview // // Genari defines interface functions for Doncentron Game API and Phaser functions that are commonly used. // Genari.Effect effect functions such as bubbling scores, explosions. // Genari.add.XX common object factory methods defined here. // // Genari.Game is the game object representing the current game. We use this to hold global states of the game. // This is the overall flow of the game. // Genari.prepareGame() create Phaser game object and calls these functions to initialize the game // Genari.StatePlay: preloadState() // Genari.StatePlay: loadThemeAssets() Download theme game assets from server // Genari.StatePlay: createLayersGroups() Create layer and group objects to manage rendering orders and groups of objects // Genari.StatePlay: createWorld() Add game objects (sprites, images, audio) to the game stage to show // Genari.StatePlay: createHud() Setup the HUD of the game: score bars, pause button, player icon,... // Genari.StatePlay: createPlayer() Create player character // Genari.StatePlay: createStateObjects() Create background, tilemaps, monsters, pickup items // After the initialization, the game starts to play and this function gets called every frame: // Genari.StatePlay: updateState() Update state for each frame // When the game is over, this function is get called for us to clean up any objects: // Genari.StatePlay: shutdownState() Clean up game assets after completing the game level // // Layers and groups: // The game uses layers to control z-index (rendering orders of display objects). // layerBottom holds background, platforms. These appear as background of the game // layerPlayer holds players, player interactive items. This appear on top of objects in layerBottom // layerEffects holds explosions, bullets, effects. This appear on top of objects in layerPlayer and so on. // layerButtons holds control buttons, frames, windows, HUD items // layerDialog holds dialog boxes. Top layer // // Initialize these layers in StatePlay.createLayersGroups() // // The game also uses groups to manage a group of display objects and manage collision detection // groupPlatform // groupBullets // groupCorrectBox // groupIncorrectBox // // ** Create your own group classes in myClasses by extending Genari.Group or subclasses // // Detecting collisions and overlaps using the groups: // This detects collision of bullets with correct boxes and call shootRight function if collide // Genari.dcGame.groupBullets.checkOverlap(ga.groupCorrectBox, this.shootRight, null, this); // // Roles of classes: // Genari.GameState Controls the flow. We normally require at least 2 states: menu and play // Genari.Control. Adds control keys, buttons and update their states. // Genari.Player. This is optional. Controls the player character. Some games don't have a player. // Genari.RunPlayer is a sub-class of Genari.Player for running games. // We use this for scrolling running games. // Genari.Group Creates, update, pause, resume a group of game objects // Genari.PlatformGroup A subclass of Group holding collidable buildings // Genari.BulletGroup A subclass of Group for bullets, containes addBullet, updateBullet which destroy bullets automatically. // Genari.PicktupGroup A subclass of Group for pickup items // Genari.WordBoxGroup A subclass of Group for word box items, which contain statements. // // ** Extend these classes in myClasses in app_class.js for your game. // // ----------------------------------------------------------- // Steps to create your game: // 1. Configure game assets using the game editor. All game assets are defined in auxcode.js // 2. Customise StetePlay methods for loading assets, layers, groups, world, and updating frames // Genari.Control // Genari.Game // Genari.StatePlay: preloadState() Load theme assets // Genari.StatePlay: loadThemeAssets() // Genari.StatePlay: createLayersGroups() // Genari.StatePlay: createWorld() // Genari.StatePlay: createHud() Setup the HUD of the game: score bars, pause button, player icon,... // Genari.StatePlay: createPlayer() Create player character // Genari.StatePlay: createStateObjects() Create background, tilemaps, monsters, pickup items // Genari.StatePlay: shutdownState() Clean up game assets after completing the game level // Genari.StatePlay: updateState() Update state for each frame // Genari.Group: Add Group classes to manage your game objects (monsters, bullets, pickup items, boss,...) // // 3. We check if the game is completed or over in PStatePlay.update() using RunningGame.checkLevelEnd()), // Genari.Game.saveAndStartNextLevel() is called to save the game and load the next game level. // // Functions to start a new game, save and start next level, restart current level, pause game, and unpause game. // You don't need to change these methods. Just call them whenever appropriate. // Genari.Game:startNew() // Start a new game // Genari.Game:saveAndStartNextLevel() // Save score and start a next game level // RunningGame:restartLevel() // Restart the current game level. You can customise this for your need // RunningGame:pause() // You can customise this for your need // Genari.Game:resume() // un-pause the game // // ------------------------------------------------------------------- // Global variables used by the API. var ga_assets_common = {}; // deprecated var ga_assets_themes = []; // deprecated var char_strokes = []; // Used by stroke games to store character stroke sequence data // Theme data will be loaded into this variable: var game_themes = [[]]; window["game_themes"] = game_themes; // DEVELOPER_CODE This is updated by API. So we need to export for developer version if(typeof dc_site_url === "undefined"){ var dc_site_url = window.location.protocol + "//" + window.location.hostname } // Common assets will be loaded into this variable: var game_common_assets = { "imagesSprites": { "userIconFrame": [dc_site_url+'/assets/gassets/ui/userIconFrame.png'] }, "audio":{} }; window["game_common_assets"] = game_common_assets; // DEVELOPER_CODE This is updated by API. So we need to export for developer version /********************************************************************* * Docentron Game API interface functions. * Genari Game API Interface *********************************************************************/ var Genari = { author: "Docentron", // dcGame: null, // This will be set to the Genari.Game obj created phaserGame: null, // This will be set to the Phaser game created worldTileMap: null, // tileMap for the game. This will be set if loaded. // This is used for previewing new games being edited by a developer gno: -1, // set this to use themeDBLoadHook themeDBLoadHook: null, // If this is set, it is called with gno and a callback function. // themeDBLoadHook(gno, callback); // This function must call the callback with theme data // callback(themeData) /** * Use Genari.Question class instead of using this to use Memory card questions * * Generate a random memory card question and its answer choices (2 or 4 answers). * If there are no more questions, returns an empty array. * If there are no images, imgUrl/iconUrl are set to null * Check the returned urls for debugging. * * @param {boolean} [resetIdx] Set to true to reset the index to start from the beginning. * @return {Array|undefined} Return an array like this: * [ qNo, * "question text", * correctChoiceNo, // answer starting from 1 * ["choice1 text", imgUrl, sndUrl, imgKey, sndKey, snd2Url, snd2Key], // answer 1 * ["choice2 text", imgUrl, sndUrl, imgKey, sndKey, snd2Url, snd2Key], // answer 2 * ["choice3 text", imgUrl, sndUrl, imgKey, sndKey, snd2Url, snd2Key], * ["choice4 text", imgUrl, sndUrl, imgKey, sndKey, snd2Url, snd2Key] * ["choice5 text", imgUrl, sndUrl, imgKey, sndKey, snd2Url, snd2Key] * iconUrl, // URL of the icon image * img1Url, // URL of question image1 * sndUrl, // URL of question sound * img1Key, // image 1 asset key loaded * sndKey, // sound asset key loaded * img2Url, * img2Key * ] */ getFlashCardQuestion: function(resetIdx){ return _gitf049(resetIdx); }, /** * These are the list of attributes of each game level: qNo = 0 * questionData[qNo]["question"] The level question * questionData[qNo]["icon"] icon file id * questionData[qNo]["img1"] Activity Banner Image file Id. Key is ik_FileId * questionData[qNo]["img2"] End image file Id. Key is ik_FileId * questionData[qNo]["snd1"] opening sound file Id. Key is sk_FIleId * questionData[qNo]["answers"] = [ * {atype:1, answer:"answer",imageKey:key, snd1Key:key,..} * ... * ] * The level assets are loaded after theme assets are loaded: after Genari.StatePlay.loadThemeAssets() are called. * The loaded audio assets are stored in Genari.Game.audioAssets * @deprecated Use getLevelData() * @returns {*} */ getAllQuestions: function(){ return _gitf049a(); }, /** * These are the list of attributes of each game level: qNo = 0 * questionData[qNo]["question"] The level question * questionData[qNo]["icon"] icon file id * questionData[qNo]["img1"] Activity Banner Image file Id. Key is ik_FileId * questionData[qNo]["img2"] End image file Id. Key is ik_FileId * questionData[qNo]["snd1"] opening sound file Id. Key is sk_FIleId * questionData[qNo]["answers"] = [ * {atype:1, answer:"answer", params:parametersText, imageKey:key, snd1Key:key,..} * ... * ] * The level assets are loaded after theme assets are loaded: after Genari.StatePlay.loadThemeAssets() are called. * The loaded audio assets are stored in Genari.Game.audioAssets * @returns {*} */ getLevelData: function(){ return _gitf049a(); }, /** * Return Activity image key for the current game level * @return {*} */ getLevelActivityImageKey: function(){ if(Genari.getLevelData()[0]["img1"] > 0){ return "ik_" + Genari.getLevelData()[0]["img1"]; }else{ return null; } }, /** * Return End image key for the current game level * @return {*} */ getLevelEndImageKey: function(){ if(Genari.getLevelData()[0]["img2"] > 0){ return "ik_" + Genari.getLevelData()[0]["img2"]; }else{ return null; } }, /** * @deprecated use getLevelOpeningSoundKey * @return {*} */ getLevelOpendingSoundKey: function(){ return Genari.getLevelOpeningSoundKey(); }, getLevelOpeningSoundKey: function(){ if(Genari.getLevelData()[0]["snd1"] > 0){ return "sk_" + Genari.getLevelData()[0]["snd1"]; }else{ return null; } }, /** * Return the max score of the current flash card question * @returns {number} max score of the current question */ getFlashCardQuestionScore: function(){ return _gitf073(); }, /** * Set to flash-card-game mode. This forces the game to load all questions. * Call this for flash card games. * This is called by the game before the start of the game/level */ setToFlashCardGameMode: function(){ _gitf069(); }, setToTestMode: function(){ _gitf069b(); }, /** * Return the number of questions for flash card game * @returns {number} The total number of questions. */ getNumberOfQuestions: function(){ return _gitf068(); }, /** * Return statistics of the statements * @returns {Object} {totalShown:TotalNoOfStatements, totalCorrect: NofCorrectStatements, totalIncorrect: noIncorrectStatements} * @deprecated Use Generi.getAnswers and use the result to count stat. */ getStatementStat: function(){ return _gitf058(); }, /** * Randomly generate the words and call the callback function with the word info for each answer * @param {Function} callBack Callback will be called for each answer * { * "answer": answer text * "score": answer score. Float * "img": image file id. If 0, it is not set * "imgtype": image type. 0 for image. * "snd1": sound file id for MP3 file. If 0, it is not set * "snd2": sound2 file id for Ogg file. If 0, it is not set * "imgKey": image asset key. Use this to add image to the stage. This is already loaded. * "snd1Key": sound asset key MP3 file. Use this to add sound to the stage. This is already loaded. * "snd2Key": sound2 asset key: Ogg file. NOT used now. * "answer_info": information about the answer. Show this text when the player collects this answer. This explains the answer. * "showtxt": if 1, content designer wants show text with the image together * "atype": if 1, the answer is a correct answer * } */ forEachStatement: function(callBack){ _gitf059(callBack); }, /** * Return all answers of the current game level * * A game level has two sets of answers. Here we will refer to as correctAnswers and incorrectAnswers. * Some games has only one set of questions. For example, order game has only answer images. * @return {Array|null} Return arrays of answers [correctAnswers, incorrectAnswers]. * Returns null if there are no answers. * Each answer has the following format. * { * "answer": answer text * "params": parameters text (optional parameters depending on games) * "score": answer score. Float * "img": image file id. If 0, it is not set * "imgtype": image type. 0 for image. * "snd1": sound file id for MP3 file. If 0, it is not set * "snd2": sound2 file id for Ogg file. If 0, it is not set * "imgKey": image asset key. Use this to add image to the stage. This is already loaded. * "snd1Key": sound asset key MP3 file. Use this to add sound to the stage. This is already loaded. * "snd2Key": sound2 asset key: Ogg file. NOT used now. * "answer_info": information about the answer. Show this text when the player collects this answer. This explains the answer. * "showtxt": if 1, content designer wants show text with the image together * "atype": if 1, the answer is a correct answer * } * Usage: * var answers = Genari.getAnswers(); * var correct_answers = answers[0]; * var incorrect_answers = answers[1]; * correct_answers[i]["imgKey"] <--- img asset key of the i-th correct answer */ getAnswers: function(){ return _gitf088b(); }, /** * Return a random statement (word) * @deprecated use getRandomAnswer * @param {boolean} [reset] Set to true to reset the counter. * @returns {Object} {word:wordText, score:Score, [img:urlToImage]} */ getRandomStatement: function(reset){ return _gitf056(reset); }, /** * Return a random statement (word) * @param {boolean} [reset] Set to true to reset the counter. * @returns {Object} {word:wordText, score:Score, [img:urlToImage]} */ getRandomAnswer: function(reset){ return _gitf056(reset); }, /** * Return l_showhint state for current game level * @returns {boolean} l_showhint = True show hint */ isShowHint: function(){ return _gitf062(); }, /** * Return the objective of current game level * @returns {string} question text. Max 70 characters */ getQuestion: function(){ return _gitf060(); }, /** * Return the stroke data for the current character (current level) * @returns {Object} {"char": char, "strokes": [[[x,y],...],...], "language": language, } */ getCharStrokeData: function(){ return _gitf061a(); }, /** * Return question id of current game level * @returns {number} question id */ getQuestionId: function(){ return _gitf063(); }, /** * Return sound asset key of the question of the current game level * @returns {string|null} sound asset key */ getQuestionSoundKey: function(){ return _gitf063a_s(0); }, /** * Return image asset key of the question of the current game level * @returns {string|null} sound asset key */ getQuestionImageKey: function(){ return _gitf063a_i(0); }, /** * Return a list of top 10 scores of the game * @returns {Array} a list of scores, descending order */ getScoreBoard: function(){ return _gitf063(); }, /** * Get phaser game time * @returns {number} phaser game time */ getGameTime: function(){ return _gitf051(); }, /** * Limit the length of the sentence to 35 or to the length * @param {string} sentence * @param {number} [maxLength] * @returns {string} */ limitSentence: function(sentence, maxLength){ return _gitf052(sentence, maxLength); }, /** * Add event handlers for a phaser keyboard key * @param keyName Name of a key E.g., "UP", "ENTER", "SPACEBAR". http://phaser.io/docs/2.4.6/Phaser.KeyCode.html * @param {Function|undefined} [downActionFunction] listener function for key down event * @param {Function|undefined} [upActionFunction] listener function for key up event * @param {Object|undefined} [listenerContext] * @returns {Object|null} */ addKey: function(keyName, downActionFunction, upActionFunction, listenerContext){ return _gitf053(keyName, downActionFunction, upActionFunction, listenerContext); }, /** * Check if a key is down * @param {string} key Key name. E.g., "UP", "ENTER", "SPACEBAR". http://phaser.io/docs/2.4.6/Phaser.KeyCode.html * @return {boolean} true if down * **/ checkKeyDown: function(key){ return _gitf020(key); }, /** * Not used * @param array * @returns {*} */ shuffleWordList: function (array) { return _gitf054(array); }, /** * Calculate direction between two points * @param point1 {Array} A point array [x, y] * @param point2 {Array} A point array [x, y] * @return {string} Return up, down, left, or right towards point2 */ dirBtw2Points: function(point1, point2){ return dirBtw2Points(point1, point2); }, /** * Return path to the game asset folder * @param pathToFileInGassets * @returns {*} */ gameAssetPath: function(pathToFileInGassets){ return _gitf055(pathToFileInGassets); }, /** * Show score board when paused */ showScoreBoard: function(){ _gitf065(); }, /** * Get user name */ getUserName: function(){ return _gitf066(); }, /** * Get URL of user photo */ getUserPhoto: function(){ if(typeof _gitf067 !== "undefined") return _gitf067(); else return dc_site_url+"/assets/images/user.png"; }, /** * Return the theme-no of the current game level */ getThemeNo: function (){ return _gitf016(); }, /** * Return the theme-no that can exceed the default max theme No for leading from database */ getThemeNoForDB: function (){ return _gitf016a(); }, /** * Return the theme data of the current game level. Each level can have different theme * @returns {Object} Genari.getTheme()["key"] returns the value for attributes */ getTheme: function(){ return _gitf070(); }, /** * Return the value of an attribute asset * @param {string} attributeKey attribute asset key E.g., Geneari.k.hintImageWidthKey * @param {number|string|Object} defaultValue * @returns {number|string|Object} */ getThemeAttribute: function(attributeKey, defaultValue){ var theme = _gitf070(); if(theme && theme[attributeKey]) return theme[attributeKey]; else return defaultValue; }, /** * Return an array of coordinates of an attribute asset, which is a string containing coordinates * E.g., a string containing "(x1,y1),(x2,y2),...." will return [[x1, y1], [x2, y2],....] * @param {string} attributeKey an asset key of attribute containing a string containing coordinates. key example. Geneari.k.hintImageWidthKey. String example: "(x1,y1),(x2,y2),...." * @param {Array} defaultValue An array of coordinates E.g., [[x1, y1], [x2, y2],....] * @returns {Array} */ getThemeArrayStringAttribute: function(attributeKey, defaultValue){ var theme = _gitf070(); if(theme && theme[attributeKey]) return Genari.parseArrayOfCoordinates(theme[attributeKey]); else return defaultValue; }, /** * Convert a string containing an array of coordinates to an array of coordinates * @param {string} coordinateArrayString string containing array of coordinates E.g., "(x1,y1),(x2,y2),.... " * @return {Array} E.g., [[x1,y1],[x2,y2],.....] */ parseArrayOfCoordinates: function(coordinateArrayString){ var coordinates = []; var coordinate = []; // store one coordinate var tokens = coordinateArrayString.replace(/\)(.*?)\(/g,")(").replace(/\(/g,"").split(")"); tokens.forEach(function(t){ if(t.length>0){ coordinate = t.split(","); if(coordinate.length === 2){ coordinate[0] = parseInt(coordinate[0],10); coordinate[1] = parseInt(coordinate[1],10); coordinates.push(coordinate); } } }); return coordinates; }, /** * Set the current theme data * @param {Object} themeData */ setTheme: function(themeData){ _gitf070b(themeData); }, // /** * Return true if minscore is achieved */ checkMinScore: function (levelScore){ return _gitf017(levelScore); }, /** * Phaser interface functions * Prevent event propagation of a keybaord key. E.g., add arrow keys to stop browser scrolling up. * @param {string} key Key name. E.g., "ENTER", "SPACEBAR" */ phaserAddKeyCapture: function(key){ _gitf018(key); }, /** * Creates and returns an object containing 4 hotkeys for Up, Down, Left and Right. * @return {Object} Creates and returns an object containing 4 hotkeys for Up, Down, Left and Right. */ createCursorKeys: function(){ return _gitf021(); }, /** * Create a joystick at the location (x,y). * Supports multi-touch. See app_class.js for an example on creating one. * @param {number} alpha Transparency. * @param {number} stickOffset location of the center of the stick within the circle * @param {number} x * @param {number} y * @param {string} stickBaseSpriteKey Name of the sprite asset loaded. * @param {string} StickSpriteKey Name of the sprite asset loaded */ createJoyStick: function(alpha, stickOffset, x, y, stickBaseSpriteKey, StickSpriteKey){ return _gitf036(alpha, stickOffset, x, y, stickBaseSpriteKey, StickSpriteKey); }, /** * Update joystick state and get its direction info * @return {Array} [stickLeftRight, stickUpDown] + for right and up */ updateJoyStick: function(){ return _gitf037b(); }, /** * Given a sprite, which was initially placed with the given offset values (E.g., center it to the stage), * get scaled center of a sprite from the current location of the sprite. * This works for all scales of the game. * @param sprite * @param xOffset * @param yOffset * @returns {{x, y}|*} */ getScaledCenter: function(sprite, xOffset, yOffset){ return _gitf095(sprite, xOffset, yOffset); }, /** * Update joystick state and get its direction info * @param {Object} monsterSprite Phaser.Sprite * @param {boolean|undefined} updateLocation Default true * @param {number} x monster x * @param {number} y monster y Distance of the monster from the screen * @param {number} z monster z Distance of the monster from the ground * @param {number} cx Default 400 Camera x location * @param {number} cy Default 400 Camera distance from the screen * @param {number} cz Default 200 Camera height from the ground. * @param {number | null} [minScale] Default 0.2 * @param {number | null} [maxScale] Default 1 * @return {Array} [x, y] */ calcProjection: function(monsterSprite, updateLocation, x, y, z, cx, cy, cz, minScale, maxScale){ return _gitf078(monsterSprite, updateLocation, x, y, z, cx, cy, cz, minScale, maxScale); }, /** * Calculate the travelled distance since the last call * @param {Object} monsterSprite Phaser.Sprite * @param {number} v Pixels per second * @param {number} [deltaTime] millisecondss. If given, this is used to calculate * @returns {number} Travelled distance */ calcTravelDistance: function(monsterSprite, v, deltaTime){ return _gitf079(monsterSprite, v, deltaTime); }, /** * Add actions for a cursor key. key = up, down, left, right * * @param {Object} cursorKeys An object created using Genari.Game.createCursorKey() * @param {string} key key name: up, down, left, right * @param {Function} downAction Function that will be called when the key is down. * @param {Function} upAction Function that will be called when the key is up. * @param {Object} listenerContext */ addCursorKeyActions: function(cursorKeys, key, downAction, upAction, listenerContext){ _gitf022(cursorKeys, key, downAction, upAction, listenerContext); }, /** * Add a scrolling background image and set the world bound to the world size. * * @param layer Layer to which you want to add the background to * @param key Key of the image asset * @param {number|undefined} [worldWidth] Default screen width * @param {number|undefined} [worldHeight] Default screen height * @param {number|undefined} [x] Default 0 The initial location of the tile sprite * @param {number|undefined} [y] Default 0 The initial location of the tile sprite * @param {number|undefined} [width] Default screen width. The width of the tile sprite * @param {number|undefined} [height] Default screen height. The height of the tile sprite * @param {number|undefined} [frame] Default 0. Frame of the sprite to use * @return {Object} Phaser.TileSprite */ addBackground: function(layer, key, worldWidth, worldHeight, x, y, width, height, frame){ return _gitf080(layer, key, worldWidth, worldHeight, x, y, width, height, frame); }, /** * Scroll background as the camera move * @param {number} scale * @param {Object|undefined} [backgroundTileSprite] Phaser.TileSprite Default the last background set using Genari.addBackground() */ scrollBackground: function(scale, backgroundTileSprite){ _gitf081(scale, backgroundTileSprite); }, /** * Import Polygons from a TileMap layer to use as a platform * @param layerNameInTileMap * @param collideWithThisGroup * @returns {Object|undefined} Phaser.CollisionGroup of the platform p2 bodies. Use this to set collisions for other p2 bodies */ p2ImportPolygonsAsPlatforms: function(layerNameInTileMap, collideWithThisGroup){ return ibg_p2ImportPolygonsAsPlatforms(layerNameInTileMap, collideWithThisGroup); }, /** * Import Polygon from a TileMap layer to use as collision body * @param layerNameInTileMap * @returns {Array} an array of Phaser.Physics.Body */ p2ConvertCollisionObjects: function(layerNameInTileMap){ return _gitf082(Genari.dcGame.statePlay.tileMaps["worldTileMap"], layerNameInTileMap, true); }, /** * Create p2 collision group * @returns {Object} Phaser.CollisionGroup */ p2CreateCollisionGroup: function(){ return _gitf083(); }, /** * Create a collision group for a p2Bodies and set it to collide with another collision group given. * @param {Array} p2Bodies The p2Bodies An array of P2 Bodies * @param {Object|undefined} [collisionGroup] set the collisiongroup of the p2Bodies with this * @param {Object|undefined} [collideWithThisGroup] Collide with this * @param {Object|undefined} [callback] * @param {Object|undefined} [callbackContext] * @param {Object|undefined} [shape] * @returns {Object} Phaser.CollisionGroup of the p2Bodies */ p2SetCollisionGroup: function(p2Bodies, collisionGroup, collideWithThisGroup, callback, callbackContext, shape){ return _gitf084(p2Bodies, collisionGroup, collideWithThisGroup, callback, callbackContext, shape); }, /** * * @param {string} key * @param {Object|undefined} [parentSprite] * @param {number|undefined} [x] Default 0 * @param {number|undefined} [y] Default 0 * @param {number|undefined} [maxParticles] Default 5 * @param {number|undefined} [lifespan] Default 150 * @param {Array|undefined} [maxParticleSpeed] [xSpeed, ySpeed] * @param {Array|undefined} [minParticleSpeed] [xSpeed, ySpeed] * @returns {*} */ addParticleEmitter: function(key, parentSprite, x, y, maxParticles, lifespan, maxParticleSpeed, minParticleSpeed){ return _gitf085(key, parentSprite, x, y, maxParticles, lifespan, maxParticleSpeed, minParticleSpeed); }, /** * Create a P2 body from a physics asset. * Create physics using Physics eidtor: https://www.codeandweb.com/physicseditor * @param {Object|undefined} layer * @param {string} key * @param {number} x * @param {number} y * @param {string} physicsAssetKey The key of the Physics Data file as stored in Game.Cache. * @param {string} objectName The key of the object within the Physics data file that you wish to load the shape data from * @param {Object} collisionGroup Phaser.CollisionGroup * @param {number|undefined} [mass] Default 80 * @param {number|undefined} [bounce] Default 0.5 The elasticity of the Body when colliding. bounce.x/y = 1 means full rebound, bounce.x/y = 0.5 means 50% rebound velocity. * @param {Array|undefined} [friction] Default [10, 1] [xFriction, yFriction] */ createP2BodyFromPhysics: function(layer, key, x, y, physicsAssetKey, objectName, collisionGroup, mass, bounce, friction){ return _gitf086(layer, key, x, y, physicsAssetKey, objectName, collisionGroup, mass, bounce, friction); }, /** * Set the p2Sprite collide with the collision group and call the callback upon collision * @param p2Sprite Phaser.Body * @param collisionGroup * @param [callback] * @param [callbackContext] * @param [shape] */ setP2BodyCollision: function(p2Sprite, collisionGroup, callback, callbackContext, shape) { _gitf087(p2Sprite, collisionGroup, callback, callbackContext, shape); }, /** * Add P2 body image text box at the obj location that will collide with other collisionGroups * @param {Genari.WordBoxGroup} wordBoxGroup * @param {string} wordBoxFrameImgKey * @param {Object} object * @param {Object} collisionGroup of this word box Phaser.CollisionGroup * @param {Object|Array} collideList Phaser.CollisionGroup collision groups that will collide with this word box * @param {Function} [callbackForEachSprite] this is called for each wordbox created for further customisation * @return {Object} Phaser.Sprite with answer attribute. Object.answer["word"], Object.answer["score"], ... */ addP2BodyImageTextBoxFromObj: function(wordBoxGroup, wordBoxFrameImgKey, object, collisionGroup, collideList, callbackForEachSprite){ return _gitf102(wordBoxGroup, wordBoxFrameImgKey, object, collisionGroup, collideList, callbackForEachSprite); }, /** * Return the world width of the game: Phaser["world"]["width"] * @returns {*} */ phaserWorldWidth: function(){ return _gitf071(); }, /** * Phaser function: addText * @param x * @param y * @param text * @param {Object|string|undefined} [style] CSS style for the text. E.g., { "fontSize": '18px', "fill": "#000000" } * @returns {Object} Phaser text */ phaserAddText: function (x, y, text, style){ return _gitf025(x, y, text, style); }, /** * Wrapper for Phaser.Tilemap.getTile() * * @param tilemap * @param {number} x * @param {number} y * @param {string|number} layer * @returns {Object} Phaser.Tile */ phaserGetTile: function (tilemap, x, y, layer){ return tilemap["getTile"](x, y, layer); }, /** * Load Phaser Physics data * @param carPhysicsDataKey */ phaserLoadPhysicsData: function(carPhysicsDataKey){ ibg_phaserLoadPhysicsData(carPhysicsDataKey); }, /** * Add answer image or text to a sprite or image as a child * @param sprite * @param answer * @param score * @param textOffset * @param width * @param height * @param align * @param maxFontSize * @return {Object} Phaser Text or Image */ addAnswerToSprite: function(sprite, answer, score, textOffset, width, height, align, maxFontSize){ return _gitf090(sprite, answer, score, textOffset, width, height, align, maxFontSize); }, /** * Check if an answer image is given * @param {Object} answer an answer object obtained from Genari.getRandomAnswer() */ checkAnswerImageExist: function(answer){ return _gitf096(answer); }, /** * Check if an answer image is given * @param {Object} answer an answer object obtained from Genari.getRandomAnswer() */ checkAnswerSoundExist: function(answer){ return _gitf096b(answer); }, /** * Phaser function: add phaser button object to the current stage * http://phaser.io/docs/2.4.4/Phaser.Button.html * @param x * @param y * @param key * @param {Function|undefined} [callback] * @param {Object|undefined} [callbackContext] * @param {number|undefined} [overFrame] * @param {number|undefined} [outFrame] * @param {number|undefined}[downFrame] * @param {number|undefined}[upFrame] * @param {number|undefined} [btnWidth] * @param {number|undefined} [btnHeight] * @returns {Object} Phaser Button */ phaserAddButton: function (x, y, key, callback, callbackContext, overFrame, outFrame, downFrame, upFrame, btnWidth, btnHeight){ return _gitf014(x, y, key, callback, callbackContext, overFrame, outFrame, downFrame, upFrame, btnWidth, btnHeight); }, /** * Phaser function: Add audio to stage * @param key * @param {number|undefined} [volume] * @param {boolean|undefined} [loop] * @returns {Object} Phaser audio object */ phaserAddAudio: function (key, volume, loop){ return _gitf026(key, volume, loop); }, /** * Phaser function: Add sprite to stage * After adding the sprite, we can add animations (named animation sequence) * var walk = mySprite.animations.add('walk',[0,1]); // create an animation using two frames 0, 1 * mySprite.animations.play('walk', 30, true); // play at 30 frames per second in loop * Ref: see https://phaser.io/examples/v2/animation/sprite-sheet * @param {number} x * @param {number} y * @param {string} key * @param {number|string|undefined} [frame] A frame to use initially * @param {Object} [layer] Phaser.Group. If provided, add to the group * @returns {Object} Phaser sprite */ phaserAddSprite: function (x, y, key, frame, layer){ return _gitf027(x, y, key, frame, layer); }, /** * Phaser function: Add image to stage * * @param x * @param y * @param key * @param {Object} [layer] Phaser.Group. If porvided, add to the group * @returns {Object} Phaser image */ phaserAddImage: function (x, y, key, layer){ return _gitf027b(x, y, key, layer); }, /** * Rescale the given image or sprite to the given size and center it horizontally * @param obj * @param width * @param height */ rescaleAndCenter: function(obj, width, height){ _gitf094(obj, width, height); }, /** * A TileSprite is a Sprite that has a repeating texture. * You shouldn't ever create a TileSprite any larger than your actual screen size. * Use the tilePosition property to scroll the texture as the player moves. * @param {number} x * @param {number} y * @param {number} width Must same or less than the screen size * @param {number} height Must same or less than the screen size * @param {string} key Sprite * @param {number|undefined} [frame] Frame of the sprite to use. Default Null * @param {Object|undefined} [layer] * @returns {Object} Phaser tile sprite */ phaserAddTileSprite: function (x, y, width, height, key, frame, layer){ return _gitf028(x, y, width, height, key, frame, layer); }, /** * Phaser function: Load sprite sheet * * @param key * @param url * @param frameWidth * @param frameHeight * @param {number|undefined} [frameMax] * @param {number|undefined} [margin] * @param {number|undefined} [spacing] * @returns {Object} Phaser sprite sheet */ phaserLoadSpriteSheet: function (key, url, frameWidth, frameHeight, frameMax, margin, spacing){ return _gitf029(key, url, frameWidth, frameHeight, frameMax, margin, spacing); }, /** * Phaser function: Load image * * @param key * @param url * @param {boolean|undefined} [overwrite] * @returns {Object|undefined} Phaser image */ phaserLoadImage: function (key, url, overwrite){ return _gitf030(key, url, overwrite); }, /** * Phaser function: Load audio * * @param key * @param urls * @param {boolean|undefined} [autoDecode] * @returns {Object|undefined} Phaser audio */ phaserLoadAudio: function (key, urls, autoDecode){ return _gitf031(key, urls, autoDecode); }, calcHalfX: function(obj) { return obj["x"] + obj["width"] / 2; }, calcHalfY: function(obj) { return obj["y"] + obj["height"] / 2; }, /** * Calculate the x offset from the box left boundary to center obj horizontally in the box * @param {Object} box Has width and height properties * @param {Object} obj Has width and height properties * @returns {number} x offset from the box left boundary to center obj horizontally in the box */ calcBoxCenterX: function (box, obj) { return _gitf033(box, obj); }, /** * Calculate the y offset from the box top boundary to center obj vertically in the box * @param {Object} box Has width and height properties * @param {Object} obj Has width and height properties * @returns {number} x offset from the box left boundary to center obj horizontally in the box */ // Return the y offset from the box top boundary to center obj vertically in the box calcBoxCenterY: function (box, obj) { return _gitf034(box, obj); }, /** * Calculate the offset from the boundary of the container in order to center the obj * @param {number} containerSize in pixels * @param {number} objectSize in pixels * @returns {number} offset from the boundary of the container */ calcCenter: function (containerSize, objectSize) { return (containerSize - objectSize)/2; }, /** * Draw a line between sprite1 and sprite2. * if (x,y) is given, move sprite1 to (x,y) * If line is given, the line object is reused otherwise a new one is created. * @param sprite1 Phaser.Sprite object * @param sprite2 Phaser.Sprite object * @param {Object|undefined} [line] Phaser.Graphic object * @param {number|undefined} [x] * @param {number|undefined} [y] * @param {number|undefined} [lineThickness] * @param {number|undefined} [lineColor] * @return {Object} Phaser.Grphics object for the line */ drawLineBetweenSprites: function (sprite1, sprite2, line, x, y, lineThickness, lineColor) { return _gitf091(sprite1, sprite2, line, x, y, lineThickness, lineColor); }, /** * Draw a line between two points: (sx, sy) and (ex, ey). * ** Provide an existing line object to reuse instead of creating new lines everytime. * @param sx * @param sy * @param ex * @param ey * @param {Object|undefined} [line] If provided, this line object is reused. Otherwise a new line graphic object will be created. * @param {number|undefined} [lineThickness] Default 5. * @param {number|undefined} [color] RGB color value of the line. Default 0x00E599 * @param {number|undefined} [alpha] transparency of the line. Default 1 (opaque) * @param {boolean|undefined} [rescale] Set to true to rescale the coordinates * @return {Object} Returns Phaser line graphic object. */ drawLine: function(sx, sy, ex, ey, line, lineThickness, color, alpha, rescale){ // Clear any previous line if(!line) line = Genari.dcGame.phaserGame["add"]["graphics"](0, 0); else line["clear"](); lineThickness = lineThickness || 5; color = color || 0x00E599; alpha = alpha || 1; if(rescale){ // scale the coordinates to match the scaled game display sx = sx / Genari.dcGame.screenScaleRatio; sy = sy / Genari.dcGame.screenScaleRatio; ex = ex / Genari.dcGame.screenScaleRatio; ey = ey / Genari.dcGame.screenScaleRatio; } if (line) { line["lineStyle"](lineThickness, color, alpha); line["moveTo"](sx, sy); line["lineTo"](ex, ey); } return line; }, /** * Calculate dX (x length), dY (y length) of a Phaser line grphic object. * @param graphicLine Phaser line object * @returns {Array} [dx, dy] */ calcLineDelta: function (graphicLine) { return _gitf092(graphicLine); }, /** * @returns {Array} [x, y] */ getActivePointerLocation: function(){ return _gitf093(); }, /** * @returns {Array} [x, y] */ isActivePointerDown: function(){ return _gitf093b(); }, /** * Get states of the first 3 pointers * mousePointer, pointer 1, pointer 2 * Each pointer contains [x, y, isDown] */ getPointerStates: function(){ var mousePointer = Genari.getPointerLocationState(0); var pointer1 = Genari.getPointerLocationState(1); var pointer2 = Genari.getPointerLocationState(2); return [mousePointer, pointer1, pointer2]; }, /** * Return the location of a pointer and state * @param {number} [pointerId] Id of the pointer starting from 1. By default the game supports 2 pointers * @returns {Array} [x, y, isDown] */ getPointerLocationState: function(pointerId){ var pointer, px, py, isDown; if(pointerId === 0){ // mouse pointer pointer = Genari.dcGame["_p"]["input"]["mousePointer"]['position']; isDown = Genari.dcGame["_p"]["input"]["mousePointer"]["isDown"]; }else{ pointer = Genari.dcGame["_p"]["input"]["pointer"+pointerId]; isDown = pointer["isDown"]; } px = pointer['x']/Genari.dcGame.screenScaleRatio; py = pointer['y']/Genari.dcGame.screenScaleRatio; return [px, py, isDown]; }, /** * Return the down state of a pointer * @param {number} [pointerId] Id of the pointer starting from 1. By default the game supports 2 pointers * @returns {Array} [x, y, isDown] */ isPointerDown: function(pointerId){ var pointerIdStr = "pointer"+pointerId; var pointer = Genari.dcGame["_p"]["input"][pointerIdStr]; var isDown = pointer["isDown"]; return isDown; }, /** * Create legends (numbers) along the edge of a board game board. * @param {number} numRows * @param {number} numCols * @param {number} borderThickness * @param {Object} boardBorderImg Phaser.Image * @param {Object} fontStyle font style of the legend text * @param {Object} tileMapBoardLayer Phaser.Tilemap * @param {number} boardTileMap Phaser.TilemapLayer * @param {Object} boardRenderingLayer Phaser.Layer */ createBoardLegends: function( numRows, numCols, borderThickness, boardBorderImg, fontStyle, boardTileMap, tileMapBoardLayer, boardRenderingLayer ){ _gitf098(numRows, numCols, borderThickness, boardBorderImg, fontStyle, boardTileMap, tileMapBoardLayer, boardRenderingLayer); }, /** * * Check if the location is allowed for the player. * If calcFlipList is set, it also calculate list of pads that need to be flipped and change its states (flip). * If updateCellState is set to false, the pads will not be flipped. * * @param {number} col base 0 The column number to base the move on. ** col 0 and the last row are boarder cols * @param {number} row base 0 The row number to base the move on. ** row 0 and the last row are boarder rows * @param {number} playerId The group of the pad. * @param {Array} boardCellStates Default true. Set true to update cell states. Must set calcFlipList * @param {boolean} [calcFlipList] True to return a list of pads to flip for the player * @param {boolean} [updateCellState] Default true. Set true to update cell states. Must set calcFlipList * @returns {Array} [isLegalMove, {"x":positionX, "y":positionY, "player":player},...] col, row: Base 0. */ othelloGameCheckLegalMove: function(col, row, playerId, boardCellStates, calcFlipList, updateCellState){ return _gitf099(col, row, playerId, boardCellStates, calcFlipList, updateCellState); }, /** * Calculate best position for Othello Game * @param {Array} boardCellStates N by M array of integers representing the board state. 0 = empty. 1 = human player, 2 = computer player * @param {Function} utilityFunction This function takes two arguments (col, row) and returns [utilityValue, validMove], where validMove is {Array} [isLegalMove, {"x":positionX, "y":positionY, "player":player},...] col, row: Base 0. * @returns {*} [bestLocation, nomoreMove] bestLocation = default [0,0,[false]] */ othelloGameGetBestPosition: function(boardCellStates, utilityFunction){ return _gitf101(boardCellStates, utilityFunction); }, /** * * @param {number} col base 0 * @param {number} row base 0 * @param {number} interval blinking interval * @param {number} duration msec blink for this duration * @param {string} normalTileIndex normal board tile * @param {string} highlightBoardTileIndex tile that will be used as a highlighted tile * @param {Object} boardTileMap Phaser.Tilemap * @param {Object} tileMapBoardLayer Phaser.TilemapLayer * @param {Function} callback This is called after the duration */ blinkTile: function(col, row, interval, duration, normalTileIndex, highlightBoardTileIndex, boardTileMap, tileMapBoardLayer, callback){ _gitf100(col, row, interval, duration, normalTileIndex, highlightBoardTileIndex, boardTileMap, tileMapBoardLayer, callback); }, /** * Scan a direction to count the number of stones in a straight line for the given player * It returns [numberOfStones, isEmptyEnd]. * E.g., [4,true] means, there are 4 stones in the straight line (not including the current location) * and it ends with an empty cell. * If current location is not empty, it returns [-1, false]. Set checkIfEmpty to false to diable checking the current location. * * @param {number} col Scan for this location. Base 1 and less than * @param {number} row Scan for this location. Base 1 * @param {Array} directionVector [1,0] for right, [0,1] for up etc * @param {number} playerId Player id > 0 used in boardCellStates * @param {Array} boardCellStates The array representing the board M by M sqaure array * @param {boolean|null|undefined} [checkIfEmpty] Default true. If set to false, it will not check if the current location is empty * @returns {Array} [numberOfStones, isEmptyStart, isEmptyEnd] */ calcNumberOfStonesOnLine: function(col, row, directionVector, playerId, boardCellStates, checkIfEmpty){ return _gitf103(col, row, directionVector, playerId, boardCellStates, checkIfEmpty); }, /** * Calculate a location having the longest strait line of pads for a player for a board game. * The board is defined as an M by N array. The first row and col are boundary row and col, where pads cannot be placed. * * @param {number} playerId Player id on boardCellStates[row][col]. boardCellStates.length-2 is the number of rows and cols of the board. * @param {Array} boardCellStates The array representing the board M by M square array * @param {boolean|null|undefined} [checkIfEmpty] Default true. If set to false, it will not check if the current location is empty * @returns {Array} [col, row, numberOfStone, isEmptyStart, isEmptyEnd] */ calcMaxLengthLocationForPlayer: function(playerId, boardCellStates, checkIfEmpty) { return _gitf104(playerId, boardCellStates, checkIfEmpty); }, /** * Perform the initial configuration after loading game contents before starting states * @deprecated */ configSystem: function(){ //----------------------------------------------- // DO NOT change these lines ga_assets_common = game_common_assets; ga_assets_common["imagesSprites"]["userIcon"] = [Genari.getUserPhoto()]; ga_assets_themes = game_themes; // load API interface classes and classes extending the interface classes Genari.loadClasses(myClassLoader); // DEVELOPER_CODE REMOVE_FOR_THEME }, /** * Perform the initial configuration after loading game contents before starting states * ** All games using this must use Genari.k.assetKeyName to refer to the game assets * Common theme assets are automatically loaded before the game starts * Theme assets are loaded if ... * The created game is stored in Genari.dcGame * * @param {Function} GameClass Genari.Game * @param {number|undefined} [gameWidth] Default 800px * @param {number|undefined} [gameHeight] Default 428px * @param {Function|undefined} [ControlClass] Default Genari.Control * @param {Function|undefined} [PlayClass] Default Genari.StatePlay * @param {Function|undefined} [MenuClass] Default Genari.StateMenu * @param {Function|undefined} [ErrorClass] Default Genari.StateError * @param {string|undefined} [gamePhysics] Default ARCADE. Set to P2JS for Physics engine */ prepareGame: function(GameClass, gameWidth, gameHeight, ControlClass, PlayClass, MenuClass, ErrorClass, gamePhysics){ ibg_prepareGame(GameClass, gameWidth, gameHeight, ControlClass, PlayClass, MenuClass, ErrorClass, gamePhysics); }, loadScore: function(){ ibg_loadScore(); }, /** * Add the splash screen during the menu state with copyright notice. * @param {string|undefined} [key] Image asset key */ addBanner: function(key){ ibg_addBanner(key); }, /** * Create audio assets from the asset list * @param assetList */ addAudioFromList: function(assetList){ for (var k in assetList){ if (assetList.hasOwnProperty(k)) { Genari.dcGame.audioAssets[k] = Genari.phaserAddAudio(k); } } }, /** * @deprecated * @param urlToTileMap */ loadWorldTileMap: function(urlToTileMap){ Genari.phaserGame["load"]["tilemap"]( 'worldTileMap', urlToTileMap, null, Phaser["Tilemap"]["TILED_JSON"] ); }, loadThemeTileMaps: function(){ _gitf074(); }, /** * Load all image and sprite assets in the list * @param assetList */ loadImageSpriteAssets: function(assetList){ _gitf075(assetList); }, /** * Load an Image or Sprite asset * @deprecated * @param key * @param assetDesc [key, url] for image, [key, url, wiidth, height] for sprite */ loadImageSpriteAsset: function(key, assetDesc){ if(assetDesc.length >1){ // sprite Genari.phaserLoadSpriteSheet(key, assetDesc[0], assetDesc[1], assetDesc[2]); }else{ // image Genari.phaserLoadImage(key, assetDesc[0]); } }, /** * Load all image and sprite assets in the list * @param assetList */ loadAudioAssets: function(assetList){ _gitf076(assetList); }, /** * Load all image and sprite assets in the list */ loadThemeAudioAssets: function(){ _gitf076(Genari.getTheme()["audio"]); }, loadThemeImageSpriteAssets: function(){ _gitf077(); }, /** * @deprecated * @param key * @param theme */ loadThemeAsset: function(key, theme){ if(theme[key]){ if(theme[key].length >1){ // sprite Genari.phaserLoadSpriteSheet(key, theme[key][0], theme[key][1], theme[key][2]); }else{ // image Genari.phaserLoadImage(key, theme[key][0]); } } }, /** * Load question assets, question answer assets, and * all level answer assets for the level: images and audio. * * These are assets specified by content authors, not theme assets. * Call this in the preload function of the play-state * * There are two types of assets: * Level question image and audio (for all games) * Level question answer images and audios (for memory card games) * Level answer images and audios (for non-memory card games) * @param {Function|undefined} [fileComplete] * @param {Function|undefined} [loadComplete] * @param {Function|undefined} [callBackContext] */ loadLevelAssets: function(fileComplete, loadComplete, callBackContext){ pdebug("loadLevelAssets start--------------"); _gitf088(fileComplete, loadComplete, callBackContext); pdebug("loadLevelAssets complete---------------"); }, /** * Call the callback after delay ms * @param {number} delay ms * @param {Function} callback * @param {Object} [context] */ delayedCall: function(delay, callback, context){ ibg_delayedCall(delay, callback, context); }, /** * Synchronous foreach * @param {Array} array * @param {Function} callForEachElement This is called for all non-last element * @param {Function} callLast this is called for the last element */ synchronousForEach: function(array, callForEachElement, callLast){ var arrayLength = array.length; for (var i = 0; i < arrayLength; i++) { if(i >= array.length-1){ callLast(array[i], i); }else{ callForEachElement(array[i], i); } } }, /** * Get all tiles (Phaser.Tile) with given ID. * @param tileMap Phaser.Tilemap * @param tileID The given ID to match tiles with. * @returns {Array} The array of Phaser.Tile having the given tile Id. */ getTilesById: function(tileMap, tileID) { return _gitf097(tileMap, tileID); }, //---------------------------------------------------------------------- // Object factories add: { /** @return {Genari.MiniMap} */ miniMap: function(key, x, y, playerSprite, scaleFactor, mapSize, layer){ return new Genari.MiniMap(key, x, y, playerSprite, scaleFactor, mapSize, layer); }, /** * * @param {number} x The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number} y The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number|undefined} width Width of the bar * @param {number} height * @param {number} initialNumber The number to be displayed when the bar is first created. * @param {number} minNumber The number which is represented by the starting point. * @param {number} maxNumber The number which is represented by the ending point. * @param {string} frameKey The sprite key which is used to be the frame of progress bar. * @param {string} barKey The sprite key which is used to be the bar itself. * @param {Object|undefined} [layer] Phaser Group * @param {number|undefined} [barXoffset] The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number|undefined} [barYoffset] The horizontal position (x-coordinate) of the progress bar, i.e. frame * @returns {Genari.CounterBar} */ counterBar: function(x, y, width, height, initialNumber, minNumber, maxNumber, frameKey, barKey, layer, barXoffset, barYoffset) { return new Genari.CounterBar(x, y, width, height, initialNumber, minNumber, maxNumber, frameKey, barKey, layer, barXoffset, barYoffset); }, /** * * @param {number} x The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number} y The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number|undefined} width Width of the bar * @param {number|undefined} height * @param {number} initialNumber The number to be displayed when the bar is first created. * @param {number} minNumber The number which is represented by the starting point. * @param {number} maxNumber The number which is represented by the ending point. * @param {string} frameKey The sprite key which is used to be the frame of progress bar. * @param {string} barKey The sprite key which is used to be the bar itself. * @param {Object} [layer] Phaser Group * @param {number} [barXoffset] The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number} [barYoffset] The horizontal position (x-coordinate) of the progress bar, i.e. frame * @returns {Genari.TimerBar} */ timerBar: function(x, y, width, height, initialNumber, minNumber, maxNumber, frameKey, barKey, layer, barXoffset, barYoffset) { return new Genari.TimerBar(x, y, width, height, initialNumber, minNumber, maxNumber, frameKey, barKey, layer, barXoffset, barYoffset); }, /** @return {Genari.ScoreBox} */ scoreBox: function(key, size, endX, y, layer){ return new Genari.ScoreBox(key, size, endX, y, layer); }, /** @return {Genari.Hud} */ hud: function(layer){ return new Genari.Hud(layer); } }, /** * Predefined asset keys * Use Genari.k.assetKeyName format **/ k:{ _userLoginSpriteKey: "_userLoginSprite", _userRewardImgKey: "_userRewardImg", _userChapterImgKey: "_userChapterImg", _userTodayImgKey: "_userTodayImg", _userRewardBkgrImgKey: "_userRewardBkgrImg", bannerImgKey: "bannerImg", menuMusicKey: "menuMusic", // Played when at the beginning of the game endMusicKey: "endMusic", // Played when game over dialogBoxKey: "dialogBoxFrameImg", // Dialog box frame // Dialog box buttons exitButtonSpriteKey: "exitBtn", restartButtonSpriteKey: "restartBtn", resumeButtonSpriteKey: "resumeBtn", retryButtonSpriteKey: "retryBtn", // Button used for error state // HUD UI pauseButtonSpriteKey: "pauseBtn", leftButtonSpriteKey: "leftBtn", // optional rightButtonSpriteKey: "rightBtn", // optional downButtonSpriteKey: "downBtn", // optional rotateButtonSpriteKey: "rotateBtn", // optional jumpButtonSpriteKey: "jumpBtn", // optional shootButtonSpriteKey: "shootBtn", // optional scoreReelSpriteKey: "scoreReelSprite", // Reels of the score bar // Common theme specific assets backgroundImgKey: "backgroundImg", // optional lifeIconImgKey: "lifeIconImg", // optional wordBoxFrameImgKey: "wordBoxFrameImg",// optional backgroundMusicKey: "backgroundMusic",// Theme asset: played while playing the game playerSpriteKey: "playerCharSprite", // Player character sprite openingSoundKey: "openingSnd", // optional jumpSoundKey: "jumpSnd", // optional bulletSoundKey: "shootGunSnd", // optional bulletSpriteKey: "bulletImg", // optional fallDownSndKey: "fallDownSnd", // optional explosionSndKey: "explosionSnd", // optional explosionSpriteKey: "explosionSprite",// optional correctSndKey: "correctSnd", // optional incorrectSndKey: "incorrectSnd", // optional collectSndKey: "collectSnd", fightingSndKey: "fightingSnd", // optional carPhysicsDataKey: "sprite_physics", // optional carObjNameInPhysicsData: "car", // optional // Tilemap can have layers. These are default layers. When creating tilemaps, use these names tileMapBackgroundLayerName: "BackgroundLayer", /** @deprecated use tileMapCollisionLayerName*/ tileMapCollisonLayerName: "CollisionLayer", tileMapCollisionLayerName: "CollisionLayer", userPhotoKey: "userIcon", // Builtin asset for user photo userPhotoFrameKey: "userIconFrame" // User's profile photo frame image is loaded using this key } }; // Exporting for testing //window["Genari"] = Genari; // DEVELOPER_CODE REMOVE_FOR_THEME //----------------------------------------------------------------------------------- // Effect functions Genari.Effect = { /** * Set the layer to show the effects. Set to button or dialogbox layer * @param layer */ setEffectLayer: function(layer){ DCEffect.setEffectLayer(layer); }, /** * Create lightning effects from startPos to endPos * @param {number} x * @param {number} y * @param {number} delay in msec. Delay before the effect * @param {number} duration in msec * @param {boolean|undefined} [redraw] Recreate the lightning * @param {number|undefined} [width] Width of the lightning area * @param {number|undefined} [height] The length of the lightining * @param {number|undefined} [angle] Radian. 0 = down, PI/2 = left, PI = up, -PI/2 = right * @param {string|undefined} [strokeStyle] Lightning stoke style. Default 'rgb(255, 255, 255)', white color * @param {string|undefined} [soundKey] Sound asset key to play for the effect * @param {Function|undefined} [callback] * @param {Object|undefined} [callContext] * @param {number|undefined} [delayAfter] in msec. Delay after the effect * @param {Array|undefined} [callBackParameters] Parameters of the callback */ effLightning: function (x, y, delay, duration, redraw, width, height, angle, strokeStyle, soundKey, callback, callContext, delayAfter, callBackParameters) { DCEffect.effLightning(x, y, delay, duration, redraw, width, height, angle, strokeStyle, soundKey, callback, callContext, callBackParameters, delayAfter); }, /** * Method which highlight a rectagular object boundary. * @param {Object} phaserObj A Phaser display object: group, text, button, image, sprite * @param {number} delay msec * @param {number} duration msec * @param {Function} [callback] * @param {Object} [callContext] * @param {Array} [callBackParameters] Parameters of the callback */ effHighlightRectangleObj: function(phaserObj, delay, duration, callback, callContext, callBackParameters){ DCEffect.effHighlightRectangleObj(phaserObj, delay, duration, callback, callContext, callBackParameters); }, /** * Shake the Phaser display object * @param {Object} phaserDisplayObject Object to shake. * @param {number} [delay] msec Default 0 * @param {number} [duration] msec Default 500 msec * @param {number} [shrinkScale] Default 0.9. Shrink by 10% * @param {number} [enlargeScale] Default 1.1 Enlarge by 10% * @param {Function} [callback] * @param {Object} [callContext] * @param {Array} [callBackParameters] Parameters of the callback */ effShake: function(phaserDisplayObject, delay, duration, shrinkScale, enlargeScale, callback, callContext, callBackParameters){ DCEffect.effShake(phaserDisplayObject, delay, duration, shrinkScale, enlargeScale, callback, callContext, callBackParameters); }, /** * pop coin effect * @param {Object} startPoint This can be Phaser.Pointer or simply {"x":x, "y":y} * @param {Object} endPoint This can be Phaser.Pointer or simply {"x":x, "y":y} * @param {number} [delay] msec * @param {number} [duration] msec * @param {string} [particleKey] * @param {Function} [callback] * @param {Object} [callContext] * @param {Array} [callBackParameters] Parameters of the callback * @param {number} [delayAfter] msec Default 0 */ effCoin: function(startPoint, endPoint, delay, duration, particleKey, callback, callContext, callBackParameters, delayAfter){ DCEffect.effCoin(startPoint, endPoint, delay, duration, particleKey, callback, callContext, callBackParameters, delayAfter) }, /** * Flip horizontally * @param {Array} phaserDisplayObj An array of Phaser display objects * @param {number} [delay] msec * @param {number} [inDuration] msec * @param {number} [outDuration] msec * @param {Function} [callback] * @param {Object} [callContext] * @param {Array} [callBackParameters] Parameters of the callback */ effFlip: function(phaserDisplayObj, delay, inDuration, outDuration, callback, callContext, callBackParameters){ DCEffect.effFlip(phaserDisplayObj, delay, inDuration, outDuration, callback, callContext, callBackParameters); }, /** * Show score at the top center of the target sprite. * Play answer sound if available. * Play correct or incorrect sound based on the score. * @param {Object} targetSprite * @param {string|number|undefined} [score] Default 1 * @param {number|undefined} [x] Default center of the target sprite * @param {number|undefined} [y] Default the top of the target sprite * @param {Object|undefined} [style] font style of the bubble text * @param {string|undefined} [bubbleSpriteKey] if provided, show this sprite (e.g., Star) in addition to the score text * @param {number|undefined} [duration] How long show we show. Default 500 msec * @param {number|undefined} [textOffsetX] Offset of text relative to the bubbleSprite. Default -8 px * @param {number|undefined} [textOffsetY] Default -8 px * @param {string|undefined} [currencySign] Default "+-" * @param {string|undefined} [bubbleSound] */ bubbleScore: function(targetSprite, score, x, y, style, bubbleSpriteKey, duration, textOffsetX, textOffsetY, currencySign, bubbleSound){ ibg_bubbleScore(targetSprite, score, x, y, style, bubbleSpriteKey, duration, textOffsetX, textOffsetY, currencySign, bubbleSound); }, /** * Add an explosion sprite, animation, and add to the layer * @param {string} key * @param {string} [animationName] * @param {Object} [layer] Phaser.Group Default effectLayer set by Genari.Effect.setEffectLayer() * @return {Object} Phaser sprite of the xxplosion animation */ addExplosion: function(key, animationName, layer){ return DCEffect.addExplosion(key, animationName, layer); }, /** * Play explosion animation at the target sprite object * @param {Object} targetSprite object where we show the explosion * @param {boolean} [destroy] Set to true to destroy * @param {Object} [explosionSprite] Sprite animation for the explosion * @param {string} [animationName] Animation name */ explosion: function(targetSprite, destroy, explosionSprite, animationName){ DCEffect.explosion(targetSprite, destroy, explosionSprite, animationName); } }; //------------------------------------------------------- // http://phaser.io/docs/2.4.4/Phaser.State.html // Phaser state. Must use "name" format for these // create, initload, Render, loadUpdate, paused, pauseUpdate, preload, // preRender, render, resize, resumed, shutdown, update // Public methods called by Phaser: // init is the very first function called when your State starts up. It's called before preload, // It's called before preload, create or anything else. // If you need to route the game away to another State you could do so here, or // if you need to prepare a set of variables or objects before the preloading starts. // preload is called first. Normally you'd use this to load your game assets (or those needed for the current State) // ** You shouldn't create any objects in this method that require assets that you're also loading in this method, // as they won't yet be available. // create is called once preload has completed, this includes the loading of any assets from the Loader. // preRender method is called after all Game Objects have been updated, but before any rendering takes place. // resumed. This method will be called when the core game loop resumes from a paused state. // shutdown: This method will be called when the State is shutdown (i.e. you switch to another state from this one). // resize: If your game is set to Scalemode RESIZE then each time the browser resizes it will call this function, passing in the new width and height. // update: The update method is left empty for your own use. // It is called during the core game loop AFTER debug, physics, plugins and the Stage have had their preUpdate methods called. /********************************************************************************************* * A Phaser state. Used by Genari.Games * This is used to add new Phaser states E.g., play, error, menu * See app_class.js to see how this class is extended to create the menu state and play state classes. * * @param {Genari.Game} theGameObj An instance of Genari.Game, the only game object. * @param {string} key Name of the state E.g., "play". This is used to register and start the state using Phaser. * * @constructor ********************************************************************************************/ Genari.GameState = function(theGameObj, key){ if( !(this instanceof Genari.GameState)){ return new Genari.GameState(theGameObj, key); } // Create a Phaser.State object and attach this. // TODO: remove this after testing. Working without this call //Phaser["State"].call(this); // call parent constructor. // **Phaser is already loaded. // Genari.GameState extends Phaser.State class. // For inherited attributes and methods, see http://phaser.io/docs/2.4.4/Phaser.State.html // To start a state, call this.start(..) // Attributes that should not be redefined in subclasses. // If you redefine, it will simply replace things that are defined here. // It is ok to reassign new values, but must know its consequence. /** type{Genari.Game} */ this.dcGame = theGameObj; // An instance of Genari.Game, the only game object. /** type{Genari.Game} */ this.ga = theGameObj; this.phaserGame = this.dcGame.phaserGame; /** @type {Genari.Control} */ this.gameControl = null; this.key = key; this.worldTileMap = null; this.tileMapCollisionLayer = null; // Add this to Phaser state this.addState(key, this); // Replace Phaser.State methods // Implement this on your extended classes by redefining them like this but with proper function body. // DO NOT use Genari.GameState.prototype.preload approach for these functions. Must redefine with proper function body. this["preload"] = function(){}.bind(this); // redefine this in the sub-class this["create"] = function(){}.bind(this); // redefine this in the sub-class this["update"] = function(){}.bind(this); // redefine this in the sub-class }; Genari.GameState.prototype.constructor = Genari.GameState; // set constructor property // You can override these methods in subclasses, but make sure to call superclass methods like this: // Genari.GameState.prototype.methodName.call(this, ....); /** * Call this to add a new state * @param key * @param phaserState */ Genari.GameState.prototype.addState = function(key, phaserState){ _gitf011(key, phaserState); }; /** * Start this state. This causes Phaser to call preload() and create() of this state * @param {boolean|undefined} [clearWorld] * @param {boolean|undefined} [clearCache] */ Genari.GameState.prototype.start = function(clearWorld, clearCache){ _gitf012(this.key, clearWorld, clearCache); }; /** * basic house keeping. Call this from update() */ Genari.GameState.prototype.stateCheck = function(){ //_gitf042(); }; /** * The default function that display the level opening dialog box. * * Usually you don't need to customise this. Use this default if possible. * It displays the level question and ask user to click or press enter to start the game level. * It calls GameState.openingDialogAction() if clicked. * openingDialogAction() then un-pause the game and start the game. * This also plays the question audio if provided. * * Style examples (default styles): * titleStyle = {"font": '24px Arial', "fill": "#000000", "stroke":'#ffff00', "strokeThickness":6}; * questionStyle = {"font": '20px Arial', "fill": "#000000", "wordWrap": true, "stroke":'#FFFFFF', "strokeThickness":6, * "wordWrapWidth": ga.gameDialogBox.width-50}; * instructionStyle = {"font": '20px Arial', "fill": "#000000", "stroke":'#FFFFFF', "strokeThickness":6}; * * @param {Object|undefined} [titleStyle] CSS style of the text * @param {Object|undefined} [questionStyle] CSS style of the text * @param {Object|undefined} [instructionStyle] CSS style of the text * @param {boolean|undefined} [playBackgroundMusic] * @param {number|undefined} [titleYOffset] Y offset of the title. Use this to adjust the y location of the title * @param {string|undefined} [strokeColor] Default "#ffffff" white. */ Genari.GameState.prototype.showLevelOpeningDialogBox = function(titleStyle, questionStyle, instructionStyle, playBackgroundMusic, titleYOffset, strokeColor){ ibg_showLevelOpeningDialogBox.call(this, titleStyle, questionStyle, instructionStyle, playBackgroundMusic, titleYOffset, strokeColor); }; /** * When play-state starts, it shows the opening dialog box. * This is called when the user click/enter in the level opening dialog box. * Override this ONLY if need to customise it. * @param [playBackgroundMusic] Default true. Set to true to play the game level background music */ Genari.GameState.prototype.openingDialogAction = function(playBackgroundMusic) { ibg_openingDialogAction(this.dcGame, playBackgroundMusic); this.isPlaying = true; }; /** * Helper function that load a tilemap image asset * @param timeMapImageItem */ Genari.GameState.prototype.loadTileMapImage = function(timeMapImageItem){ ibg_loadTileMapImage(timeMapImageItem); }; /** * Add all tilemaps to the stage for the current theme. * We must do this before importing (creating) layers within the tilemaps. * * @param gridWidth * @param gridHeight * @return {Object} dictionary of tilemaps imported. */ Genari.GameState.prototype.addThemeTileMaps = function(gridWidth, gridHeight){ return ibg_addThemeTileMaps.call(this, gridWidth, gridHeight); }; /** * Load all layers of the theme * @param layer Rendering layer */ Genari.GameState.prototype.createThemeTileMapLayers = function(layer){ ibg_createThemeTileMapLayers.call(this, layer); }; /** * Add tile set images * @param tileMap * @param tileSetImages * @param gridWidth * @param gridHeight */ Genari.GameState.prototype.addTileSetImages = function(tileMap, tileSetImages, gridWidth, gridHeight){ ibg_addTileSetImages(tileMap, tileSetImages, gridWidth, gridHeight); }; /** * @deprecated * @returns {Object} Phaser.Tilemap */ Genari.GameState.prototype.placeWorldTileMap = function(){ return ibg_placeWorldTileMap.call(this); }; /** * @deprecated * @param gridWidth * @param gridHeight */ Genari.GameState.prototype.placeTileSetImages = function(gridWidth, gridHeight){ ibg_placeTileSetImages.call(this, gridWidth, gridHeight); }; /** * * @param tileSetNameInTheTileMap * @param imageKey * @param gridWidth * @param gridHeight */ Genari.GameState.prototype.placeTileSetImage = function(tileSetNameInTheTileMap, imageKey, gridWidth, gridHeight){ ibg_placeTileSetImage.call(this, tileSetNameInTheTileMap, imageKey, gridWidth, gridHeight); }; /** * @deprecated Use createTileMapLayer * @param layer * @param tileMapLayerName * @returns {*} */ Genari.GameState.prototype.loadTileMapLayer = function(layer, tileMapLayerName){ return this.createTileMapLayer(layer, tileMapLayerName); }; /** * Create a tilemap layer. tileMapLayerName must be defined in the tilemap you have loaded earlier. * @param {Object} layer The rendering layer to order the rendering of the layer. * @param {string} [tileMapLayerName] * @returns {Object} Phaser.TilemapLayer */ Genari.GameState.prototype.createTileMapLayer = function(layer, tileMapLayerName){ return ibg_createTileMapLayer.call(this, layer, tileMapLayerName); }; /** * @param startTileIndex * @param endTileIndex * @param collide * @param tileMapLayerName */ Genari.GameState.prototype.setTileMapCollisionBetween = function(startTileIndex, endTileIndex, collide, tileMapLayerName){ if(this.worldTileMap) this.worldTileMap["setCollisionBetween"](startTileIndex, endTileIndex, collide, tileMapLayerName); else this.tileMaps["worldTileMap"]["setCollisionBetween"](startTileIndex, endTileIndex, collide, tileMapLayerName); }; /** * TODO: rename as createTileMapBackgroundLayer * Create a tilemap layer for the background. * @param layer * @param backgroundLayerName */ Genari.GameState.prototype.createTileMapBackgroundLayer = function(layer, backgroundLayerName){ ibg_createTileMapBackgroundLayer.call(this, layer, backgroundLayerName); }; /** * @deprecated Use createTileMapBackgroundLayer * @param layer * @param backgroundLayerName */ Genari.GameState.prototype.loadTileMapBackgroundLayer = function(layer, backgroundLayerName) { this.createTileMapBackgroundLayer(layer, backgroundLayerName); }; /** * TODO: rename as createTileMapBackgroundLayer * @param layer * @param {string|undefined} [collisionLayerName] The layer name in Tiled. Tiles in this layer will block movements of payer and monsters. * @param {number|undefined} [startTileIndex] Start index of tiles that will collide with player and monsters. * @param {number|undefined} [endTileIndex] End index of tiles that will collide with player and monsters. */ Genari.GameState.prototype.createTileMapCollisionLayer = function(layer, collisionLayerName, startTileIndex, endTileIndex){ ibg_createTileMapCollisionLayer.call(this, layer, collisionLayerName, startTileIndex, endTileIndex); }; /** * @deprecated use createTileMapCollisionLayer * @param layer * @param collisionLayerName * @param startTileIndex * @param endTileIndex */ Genari.GameState.prototype.loadTileMapCollisionLayer = function(layer, collisionLayerName, startTileIndex, endTileIndex) { this.createTileMapCollisionLayer(layer, collisionLayerName, startTileIndex, endTileIndex); }; /************************************************************** * Phaser Error state class for displaying error messages. * * @param {Genari.Game} theGameObj An instance of Genari.Game, the only game object. * @param {string} key Name of the state E.g., "play". This is used to register and start the state using Phaser. * * @constructor * @extends {Genari.GameState} **************************************************************/ Genari.StateError = function(theGameObj, key) { if (!(this instanceof Genari.StateError)) return new Genari.StateError(theGameObj, key); Genari.GameState.call(this, theGameObj, key); // call parent constructor this["preload"] = function() { }; this["create"] = function() { var ga = this.dcGame; ga.setToBaseScaleMode(); var error = Genari.phaserAddText(0,0, "Sorry, network error. Please check network connection", {fill:"#ffffff"}); error["x"] += Genari.calcBoxCenterX(ga.phaserGame["camera"], error); error["y"] = Genari.calcBoxCenterY(ga.phaserGame["camera"], error) - 40; var bt = Genari.phaserAddButton(0,0,Genari.k.retryButtonSpriteKey, function(){ var ga = this.dcGame; ga.startGame(); }.bind(this), ga, 0, 1, 2, 1 ); bt["x"] = Genari.calcBoxCenterX(ga.phaserGame["camera"], bt); bt["y"] = Genari.calcBoxCenterY(ga.phaserGame["camera"], bt) + 40; ga.setToScaledMode(); }; }; Genari.StateError.prototype = Object.create(Genari.GameState.prototype); // extend DBGame Genari.StateError.prototype.constructor = Genari.StateError; // set constructor property /**************************************************************** * Phaser state class, display splash screen. This is the main Menu * * @param {Genari.Game} theGameObj An instance of Genari.Game, the only game object. * @param {string} key Name of the state E.g., "play". This is used to register and start the state using Phaser. * * @constructor * @extends {Genari.GameState} ***************************************************************/ Genari.StateMenu = function(theGameObj, key){ if( !(this instanceof Genari.StateMenu)) return new Genari.StateMenu(theGameObj, key); Genari.GameState.call(this, theGameObj, key); // call parent constructor this["preload"] = function() { }.bind(this); this["create"] = function() { var ga = this.dcGame; // scale to original scale. ** Must do this this.dcGame.setToBaseScaleMode(); ga.removeGameDialogBox(); ga.totalGameScore = 0; Genari.addBanner(); var left = ga.game_width/2-(3*92/2); this.createPlayerStat(left, 15, Genari.k._userRewardImgKey, "rp_total"); this.createPlayerStat(left+92, 15, Genari.k._userChapterImgKey, "rp_item"); this.createPlayerStat(left+184, 15, Genari.k._userTodayImgKey, "rp_item_day"); // TODO: Browser does not permit audio play without user interactions. This prevents the audio starting automatically. // Genari.phaserGame["input"]["onDown"]["addOnce"](function() { // Genari.phaserGame["sound"]["context"]["resume"](); // ga.audioPlayLoopFull(Genari.k.menuMusicKey); // }); // TODO: prevent start if click login button // click or enter will load the game data from the server and starts the game (play state) ga.addDialogAction( function (e){ if(e["position"] && e["position"]["y"] < 120) return false; // pressed the status area var ga = this.dcGame; ga.isLevelCleared = false; // ga.audioStop(Genari.k.menuMusicKey); ga.removeGameDialogBox(); Genari.phaserGame["sound"]["context"]["resume"](); // Load the game level data from server and start the game level ga.startGame(); //ibGetCurrentGameLevel(ga.startGameLevel.bind(ga)); return true; }.bind(this), this ); if (itf_getUserInfo()["user_id"] <= 0) { ga.addButton( 5, 10, Genari.k._userLoginSpriteKey, function() { _itf36(); // open login box }); } // Scale to fit the window. ** Must do this this.dcGame.setToScaledMode(); // TODO: check. Sometimes game does not rescale //ga.phaserGame["scale"]["refresh"](); }.bind(this); }; Genari.StateMenu.prototype = Object.create(Genari.GameState.prototype); // extend DBGame Genari.StateMenu.prototype.constructor = Genari.StateMenu; // set constructor property /** * Add player stat icons. * @param x * @param y * @param imageKey * @param rewardType */ Genari.StateMenu.prototype.createPlayerStat = function(x, y, imageKey, rewardType) { ibg_createPlayerStat(x, y, imageKey, rewardType); }; /************************************************************** * Phaser state class, Play state * Extend this class to customise your Play state * * @param {Genari.Game} theGameObj An instance of Genari.Game, the only game object. * @param {string} key Name of the state E.g., "play". This is used to register and start the state using Phaser. * * @constructor * @extends {Genari.GameState} **************************************************************/ Genari.StatePlay = function(theGameObj, key){ if( !(this instanceof Genari.StatePlay)) return new Genari.StatePlay(theGameObj, key); Genari.GameState.call(this, theGameObj, key); // call parent constructor // Game states this.isPlaying = false; // used to prevent update being processed during state transition this.isLevelCleared = false; // is repeating the game? this.pauseMenuButtons = []; // this is used to hold the buttons on the pause dialog-box /** * The player character * @type {Genari.Player} **/ this.player = null; /** * Called by Phaser to preload assets for the state. This download the game assets from the server. * We use ["name"] format so Phaser can call this. * ** Do not re-assignn this attribute */ this["preload"] = function() { pdebug("Play State::preload--------------------"); this.preloadState(); // We call this so developers can override this. }.bind(this); /** * Called by Phaser to create the state. This create Game assets and place them on the stage * We use ["name"] format so Phaser can call this. * ** Do not re-assign this attribute */ this["create"] = function() { //console.log("Play State::create--------------------"); // Create world, hud, player, Genari.Control this.createState(); // We call this so developers can override this. }.bind(this); /** * Called by Phaser to update the state. Pahser call for every frame before it is rendered. * We need to update location, size, color, etc so the updated state can be rendered for this frame. * We use ["name"] format so Phaser can call this. * ** Do not re-assignn this attribute */ this["update"] = function() { this.updateState(); // We call this so developers can override this. }.bind(this); // Clean up assets this["shutdown"] = function() { this.shutdownState(); // We call this so developers can override this. }.bind(this); }; Genari.StatePlay.prototype = Object.create(Genari.GameState.prototype); // extend DBGame Genari.StatePlay.prototype.constructor = Genari.StatePlay; // set constructor property /** * Called by Phaser to preload the state * This places all loading requests in Phaser loader queue and show the progress * * Override this if need to customise * @param {boolean|undefined} [isMemoryCardGame] Set to true to load for memory card game. */ Genari.StatePlay.prototype.preloadState = function(isMemoryCardGame){ ibg_preloadState.call(this, isMemoryCardGame); }; /** * Called by Genari.StatePlay.preloadState to load theme assets * Load all tilemaps, images, sprites, and audio assets of the current theme * TODO for Dev: Override this to customise */ Genari.StatePlay.prototype.loadThemeAssets = function(){ pdebug("Preloading level theme assets--------------"); // Load tileMap assets before use Genari.loadThemeTileMaps(); Genari.loadThemeImageSpriteAssets(); // load all images and sprites including tileset images here Genari.loadThemeAudioAssets(); // We should wait until all assets are loaded }; /** * Called by Phaser to create the state * Do not override this. * Developers should override createLayersGroups, createStateObjects * @protected */ Genari.StatePlay.prototype.createState = function(){ this.createLayersGroups(); var ga = Genari.dcGame; // ** Must set scale to the original game scale before adding game objects ga.setToBaseScaleMode(); // Add theme and level audio assets to stage, so they can be played ga.addThemeAudio(); ga.addLevelAudio(); // We now add image, sprite, tilemap game assets this.createStateObjects(); // Hide the on screen buttons added by Genari.Control before showing a dialog box ga.gameControl.hideOnScreenButtons(); // Show Level opening dialog box this.showLevelOpeningDialogBox(); // Set to scale mode. Now we cannot add objects anymore. ga.setToScaledMode(); // Hide the loading message ga.hideLoading(); }; /** * Called before play-state starts run for us to prepare. * Create rendering layers and game object Groups * Layers are used to control the rendering order. Layers created later will be shown on top of the layers created earlier. * Use Groups to manage a set of game objects that share same behaviors and rendering layers. * * TODO for Dev: Override this to customise. */ Genari.StatePlay.prototype.createLayersGroups = function() { var ga = Genari.dcGame; // Add layers. You can add your own layers to control z-order. if(ga.layerBottom) ga.layerBottom.destroy(); if(ga.layerPlayer) ga.layerPlayer.destroy(); if(ga.layerEffects) ga.layerEffects.destroy(); if(ga.layerButtons) ga.layerButtons.destroy(); if(ga.layerDialog) ga.layerDialog.destroy(); // layers are ordered based on the order they are created ga.layerBottom = new Genari.Layer(); // Use this as the bottom layer, Always show at the bottom. Holds background, platforms ga.layerPlayer = new Genari.Layer(); // holds players, monsters, player interactive items. ga.layerEffects = new Genari.Layer(); // holds explosions, bullets, effects ga.layerButtons = new Genari.Layer(); // holds control buttons, frames, windows, HUD items ga.layerDialog = new Genari.Layer(); // Always show at the top. Holds dialog boxes. Top layer if(ga.groupPlatform) ga.groupPlatform.destroy(); ga.groupPlatform = new Genari.PlatformGroup(ga.layerBottom); // put all collidable platform items, such as buildings Genari.Effect.setEffectLayer(ga.layerEffects); // force all effects to be drawn on ga.layerEffects }; /** * Called before play-state starts run for us to prepare. * This places the assets to the stage to show * TODO for Dev: Override this to customise */ Genari.StatePlay.prototype.createStateObjects = function() { var ga = Genari.dcGame; // Create HUD this.createHud(); // Create the world: tilemaps, add objects this.createWorld(); // Create Player this.createPlayer(); // Create control keys and onscreen control buttons //ga.gameControl = new ga.ControlClass(this.dcGame); // game, player, bullet obj, bullet sound key // Create other effect objects //Genari.Effect.addExplosion(ga.explosionSpriteKey, ga.explosionSpriteKey, ga.layerPlayer); // Completed loading the game this.isPlaying = true; // we are now playing the level, Enable update }; /** * Called by Phaser to shutdown the state. * We add here stuff to clean * TODO for Dev: Override this to customise */ Genari.StatePlay.prototype.shutdownState = function(){ // Example: // var ga = Genari.dcGame; // // ga.phaserGame["cache"]["removeImage"](ga.backgroundImgKey); // ga.phaserGame["cache"]["removeImage"](ga.lifeIconImgKey); // ga.phaserGame["cache"]["removeSound"](ga.backgroundMusicKey); }; /** * Called before play-state starts run for us to prepare. * Create the game world * TODO for Dev: Override this to customise */ Genari.StatePlay.prototype.createWorld = function(){ // Sample code // var ga = this.dcGame; // // // Add background image to the stage // if(this.bkgr) this.bkgr["destroy"](); // this.bkgr = Genari.phaserAddTileSprite(0, 0, ga.phaserGame["width"], ga.phaserGame["height"], ga.backgroundImgKey); // ga.layerBottom["add"](this.bkgr); // // //--------------------------------------------------------- // // Place the loaded tilemap to the stage to show // this.addThemeTileMaps(16, 16); // // // load the background layer and show. // //this.loadTileMapBackgroundLayer(ga.layerBottom); // // // Now load "collisionLayer" that you created in the tilemap // // This set the rendering layer of the tilemap and turn on collisions for the tiles placed in the layer // this.createTileMapCollisionLayer(ga.layerBottom, null, 31, 46); // // //And set the tile indexes for collision of correct bin or incorrect bin. // ga.correctBinTileIndex = 42; // ga.incorrectBinTileIndex = 45; }; /** * Called before play-state starts run for us to prepare. * Create the player of the game * TODO for Dev: Override this to customise */ Genari.StatePlay.prototype.createPlayer = function () { }; /** * Called before play-state starts run for us to prepare. * Create the HUD of the game * * TODO for Dev: Override this to customise */ Genari.StatePlay.prototype.createHud = function (){ // Sample code // var ga = this.dcGame; // // ga.hud = Genari.add.hud(ga.layerButtons); // // // Add the pause button so that player can pause the game. // ga.hud.addPauseButton( // ga.BUTTON_EDGE_MARGIN, ga.BUTTON_EDGE_MARGIN, // ga.pauseButtonSpriteKey, 45, // ga.pause.bind(ga), // ga // ); // // // Add user Photo icon // ga.hud.addUserPhoto(ga.game_width - 160, ga.BUTTON_EDGE_MARGIN, Genari.k.userPhotoKey, Genari.k.userPhotoFrameKey, 40); // "userIcon" "userIconFrame" // // // Add life icon // ga.hud.addLifeIcon(ga.gc_life_icon_x, ga.BUTTON_EDGE_MARGIN, Genari.k.lifeIconImgKey); // // // Add Life text // ga.hud.addLifeText( // ga.gc_life_text_x, ga.BUTTON_EDGE_MARGIN+2, // ga.ga_remainingLife, // { fontSize: '32px', fill: '#0000ff' } // ); // // // Add the score box // ga.scoreBox = Genari.add.scoreBox(ga.scoreReelSprite, 30, ga.gc_score_text_x, 15, ga.layerButtons); // // // Add Level text // ga.hud.addLevelText(ga.game_width, 3, 'Level '+ (ga.currentGameLevel + 1), // { "fontSize": '18px', "fill": "#000000" } // ); // // // Add Game objective text // ga.hud.addGameObjectiveText(ga.game_width, 25, Genari.getQuestion().split('.')[0], // { "fontSize": '14px', "fill": "#000000" } // ); }; /** * Now, when play-state starts, this is called at every frame before a frame is rendered to the display. * Update states of game assets here. * We can change locations, size, style, content, camera location of the game. * ** The frame rate varies. Mobile devices will have very low frame rate * * TODO for Dev: Override this to customise * @return {boolean} Return this.isPlaying */ Genari.StatePlay.prototype.updateState = function(){ // If game level is over, stop updating. if(!this.isPlaying) return false; // Must call this for API to do some house work this.stateCheck(); // Update game control states if game is not over if (!this.ga.checkReachedEnd()) this.ga.gameControl.update(); // TODO: update game objects: locations, size, style, content, camera location of the game. // Use Group.update functions to update states of groups of game objects return true; }; /********************************************************************************************* * Base control class. Manages the main control keys and onscreen controls of the game. * Extend this for your control keys and onscreen buttons. * See DCRunControl in app_class.js for usage * * @param {Genari.Game} theGameObj The only game object * @param {Genari.Player|undefined} [player] The player character to be controlled * * @constructor ********************************************************************************************/ Genari.Control = function(theGameObj, player){ if( !(this instanceof Genari.Control)){ return new Genari.Control(theGameObj, player); } // Attributes that should not be redefined in subclasses. // If you redefine, it will simply replace things that are defined here. this.dcGame = theGameObj; this.dcGame.gameControl = this; this.dcGame.statePlay.gameControl = this; this.phaserGame = this.dcGame.phaserGame; /** @type {Genari.Player|null|undefined} */ this.player = player; // Joystick states this.joyStickLeftRight = 0; // + if right, - if left this.joyStickUpDown = 0; // + if up, - if down this.isPointerDown = false; // This is used to detect pointer down/up event in update() this.pointerX = 0; // scaled pointer location this.pointerY = 0; this.controlButtons = []; // holds the control buttons created for display /** @private */ this.controlButtonHitAreas = []; // holds the control buttons created for hit detection. // Constants. Change this for your game this.BUTTON_WIDTH = 75; this.BUTTON_EDGE_MARGIN = 10; }; Genari.Control.prototype.constructor = Genari.Control; // set constructor property // Override these methods in subclasses, but make sure to call superclass methods like this: // Genari.Control.prototype.methodName.call(this, ....); /** * Use this to process a press event (key or button) only once until it is released. * Use idx for up to 5 keys or buttons * E.g., this.firstClick(cursor.up.isDown, 0) * This will return true if up key is pressed for the first time until it is released * @param {boolean} cond The condition you want to check for this event. * @param {number} idx Index of the event 0 to 7: this can track max seven events * @return {boolean} Returns true if the condition for the event is the first time since the last time you called this. * @public */ Genari.Control.prototype.isFirstClick = function(cond, idx){ return _gitf043(cond, idx); }; // Destroy any existing managed buttons (buttons whose hitAreas are managed) Genari.Control.prototype.destroyControlButtons = function(){ _gitf013(this.controlButtons); this.controlButtons = []; this.destroyHitAreas(); }; /** @private */ Genari.Control.prototype.destroyHitAreas = function(){ _gitf013(this.controlButtonHitAreas); this.controlButtonHitAreas = []; }; /** * Create a hit area for a button. Phaser bug fix for button hit * @param btn * @param x * @param y * @param downAction * @param upAction * @param listenerContext * @param manage * @returns {Object} Phaser.Button * @protected */ Genari.Control.prototype.createHitArea = function (btn, x, y, downAction, upAction, listenerContext, manage){ return ibg_createHitArea.call(this, btn, x, y, downAction, upAction, listenerContext, manage); }; /** * Move the hit area of a button. * Call this if your buttons are moving around to update the button hit area. * @param btn * @param x * @param y */ Genari.Control.prototype.updateHitArea = function (btn, x, y){ ibg_updateHitArea.call(this, btn, x, y); }; /** * Call this to hide control buttons temporally */ Genari.Control.prototype.hideOnScreenButtons = function () { if(this.controlButtons) this.controlButtons.forEach(function(key){key["visible"] = false;}); }; Genari.Control.prototype.showOnScreenButtons = function () { if(this.controlButtons) this.controlButtons.forEach(function(key){key["visible"] = true;}); }; /** @protected */ Genari.Control.prototype.createButtonHitArea = function (){ _gitf004(this.destroyHitAreas, this.controlButtons, this.createHitArea, this); }; /** * Add a control button to the game. * The buttons are added to this.controlButtons[] array to update them automatically when resized. * * @param {number} x * @param {number} y * @param {string} key The asset name that is already loaded * @param {Function} downAction method of an object will be called when clicked * @param {Function} upAction method of an object will be called when button is up * @param {Object} listenerContext the object to which the methods are attached to. * @param {number} [alpha] alpha of the button. 1 = opaque, 0 = completely transparent (invisible) * @param {boolean} [fixedToCamera] Set to false to allow it move * @return {Object} Pahser.Button **/ Genari.Control.prototype.addControlButton = function(x, y, key, downAction, upAction, listenerContext, alpha, fixedToCamera) { return ibg_addControlButton.call(this, x, y, key, downAction, upAction, listenerContext, alpha, fixedToCamera); }; /** * Creates control buttons on-screen. * @param {number} buttonX The x-coordinate of the button to be placed on. * @param {string} buttonKey The key of the button to be used. * @param {Function} pressFunction The function that is triggered when the button is pressed. * @param {Function} releaseFunction The function that is triggered when the button is released. * @return {Object} Pahser.Button */ Genari.Control.prototype.createControlButton = function(buttonX, buttonKey, pressFunction, releaseFunction){ return this.addControlButton( buttonX, this.dcGame.game_height - this.BUTTON_WIDTH - 5, buttonKey, pressFunction, releaseFunction, this ); }; Genari.Control.prototype.checkCursorKeyLeftDown = function(){ return this.dcGame.cursorKeys["left"]["isDown"]; }; Genari.Control.prototype.checkCursorKeyRightDown = function(){ return this.dcGame.cursorKeys["right"]["isDown"]; }; Genari.Control.prototype.checkCursorKeyUpDown = function(){ return this.dcGame.cursorKeys["up"]["isDown"]; }; Genari.Control.prototype.checkCursorKeyDownDown = function(){ return this.dcGame.cursorKeys["down"]["isDown"]; }; Genari.Control.prototype.rescale = function(){ this.createButtonHitArea(); }; /** * Check pointer down (first touch) * @param callBackPointerDown Called for touch down * @param callBackPointerUp Called for lift * @return {number} 1 = Pointer down. -1 = Pointer up. 0 = no changes */ Genari.Control.prototype.checkPointerDown = function(callBackPointerDown, callBackPointerUp){ return ibg_checkPointerDown.call(this, callBackPointerDown, callBackPointerUp); }; /********************************************************************************************* * Player class * DO NOT EDIT. Override if necessary * @param {Genari.Game} theGameObj The only game object * @param {number} maxLife Name of the state E.g., "play" * @param {number} entryX Name of the state E.g., "play" * @param {number} entryY Name of the state E.g., "play" * * @constructor ********************************************************************************************/ Genari.Player = function(theGameObj, maxLife, entryX, entryY){ if( !(this instanceof Genari.Player)) return new Genari.Player(theGameObj, maxLife, entryX, entryY); // Attributes that should not be redefined in subclasses. // If you redefine, it will simply replace things that are defined here. this.dcGame = theGameObj; this.phaserGame = this.dcGame.phaserGame; this.dcGame.player = this; this.maxLife = maxLife || 3; this.remainingLife = this.maxLife; /** @type{Object} */ this.playerSprite = null; // Phaser.Sprite this.entryX = entryX || 32; this.entryY = entryY || this.dcGame.game_height/3; /** @deprecated */ this.playerEntryX = this.entryX; /** @deprecated */ this.playerEntryY = this.entryY; /** @deprecated */ this.gaPlayerEntryX = this.entryX; /** @deprecated */ this.gaPlayerEntryY = this.entryY; }; Genari.Player.prototype.constructor = Genari.Player; // set constructor property // You can override these methods in subclasses, but make sure to call superclass methods like this: // Genari.Player.prototype.methodName.call(this, ....); // ** DO NOT change this file. //Genari.Player.prototype.resetPlayer = function(){ //this.remainingLife = this.maxLife; //}; /** * @deprecated */ //Genari.Player.prototype.unPause = function(){ // Un pause the player, allowing it move // Implement this on your player //this.player["animations"]["paused"] = false; //this.player["body"]["enable"] = true; //}; Genari.Player.prototype.resume = function(){ // Un pause the player, allowing it move // Implement this on your player if(this.playerSprite){ this.playerSprite["animations"]["paused"] = false; this.playerSprite["body"]["enable"] = true; } }; Genari.Player.prototype.pause = function(){ // Implement this on your player if(this.playerSprite){ this.playerSprite["animations"]["paused"] = true; this.playerSprite["body"]["enable"] = false; } }; Genari.Player.prototype.getX = function(){ // Implement this on your player if(this.playerSprite) return this.playerSprite['body']['x']; }; Genari.Player.prototype.getY = function(){ // Implement this on your player if(this.playerSprite) return this.playerSprite['body']['y']; }; Genari.Player.prototype.getMidY = function(){ // Implement this on your player if(this.playerSprite) return this.playerSprite['body']["y"] + this.playerSprite['body']["height"] / 2; }; Genari.Player.prototype.getWidth = function(){ // Implement this on your player if(this.playerSprite) return this.playerSprite['body']['width']; }; /** * @param {*} [parameter] */ Genari.Player.prototype.killPlayer = function(parameter){ // implement anything to clean up if you need to destroy the player }; Genari.Player.prototype.destroy = function(){ // implement anything to clean up if you need to destroy the player }; /********************************************************************************************* * Player for horizontally scrolling running games * DO NOT EDIT. Extend if necessary * @param {Genari.Game} theGameObj The only game object * @param {number} maxLife Name of the state E.g., "play" * @param {number} entryX Name of the state E.g., "play" * @param {number} entryY Name of the state E.g., "play" * @param {string} [jumpSoundKey] Name of the state E.g., "play" * * @constructor * @extends {Genari.Player} ********************************************************************************************/ Genari.RunPlayer = function(theGameObj, maxLife, entryX, entryY, jumpSoundKey){ if( !(this instanceof Genari.RunPlayer)) return new Genari.RunPlayer(theGameObj, maxLife, entryX, entryY, jumpSoundKey); Genari.Player.call(this, theGameObj, maxLife, entryX, entryY); // must call the parent class. // Never redefine inherited properties and methods. // To override methods, must use prototype. // We define attributes that should not be redefined in subclasses. // If you redefine, it will simply replace things that are defined here. var ga = theGameObj; // Genari.RunPlayer specific this.isBlinking = false; // player is invincible mode after death this.jumpSoundKey = jumpSoundKey || Genari.k.jumpSoundKey; this.walkSpeed = ga.walkSpeed; this.jumpDistance = ga.jumpDistance; this.standStillFrameNo = -1; }; Genari.RunPlayer.prototype = Object.create(Genari.Player.prototype); // extend Genari.Player Genari.RunPlayer.prototype.constructor = Genari.RunPlayer; // set constructor property // Add methods to the prototype of the superclass /** * @deprecated use resume() **/ Genari.RunPlayer.prototype.unPause = function(){ this.resume(); }; /** * @override */ Genari.RunPlayer.prototype.resume = function(){ if(this.playerSprite){ if(this.playerSprite["animations"] && this.playerSprite["animations"]["getAnimation"]()) this.playerSprite["animations"]["paused"] = false; if(this.playerSprite["body"]) this.playerSprite["body"]["enable"] = true; } }; /** @override */ Genari.RunPlayer.prototype.pause = function(){ if(this.playerSprite){ if(this.playerSprite["animations"] && this.playerSprite["animations"]["getAnimation"]()) this.playerSprite["animations"]["paused"] = true; // A disabled body won't be checked for any form of collision or overlap or have its pre/post updates run. if(this.playerSprite["body"]) this.playerSprite["body"]["enable"] = false; } }; /** @override */ Genari.RunPlayer.prototype.getX = function(){ return this.playerSprite['body']['x']; }; /** @override */ Genari.RunPlayer.prototype.getY = function(){ return this.playerSprite['body']['y']; }; /** @override */ Genari.RunPlayer.prototype.getMidY = function(){ return this.playerSprite['body']["y"] + this.playerSprite['body']["height"] / 2; }; /** @override */ Genari.RunPlayer.prototype.getWidth = function(){ return this.playerSprite['body']['width']; }; Genari.RunPlayer.prototype.checkFall = function(){ if(this.dcGame.playerResetGroundHeight) return this.playerSprite["body"]["y"] > this.dcGame.playerResetGroundHeight - this.playerSprite["height"] + 3; else return false; }; Genari.RunPlayer.prototype.checkTouchingDown = function(){ return this.playerSprite["body"]["touching"]["down"]; }; // blink the player once. used after die Genari.RunPlayer.prototype.blink = function(){ _gitf015(this.playerSprite); }; /** * Blink the player for the given msec during which the player should be invulnerable * @param {number|undefined} [duration] */ Genari.RunPlayer.prototype.blinkFor = function(duration){ ibg_blinkFor.call(this, duration); }; Genari.RunPlayer.prototype.stopBlinking = function(){ this.playerSprite["revive"](); this.isBlinking = false; }; // Override these functions in your Player class if you need to customise movements. Do not change this file Genari.RunPlayer.prototype.standStill = function(){ this.playerSprite["body"]["velocity"]["x"] = 0; this.playerSprite["animations"]["stop"](); if(this.standStillFrameNo >= 0) this.playerSprite["frame"] = this.standStillFrameNo; }; Genari.RunPlayer.prototype.walkLeft = function(speed){ if(typeof speed == "undefined") speed = -1*this.walkSpeed; this.playerSprite["body"]["velocity"]["x"] = speed; // -1*this.walkSpeed; this.playerSprite["animations"]["play"]('left'); }; Genari.RunPlayer.prototype.walkRight = function(speed){ if(typeof speed == "undefined") speed = this.walkSpeed; this.playerSprite["body"]["velocity"]["x"] = speed; //this.walkSpeed; this.playerSprite["animations"]["play"]('right'); }; Genari.RunPlayer.prototype.walkDown = function(speed){ if(typeof speed == "undefined") speed = 0.3*250; this.playerSprite["body"]["velocity"]["y"] = speed; }; Genari.RunPlayer.prototype.walkUp = function(speed) { this.jumpUp(speed); }; Genari.RunPlayer.prototype.jumpUp = function(speed){ if(typeof speed === "undefined"){ if(this.jumpDistance){ speed = -1*this.jumpDistance; } else speed = -1*250; } this.dcGame.audioPlay(this.jumpSoundKey, undefined, undefined, 0.5); this.playerSprite["body"]["velocity"]["y"] = speed; }; /** * Create player sprite and animations * Override this if you need to customise. * * @param {string} key the name of the image asset, which must be loaded before calling this in preload. * @param {number|undefined} [gravity] Player physics property: Y gravity amount. Defult 310 * @param {number|undefined} [bounceY] Player physics property: Y bounce amount. Default 0.2 * @param {Array|undefined} [leftFrames] Frame numbers in the sprite for walking left * @param {Array|undefined} [rightFrames] Frame numbers in the sprite for walking right * @param {number|undefined} [frameRate] How fast does the player walk? Default 10 frames per second * @param {boolean|undefined} [loop] Loop the animation for walking? Default true * @param {Array|undefined} [upframes] Frame numbers in the sprite for walking upwards * @param {Array|undefined} [downframes] Frame numbers in the sprite for walking downwards * @param {boolean|undefined} [camFollowPlayer] Set to false to make the camera not to follow the player. Default true. */ Genari.RunPlayer.prototype.createPlayerAnimation = function(key, gravity, bounceY, leftFrames, rightFrames, frameRate, loop, upframes, downframes, camFollowPlayer){ ibg_createPlayerAnimation.call(this, key, gravity, bounceY, leftFrames, rightFrames, frameRate, loop, upframes, downframes, camFollowPlayer); }; /** * Reduce the life of player * @param {*} [parameter] * @override */ Genari.RunPlayer.prototype.killPlayer = function (parameter) { ibg_killPlayer.call(this, parameter); }; /** * After player dies, move the player back onto the platform * @param {number|undefined} [x] * @param {number|undefined} [y] */ Genari.RunPlayer.prototype.resetBody = function(x, y){ ibg_resetBody.call(this, x, y); }; /********************************************************************************************* * Genari.Game class. The base class of all Game applications * * Game --> phaserGame * gameDialogBox * gameControl * stateError * stateMenu * statePlay * player --> playerSprite * layer____: rendering layers * group____: groups of display object * * @param {Object} game_themes An array of themes. A theme is a dictionary. See app.js for theme data * @param {number|undefined} [game_width] Default 800 Width of the canvas * @param {number|undefined} [game_height] Default 426 Height of the canvas * * @constructor ********************************************************************************************/ Genari.Game = function(game_themes, game_width, game_height){ // Docentron Game Class if( !(this instanceof Genari.Game)) return new Genari.Game(game_themes, game_width, game_height); // make sure this refer to a Genari.Game //----------------------------------------------------- // We define common asset keys used in the game. You can override these in ibStartGameLevel() in app_class /** @deprecated use Genari.k.bannerImgKey**/ this.bannerImgKey = "bannerImg"; /** @deprecated use Genari.k.menuMusicKey**/ this.menuMusicKey = "menuMusic"; // Played when at the beginning of the game /** @deprecated use Genari.k.endMusicKey**/ this.endMusicKey = "endMusic"; // Played when game over /** @deprecated use Genari.k.dialogBoxKey**/ this.dialogBoxKey = "dialogBoxFrameImg"; // Dialog box frame // Dialog box buttons /** @deprecated use Genari.k.exitButtonSpriteKey**/ this.exitButtonSpriteKey = "exitBtn"; /** @deprecated use Genari.k.restartButtonSpriteKey**/ this.restartButtonSpriteKey = "restartBtn"; /** @deprecated use Genari.k.resumeButtonSpriteKey**/ this.resumeButtonSpriteKey = "resumeBtn"; /** @deprecated use Genari.k.retryButtonSpriteKey**/ this.retryButtonSpriteKey = "retryBtn"; // Button used for error state // HUD UI /** @deprecated use Genari.k.pauseButtonSpriteKey**/ this.pauseButtonSpriteKey = "pauseBtn"; /** @deprecated use Genari.k.leftButtonSpriteKey**/ this.leftButtonSpriteKey = "leftBtn"; // optional /** @deprecated use Genari.k.rightButtonSpriteKey**/ this.rightButtonSpriteKey = "rightBtn"; // optional /** @deprecated use Genari.k.downButtonSpriteKey**/ this.downButtonSpriteKey = "downBtn"; // optional /** @deprecated use Genari.k.rotateButtonSpriteKey**/ this.rotateButtonSpriteKey = "rotateBtn"; // optional /** @deprecated use Genari.k.jumpButtonSpriteKey**/ this.jumpButtonSpriteKey = "jumpBtn"; // optional /** @deprecated use Genari.k.shootButtonSpriteKey**/ this.shootButtonSpriteKey = "shootBtn"; // optional /** @deprecated use Genari.k.scoreReelSpriteKey**/ this.scoreReelSpriteKey = "scoreReelSprite"; // Reels of the score bar // Common theme specific assets /** @deprecated use Genari.k.backgroundImgKey**/ this.backgroundImgKey = "backgroundImg"; // optional /** @deprecated use Genari.k.lifeIconImgKey**/ this.lifeIconImgKey = "lifeIconImg"; // optional /** @deprecated use Genari.k.wordBoxFrameImgKey**/ this.wordBoxFrameImgKey = "wordBoxFrameImg";// optional /** @deprecated use Genari.k.backgroundMusicKey**/ this.backgroundMusicKey = "backgroundMusic";// Theme asset: played while playing the game /** @deprecated use Genari.k.playerSpriteKey**/ this.playerSpriteKey = "playerCharSprite"; // Player character sprite /** @deprecated use Genari.k.openingSoundKey**/ this.openingSoundKey = "openingSnd"; // optional /** @deprecated use Genari.k.jumpSoundKey**/ this.jumpSoundKey = "jumpSnd"; // optional /** @deprecated use Genari.k.bulletSoundKey**/ this.bulletSoundKey = "shootGunSnd"; // optional /** @deprecated use Genari.k.bulletSpriteKey**/ this.bulletSpriteKey = "bulletImg"; // optional /** @deprecated use Genari.k.fallDownSndKey**/ this.fallDownSndKey = "fallDownSnd"; // optional /** @deprecated use Genari.k.explosionSndKey**/ this.explosionSndKey = "explosionSnd"; // optional /** @deprecated use Genari.k.explosionSpriteKey**/ this.explosionSpriteKey = "explosionSprite";// optional /** @deprecated use Genari.k.correctSndKey**/ this.correctSndKey = "correctSnd"; // optional /** @deprecated use Genari.k.incorrectSndKey**/ this.incorrectSndKey = "incorrectSnd"; // optional /** @deprecated use Genari.k.collectSndKey**/ this.collectSndKey = "collectSnd"; /** @deprecated use Genari.k.fightingSndKey**/ this.fightingSndKey = "fightingSnd"; // optional /** @deprecated use Genari.k.carPhysicsDataKey**/ this.carPhysicsDataKey = "sprite_physics"; // optional /** @deprecated use Genari.k.carObjNameInPhysicsData**/ this.carObjNameInPhysicsData = "car"; // optional // Tilemap can have layers. These are default layers. When creating tilemaps, use these names /** @deprecated use Genari.k.tileMapBackgroundLayerName**/ this.tileMapBackgroundLayerName = "BackgroundLayer"; /** @deprecated use Genari.k.tileMapCollisionLayerName**/ this.tileMapCollisonLayerName = "CollisionLayer"; /** @const * @deprecated Use Genari.k.userPhotoKey **/ this.userPhotoKey = "userIcon"; // Builtin asset for user photo /** @const * @deprecated Use Genari.k.userPhotoFrameKey **/ this.userPhotoFrameKey = "userIconFrame"; // User's profile photo frame image is loaded using this key this.game_width = game_width || 800; // ** if you change, make sure the screen ratio should remain the same this.game_height = game_height || 426; // Settings for HUD items. This works for Landscope mode games this.life_icon_x = 55; this.life_text_x = 127; this.score_text_x = this.game_width - 40; /** @deprecated Use this.game_width */ this.gc_game_width = game_width; /** @deprecated Use this.game_height */ this.gc_game_height = game_height; /** @type {Function} Genari.Control * @private **/ this.ControlClass = null; // Optional common parameters for platform running games this.jumpDistance = 300; // player jump distance this.walkSpeed = 150; // player walk speed this.playerWeight = 80; // used by CarPlayer this.playerGravity = 10; // used by CarPlayer this.playerResetGroundHeight = 100; // reset player Y position to this when it dies this.playerResetXPosition = undefined; // The amount the player will move back when die. this.playerFlyingTime = 3000; // ms this.playerFallLine = this.game_height - 100; // player dies if fall below this line // Initialize API Genari.dcGame = this; // update the scale ratio //console.log("Genari.Game", game_themes); this.screenScaleRatio = _gitf040(this, game_themes, game_width, game_height); // Constants /** @const */ this.BUTTON_EDGE_MARGIN = 10; /** @const */ this.gc_building_height = 60; // crate height /** @private */ this.screenScaleRatio = 1; // this is automatically calculated // Game states this.levelScore = 0; this.currentGameLevel = 0; this.totalGameScore = 0; this.totalWordNo = 0; // the total number of answers for the current level this.wordNo = 0; // idx of the answer to show next // Loaded/created assets this.phaserGame = null; // Phaser.Game. the Phaser instance this.isPaused = false; // true if game is paused this.enterKey = null; // Phaser "ENTER" keyboard key this.spaceBarKey = null; // Phaser "SPACEBAR" keyboard key this.cursorKeys = null; // Phaser cusorkey this.gameDialogBox = null; this.audioAssets = {}; // a list of audio assets ready to play for the game state. /** @deprecated */ this.phaserGroups = {}; this.scoreBox = null; this.gameThemes = game_themes; // game themes this.lifeText = null; this.currentStroke = 0; // used by stroke game /** @type {Genari.Control} */ this.gameControl = null; /** @type {Genari.Player} */ this.player = null; /** @type {Genari.GameState} */ this.statePlay = null; // level play state /** @type {Genari.GameState} */ this.stateError = null; // show error message /** @type {Genari.GameState} */ this.stateMainMenu = null; // show main menu this.recreateDialogBox = false; // set this to true to recreate dialog boxes for game over and pause events. // this forces the dialog box to appear on the top. this.isShowLevelOpeningDialog = true; // if set to true show a dialog box when start a new level this.isShowLevelCompleteDialog = true; // if set to true show a dialog box when a level is completed // Layers. Use layers to control z-order this.layerBottom = null; // holds background, platforms this.layerPlayer = null; // holds players, player interactive items this.layerEffects = null; // holds explosions, bullets, effects this.layerButtons = null; // holds control buttons, frames, windows, HUD items this.layerDialog = null; // holds dialog boxes. Top layer // Learning statistics this.correctWordsCollected = []; // add correct words collected here this.incorrectWordsDestroyed = []; // add incorrect words collected here this.correctWordsDestroyed = []; this.incorrectWordsCollected = []; this.learningData = []; this.mouseClickDelay = 200; // msec. Used in resume to delay resuming after user clicks and delayed call this.who = "Game"; // Built in groups this.groupBullets = null; // Exports symbols to external libraries this["_sn"] = this.startNew; this["_rs"] = this.rescaleGame; this["_cg"] = this.resume; this["_p"] = this.phaserGame; this["_gdb"] = this.gameDialogBox; }; // You can override these methods in subclasses, but make sure to call superclass methods like this: // Genari.Game.prototype.methodName.call(this, ....); Genari.Game.prototype = { /** * Create Phaser and initialize for this game * You can override this to customise Phaser initialization, but must set ["_p"] and scale mode properly * * @public * * @param {string | HTMLElement} gameContainer Parent * @param {Function} preloadFn * @param {Function} createFn * @param {string} renderMethod Default "AUTO" * @param {string} gamePhysics Default "ARCADE" */ createPhaser: function(gameContainer, preloadFn, createFn, renderMethod, gamePhysics){ ibg_createPhaser.call(this, gameContainer, preloadFn, createFn, renderMethod, gamePhysics); }, /** * Return true if minscore is achieved * @protected */ checkMinScore: function (){ return Genari.checkMinScore(this.levelScore); }, setToBaseScaleMode: function(){ _gitf023(this.game_width, this.game_height); }, setToScaledMode: function(){ _gitf024(this.game_width*this.screenScaleRatio, this.game_height*this.screenScaleRatio); }, /** * Add audio asset to the game and store it in an array for easy access. * @param audioAssets */ addAudios: function (audioAssets) { audioAssets.forEach(function(key) { this.audioAssets[key[0]] = Genari.phaserAddAudio(key[1]); }.bind(this)); }, /** * Create audio assets from the asset list * @param assetList */ addAudioFromList: function(assetList){ Genari.addAudioFromList(assetList); }, /** * Add all theme audio assets of the current level */ addThemeAudio: function(){ this.addAudioFromList(Genari.getTheme()["audio"]); }, /** * Add all answer audio assets for the current level. * These are audio files added by game level authors, not the theme audio files. * Loaded audio assets are added to Genari.dcGame.audioAssets with their keys * @param {number} [qNo] question number. Leave this blank for non-card games */ addLevelAudio: function(qNo){ _gitf089(Genari.dcGame.audioAssets, qNo); }, /** * Add audio assets for a card game * These are audio files added by game level authors, not the theme audio files. * Loaded audio assets are added to Genari.dcGame.audioAssets with their keys * @param {number} qNo question number. Default 0. */ addQuestionAudio: function(qNo){ _gitf089b(Genari.dcGame.audioAssets, qNo); }, /** * Play an audio asset from the asset list * @param key * @param {number|undefined} [marker] * @param {number|undefined} [position] * @param {number|undefined} [volume] * @param {boolean|undefined} [loop] * @param {boolean|undefined} [forceRestart] * @param {boolean|undefined} [stopIfPlaying] Default true * @param {Function|undefined} [onCompleteCallBack] if given, this will be called when the sound play is completed. */ audioPlay: function(key, marker, position, volume, loop, forceRestart, stopIfPlaying, onCompleteCallBack){ stopIfPlaying = stopIfPlaying || true; //console.log(key, this.audioAssets[key]); if(key && this.audioAssets[key]){ if(this.audioAssets[key]["isPlaying"] && stopIfPlaying) this.audioAssets[key]["stop"](); this.audioAssets[key]["play"](marker, position, volume, loop, forceRestart); // Register callback if set if(onCompleteCallBack) this.audioAssets[key]["onStop"]["addOnce"](onCompleteCallBack); } }, /** * * @param answer * @param {string} alternativeSndKey This will be played if the answer sound is not found * @param {number|undefined} [volume] * @param {boolean|undefined} [forceRestart] * @param {boolean|undefined} [stopIfPlaying] Default true * @param {Function|undefined} [onCompleteCallBack] if given, this will be called when the sound play is completed. */ audioPlayAnswerSnd: function(answer, alternativeSndKey, volume, forceRestart, stopIfPlaying, onCompleteCallBack){ if(answer["soundKey"] && answer["soundKey"] !== "sk_0"){ this.audioPlay(answer["soundKey"], undefined, undefined, volume, undefined, forceRestart, stopIfPlaying, onCompleteCallBack); }else{ this.audioPlay(alternativeSndKey, undefined, undefined, 0.5, undefined, forceRestart, stopIfPlaying, onCompleteCallBack); } }, /** * Play an audio asset from the asset list if it is not already playing * @param key * @param [marker] * @param [position] * @param [volume] * @param [loop] * @param [forceRestart] */ audioPlayIfNotPlaying: function(key, marker, position, volume, loop, forceRestart){ //console.log("audioPlay", key, this.audioAssets[key], this.audioAssets); if(key && this.audioAssets[key] && !this.audioAssets[key]["isPlaying"]){ this.audioAssets[key]["play"](marker, position, volume, loop, forceRestart); } }, audioIsPaused: function(key){ if(this.audioAssets[key]){ return this.audioAssets[key]["paused"]; }else return false; }, audioIsPlaying: function(key){ if(this.audioAssets[key]){ return this.audioAssets[key]["isPlaying"]; }else return false; }, /** * Play an audio asset from the asset list * @param key * @param {number|undefined} [volume] */ audioPlayLoopFull: function(key, volume){ //console.log("audioPlayLoopFull", key); if(key && this.audioAssets[key] && !this.audioAssets[key]["isPlaying"]){ this.audioAssets[key]["loopFull"](volume); } }, /** * Stop audio * @param key */ audioStop: function(key){ if(key && this.audioAssets[key] && this.audioAssets[key]["stop"]){ this.audioAssets[key]["stop"](); } }, /** * Pause audio * @param key */ audioPause: function(key){ if(key && this.audioAssets[key] && this.audioAssets[key]["pause"]){ this.audioAssets[key]["pause"](); } }, /** * Resume audio * @param key */ audioResume: function(key){ if(key && this.audioAssets[key] && this.audioAssets[key]["resume"]){ this.audioAssets[key]["resume"](); } }, // Add text to the stage addText: function (variable, x, y, text, property, camera, visible, parent) { ibg_addText(variable, x, y, text, property, camera, visible, parent); }, // Add level info text to the stage addLevelText: function (y, text, style, x_offset) { x_offset = x_offset || 0; return _gitf032(this.game_width + x_offset, y, text, style); }, /** * Create a Phaser group (a display object) and add it to this.phaserGroups array using the arrayKey. * Use this to create and manage phaser groups. A phaser group is a display object which can contain other display objects * @deprecated use Genari.Group classes to manage groups * @param {string} arrayKey index key for this.phaserGroups * @param {boolean} enableBody Set to true to enable physics * @returns {Object} Phaser.Group object */ phaserAddGroup: function (arrayKey, enableBody) { return _gitf001(this.phaserGroups, arrayKey, enableBody); }, // Rescale the entire game when window is re-sized. ** call this AFTER adding/creating all assets. Not before rescaleGame: function (){ ibg_rescaleGame.call(this); }, /** * @deprecated Use resume() */ continueGame: function(){ this.resume(); }, resumePhysics: function(){ ibg_resumePhysics(); }, //----------------------------------------------------------- // resume paused game /** * Resume the game * @returns {boolean} Return true if resumed */ resume: function () { return ibg_game_resume.call(this); }, // Create game dialog box to show level openings, scores, etc addGameDialogBox: function (dialogBoxFrameSpriteKey){ ibg_addGameDialogBox.call(this, dialogBoxFrameSpriteKey); }, /** * Set game dialog box content with the given title, message, score, or menu options and show the box * * @param {string} titleMsg * @param {string} bodyText * @param {number} levelScore * @param {number} totalScore * @param {string|undefined} [instructionMsg] * @param {Object|undefined} [titleStyle] text style E.g., {font:'40px Arial', fill:'#ffffff'} * @param {Object|undefined} [msgStyle] * @param {Object|undefined} [scoreStyle] * @param {Object|undefined} [totalScoreStyle] * @param {Object|undefined} [instructionStyle] * @param {number|undefined} [titleYOffset] Default -100 * @param {number|undefined} [strokeColor] * @param {string|undefined} [imgKey] * @param {boolean|undefined} [isLevelComplete] Set to true if this is level end dialog box */ setGameDialogBoxContentAndShow: function ( titleMsg, bodyText, levelScore, totalScore, instructionMsg, titleStyle, msgStyle, scoreStyle, totalScoreStyle, instructionStyle, titleYOffset, strokeColor, imgKey, isLevelComplete ) { _gitf005(this.gameDialogBox, titleMsg, bodyText, levelScore, totalScore, instructionMsg, this, titleStyle, msgStyle, scoreStyle, totalScoreStyle, instructionStyle, titleYOffset, strokeColor, imgKey, isLevelComplete ); }, /** * Add Phaser.Button * @param x * @param y * @param key * @param {Function|undefined} [action] callback when the button is pressed. * @param {number|undefined} [btnWidth] * @param {number|undefined} [btnHeight] * @returns {Object} */ addButton: function (x, y, key, action, btnWidth, btnHeight) { return Genari.phaserAddButton(x, y ,key, action, this, 1, 1, 1, 1, btnWidth, btnHeight); // 1, 1, 0, 1 }, /** * Add a button to the game dialog box * @param x * @param y * @param key * @param offsetX * @param btnAction * @param listenerContext * @param {number|undefined} [btnWidth] * @param {number|undefined} [btnHeight] * @returns {Object} Phaser.Button */ addButtonToDialogBox: function (x, y, key, offsetX, btnAction, listenerContext, btnWidth, btnHeight){ return _gitf006(x, y, key, offsetX, this.addButton, //dcGAPI.calcBoxCenterX, this.gameDialogBox, this.gameControl.createHitArea, btnAction, this.statePlay.pauseMenuButtons, listenerContext, this, this.gameControl ); }, /** * When the user click or press the Enter key, remove the game dialog box and call action() * @param {Function} action The event handler * @param {Object} listenerContext Set this so we can use this in the event handler * @param {boolean} [addClick] Set to true to add click handler as well */ addOnceDialogAction: function(action, listenerContext, addClick){ _gitf007(this.enterKey, addClick, action, listenerContext); }, /** * When the user click or press the Enter key, remove the game dialog box and call action() * @param {Function} action The event handler * @param {Object} listenerContext Set this so we can use this in the event handler * @param {boolean} [addClick] Set to true to add click handler as well */ addDialogAction: function(action, listenerContext, addClick){ _gitf007a(this.enterKey, addClick, action, listenerContext); }, /** * Do not call this directly. Game flow controls * This function is called when a game level data is received automatically. * Callback function signature. DO NOT CHANGE * @param isError * @param hasLevelData * @param message */ startGameLevel: function (isError, hasLevelData, message) { // ** callback function signature. DO NOT CHANGE ibg_startGameLevel.call(this, isError, hasLevelData, message); }, /** * Hide game dialog box */ removeGameDialogBox: function (){ _gitf008(this.gameDialogBox, this.statePlay.pauseMenuButtons); this.statePlay.pauseMenuButtons = []; }, /** * Start a new game. Show the splash screen * start stateMainMenu state * Do not override this. Add additional initialization to stateMainMeu.create() * @final */ startNew: function () { ibg_startNew.call(this); }, /** * Save game and start a new */ gameOver: function(){ this.saveAndStartNextLevel(true); }, /** * Call this to save the game score and go to the next game level. * If there is no more game data, it will end the game. * If you need, you can override this in a subclass. * @param {boolean|undefined} [gameOver] Set to true if game over. Default false. * @param {boolean|undefined} [playEndMusic] Default true */ saveAndStartNextLevel: function (gameOver, playEndMusic){ ibg_saveAndStartNextLevel.call(this, gameOver, playEndMusic); }, // ** DO NOT call this directly. // ** DO NOT change the signature of this function // This is called by ibcgl() // This function is called when we receive the next level game data from the server // We show level-complete dialog box based on the availability of the game data. // If you need, you can override in a subclass. gameLevelComplete: function (isError, hasLevelData, score, totalScore, message, gameOver) { ibg_gameLevelComplete.call(this, isError, hasLevelData, score, totalScore, message, gameOver); }, /** * Show the dialog box when the player completed the level * Override this to customise the dialog box appearance * @param bodyText * @param score * @param totalScore * @param actionMsg * @param buttonClickHandler * @param title */ showLevelCompleteDialogBox: function(bodyText, score, totalScore, actionMsg, buttonClickHandler, title){ title = title || "Congratulations!"; this.setGameDialogBoxContentAndShow( title, bodyText, score, totalScore, actionMsg, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, true ); this.addOnceDialogAction(buttonClickHandler, this); }, /** * Loads the game data and starts the game * Calls startGameLevel after the game data is loaded * This is called when the user click start in the game banner screen */ startGame: function(){ ibgcgl(this.startGameLevel.bind(this), this.currentGameLevel); }, // Restart just the current game level. // Call this if user requests to retry. // If you need to change, make sure to call this function from your own function. restartLevel: function (){ this.statePlay.isLevelCleared = false; // we haven't finished the current level yet. this.statePlay.isPlaying = false; // prevent update calls this.levelScore = 0; this.isPaused = false; this.resumePhysics(); // Now start Play state this.statePlay.start(true); // set true to re-create the game }, // Use this to recreate the dialog box during the game play to make it appear on the top createDialogBox: function(){ this.setToBaseScaleMode(); this.addGameDialogBox(Genari.k.dialogBoxKey); this.setToScaledMode(); }, /** * Show the loading progress. Call this in preload() of state * @param loadingMsg * @return {Object} Phaser text object. */ showLoading: function(loadingMsg){ return _gitf038(this.game_width, this.game_height, loadingMsg); }, // Hide loading message. Call this in create after loading and creating assets hideLoading: function(){ _gitf039(); }, addTextToGameDialogBox: function(message, fontSize, fontName, fillColor, offsetY) { ibg_addTextToGameDialogBox.call(this, message, fontSize, fontName, fillColor, offsetY); }, /** * Updates this.levelScore value * If this.scoreBox is set, scoreBox.gainScore will be called to display the score. * If score is an object, score.answer["score"] will be checked for score value. * @param {Object|number} score sprite with answer or score value */ updateScore: function(score){ ibg_updateScore.call(this, score); }, /** * Return true if the player reaced the end of the game level. * @returns {boolean} */ checkReachedEnd: function() { return false; } }; Genari.Game.prototype.constructor = Genari.Game; // set constructor property /** * @deprecated Use pause() */ Genari.Game.prototype.pauseGame = function () { this.pause(); }; /** * Show the pause dialog box * @param {boolean|undefined} [recreateDialogBox] Default false */ Genari.Game.prototype.showPauseDialogBox = function(recreateDialogBox){ ibg_showPauseDialogBox.call(this, recreateDialogBox); }; /** * When the pause button is pressed, we pause the game by disabling components. * Also display the pause dialog box * @param {Object|null|undefined} [button] The button or sprite pressed for pause * @param {Object|null|undefined} [pointer] Phaser.Pointer that activated the button or sprite * @param {boolean|null|undefined} [showPauseDialogBox] Default true. Show the the pause dialogbox * @returns {boolean} Whether the game is playing or not. */ Genari.Game.prototype.pause = function (button, pointer, showPauseDialogBox) { return ibg_game_pause.call(this, button, pointer, showPauseDialogBox); }; Genari.Game.prototype["_pg"] = Genari.Game.prototype.pause; /*********************************************************************************** * Generic Board Game. Extend and customise this for typical board games such as Omok, Othello, Chess games * * @param {Object} game_themes An array of themes. A theme is a dictionary. See app.js for theme data * @param {number} game_width Width of the canvas * @param {number} game_height Height of the canvas * * @constructor * @extends {Genari.Game} ***********************************************************************************/ var BoardGame = function(game_themes, game_width, game_height){ if( !(this instanceof BoardGame)) return new BoardGame(game_themes, game_width, game_height); Genari.Game.call(this, game_themes, game_width, game_height); // call the parent constructor this.board = null; // This refers to the board of the game, created when the game starts. this.computerScore = 0; this.animationFPS = 10; // Animation frame per second //this.mouseClickDuration = 200; // Number of milliseconds to wait before resume after clicking dialog box. /** @type {Genari.Hud} */ this.hud = null; this.who = "BoardGame"; }; BoardGame.prototype = Object.create(Genari.Game.prototype); // extend DBGame BoardGame.prototype.constructor = BoardGame; // set constructor property /** * Overriding the superclass method createPhaser * @override **/ BoardGame.prototype.createPhaser = function(gameContainer, preloadFn, createFn, renderMethod, gamePhysics) { // ** Make sure to call the parent Genari.Game.prototype.createPhaser.call(this, gameContainer, preloadFn, createFn, renderMethod, gamePhysics); // Your own stuff here }; /** * Overriding the superclass method restartLevel * @override * */ BoardGame.prototype.restartLevel = function(){ // ** Make sure to call the parent Genari.Game.prototype.restartLevel.call(this); // Your own stuff here }; /** * This is how to check the end of the game level for the game */ BoardGame.prototype.checkLevelEnd = function (){ // full or no more moves? //var whoWon = this.checkReachedEnd(); //console.log("BoardGame.prototype.checkLevelEnd", this.who, whoWon); if (this.board.checkReachedEnd()) { // if human player won, go to the next level if (this.board.isHumanPlayerWinning()){ this.board.stopAnimation(); // completed the level. Save game and Go to next level this.saveAndStartNextLevel(false); } else { this.gameOver(); } // reset computer score. Human score will be recorded first and reset //this.computerScore = 0; } }; /** * Set board * * @param board */ BoardGame.prototype.setBoard = function (board) { this.board = board; }; /** * Get board */ BoardGame.prototype.getBoard = function () { return this.board; }; /** * This is the function to pause the game * @param {Object|null|undefined} [button] The button or sprite pressed for pause * @param {Object|null|undefined} [pointer] Phaser.Pointer that activated the button or sprite * @param {boolean|null|undefined} [showPauseDialogBox] Default true. Show the the pause dialogbox * @returns {boolean} Whether the game is playing or not. * @override */ BoardGame.prototype.pause = function(button, pointer, showPauseDialogBox){ if(Genari.Game.prototype.pause.call(this, button, pointer, showPauseDialogBox)){ if(this.board) this.board.pauseSoldiers(); return true; }else return false; /* this.isPaused = true; if(!this.statePlay || !this.statePlay.isPlaying) return false; // game level is not playing yet if(this.board) this.board.pauseSoldiers(); this.audioPause(this.backgroundMusicKey); this.gameControl.hideOnScreenButtons(); console.log("BoardGame.Game.prototype.pause " + showPauseDialogBox); // DEVELOPER_CODE if (showPauseDialogBox) { this.showPauseDialogBox(); } return true; */ }; /* BoardGame.prototype.pauseDialogBox = function() { // if you need to recreate the dialog box to appear on the top, uncomment this //this.createDialogBox(); this.setGameDialogBoxContentAndShow("Game Paused", "", -1, 0, "Click or press Enter to resume"); // Buttons var bx = (this.gameDialogBox["width"] / 2); var by = (this.gameDialogBox["height"] / 3); // + this.board.numCols); this.addButtonToDialogBox(bx, by, this.exitButtonSpriteKey, -115, this.startNew, this); this.addButtonToDialogBox(bx, by, this.restartButtonSpriteKey, 0, this.restartLevel, this); this.addButtonToDialogBox(bx, by, this.resumeButtonSpriteKey, 118, function() { this.phaserGame["time"]["events"]["add"](this.mouseClickDuration, function() { this.resume(); }.bind(this)); }, this); this.addOnceDialogAction(function() { this.phaserGame["time"]["events"]["add"](this.mouseClickDuration, function() { this.resume(); }.bind(this)); }, this, false); };*/ /** * Resume game * @returns {boolean} Whether the game exists or not. * @override */ BoardGame.prototype.resume = function(){ if(this.board) this.board.resumeSoldiers(); return Genari.Game.prototype.resume.call(this); /* this.removeGameDialogBox(); if(this.phaserGame){ if(this.audioAssets[this.backgroundMusicKey]&& this.audioAssets[this.backgroundMusicKey]["paused"]) { try { this.audioResume(this.backgroundMusicKey); } catch (Exception) { console.log("Error resuming audio.", Exception); } } if(this.gameControl) this.gameControl.showOnScreenButtons(); this.isPaused = false; this.audioResume(this.backgroundMusicKey); return true; } else { this.isPaused = false; this.audioResume(this.backgroundMusicKey); this.resumePhysics(); return false; } */ }; /********************************************************************************************* * IoT controller to control a remote IoT nodes * * @constructor ********************************************************************************************/ Genari.IoTController = function(){ if( !(this instanceof Genari.IoTController)) return new Genari.IoTController(); // Never redefine inherited properties and methods. // To override methods, must use prototype. // We define attributes that should not be redefined in subclasses. // If you redefine, it will simply replace things that are defined here. this.dataInfo = {"temp":{"unit":"C"}, "humidity": {"unit":"%"}, "pressure": {"unit":"hPa"}, "input":{"unit":"Bits"}}; this.deviceInfo = {"sno":"123456", "name":"deviceName", "time":"20:02:12", "type":"sensor-node", "model":"DCLoRa10"}; this.data = {"temp":12, "humidity": 80, "pressure": 120, "input":0x0001}; this.configParas = { "interval":600, // seconds. IoT end node sends data at this interval "output":0x00, // 16bit. output port value "data":0x00 // 16bit. output port value }; this.configParasInfo = { "interval":{"unit":"seconds", "desc": "IoT end node sends data at this interval"}, "output":{"unit":"Hexadecimal 16 bit", "desc": "Output port value"} }; }; Genari.IoTController.prototype.constructor = Genari.IoTController; // set constructor property /** * Connect to a remote IoT device. It returns device info if successful. * @param {string} serialNo * @returns {Object|undefined} device information or undefined */ Genari.IoTController.prototype.connect = function(serialNo){ // check if the device is connected to the server // return the device info if connected if(serialNo === this.deviceInfo["sno"]) return this.deviceInfo; else return undefined; }; /** * Disconnect with the remote IoT device */ Genari.IoTController.prototype.disconnect = function(){ }; /** * Get the latest data value * @param {string} name Field name the data. Use getDataInfo() to get the list of fields available. * @returns {Object|undefined} Data value with unit, date, and time information */ Genari.IoTController.prototype.getData = function(name){ if(typeof this.data[name] !== "undefined") return {"value": this.data[name], "unit":this.dataInfo[name]["unit"], "date":"2020:02:14", "time":"09:11:24"}; else return undefined; }; /** * Get the list of data names and units. E.g., temp, humidity, and pressure. * @returns {Object|undefined} {"fieldName":{"unit":"unitName}, ....} */ Genari.IoTController.prototype.getDataInfo = function(){ return this.dataInfo; }; /** * Get the current device configuration parameters * @returns {Object} Data with type and name information */ Genari.IoTController.prototype.getConfigParams = function(){ return this.configParas; }; /** * Set device parameter * @param {string} name * @param {string|number} value */ Genari.IoTController.prototype.setParameter = function(name, value){ }; /** * Load API classes when the game data is loaded. This must be called before creating the game. * @param {Function} [myClassLoader] If provided, this is called to load the classes of your game. Use this to initialize classes the classes extend classes defined here. */ Genari.loadClasses = function(myClassLoader){ // DEVELOPER_CODE REMOVE_FOR_THEME /********************************************************************************************* * Represent a statement with score. * * @constructor ********************************************************************************************/ Genari.Statement = function(){ if( !(this instanceof Genari.Statement)) return new Genari.Statement(); this.word = ""; this.score = 0; this.statement = null; }; Genari.Statement.prototype.constructor = Genari.Statement; /** * Non-replacement sampling of statements. If all statements are retrieved, it starts from thebeginningg again. * @param reset Set to true to start from the beginning. */ Genari.Statement.prototype.loadRandomStatement = function(reset){ this.statement = Genari.getRandomStatement(reset); if(this.statement){ this.word = this.statement["word"]; this.score = this.statement["score"]; } }; /********************************************************************************************* * Use this to manage a group of display objects in the game: monsters, platforms, bullets * Extend this to customise for your game. * * @param {Object} layer Phaser.Group. Rendering layer of this group. * @param {boolean|undefined} [fixedToCamera] Default false. If set to true, it move with camera. The location is then camera offsets. * @param {boolean|undefined} [enableBody] Default true. If set to true, any objects added will have physics enables * @param {number|undefined} [physicsBodyType] Default Phaser.Physics.ARCADE. Alternatives are Phaser.Physics.P2, Phaser.Physics.NINJA * @constructor * @extends {DCGroup} ********************************************************************************************/ Genari.Group = function(layer, fixedToCamera, enableBody, physicsBodyType){ if( !(this instanceof Genari.Group)) return new Genari.Group(layer, fixedToCamera, enableBody, physicsBodyType); // make sure this refer to a Genari.Game DCGroup.call(this, layer, fixedToCamera, enableBody, physicsBodyType); }; Genari.Group.prototype = Object.create(DCGroup.prototype); // extend Genari.Group Genari.Group.prototype.constructor = Genari.Group; /** * Return the number of display objects added to this group * @returns {number} * @override */ Genari.Group.prototype.length = function(){ return DCGroup.prototype.length.call(this); }; /** * Return the Phaser Group of this group that holds all display objects added to this group. * @returns {Object} Phaser.Group. This group contains Phaser.Sprite {DisplayObject} * // we can iterate through group members * myGroup.getGroup().forEach(sprite){ * console.log(sprite.x, sprite.y); * }; * myGroup.length(); // the size of the group * @override */ Genari.Group.prototype.getGroup = function(){ return DCGroup.prototype.getGroup.call(this); }; /** * Checks for collision and separate objects if collide * @param {Object|Array} object The object that this group collide with. Can be Phaser.Sprite, Phaser.Group or Phaser.Particles.Emitter. * @param {Function} [overlapCallback] overlapCallback(an object in this group, object it collides with) * @param {Function} [processCallback] * @param {Object} [callbackContext] * @override */ Genari.Group.prototype.checkCollision = function(object, overlapCallback, processCallback, callbackContext){ return DCGroup.prototype.checkCollision.call(this, object, overlapCallback, processCallback, callbackContext); }; /** * Add Physics collision to sprite * @param {Object|Array} object object or array of objects to check. Can be Phaser.Sprite, Phaser.Group or Phaser.Particles.Emitter. * @param {Function|undefined} [overlapCallback] * @param {Function|undefined} [processCallback] * @param {Object|undefined} [callbackContext] * @return {boolean} True if collision is detected. * @override */ Genari.Group.prototype.checkOverlap = function(object, overlapCallback, processCallback, callbackContext){ return DCGroup.prototype.checkOverlap.call(this, object, overlapCallback, processCallback, callbackContext); }; /** * Add a Phaser display object as a child of the Phaser group, so they will move together * @param {Object} child Phaser display object * @override */ Genari.Group.prototype.addChild = function(child){ DCGroup.prototype.addChild.call(this, child); }; /** * Add a Phaser image object and add as a child of this group. * @param {number} x * @param {number} y * @param {string} imageKey * @override */ Genari.Group.prototype.addImage = function(x, y, imageKey){ return DCGroup.prototype.addImage.call(this, x, y, imageKey); }; /** * Add a Phaser sprite object and add as a child of this group. * @param {number} x * @param {number} y * @param {string} key Asset key * @param {string|number} frame The initial frame to show * @return {Object} Phaser.Sprite * @override */ Genari.Group.prototype.addSprite = function(x, y, key, frame){ return DCGroup.prototype.addSprite.call(this, x, y, key, frame); }; /** * Add a Phaser sprite object using an image asset loaded as a child object of this group. * @param {number} x * @param {number} y * @param {string} key The image asset key that is already loaded * @param {string|number} frame The initial frame to show * @param {number} [numOfFrames] The number of frames. Default 1 * @param {number} [frameWidth] The width of frames. Default is imageWidth/numOfFrames * @param {number} [frameHeight] Not used * @return {Object} Phaser.Sprite * @override */ Genari.Group.prototype.addImageAsSprite = function(x, y, key, frame, numOfFrames, frameWidth, frameHeight){ return DCGroup.prototype.addImageAsSprite.call(this, x, y, key, frame, numOfFrames, frameWidth, frameHeight); }; /** * Add a Phaser sprite object using an image asset loaded as a child object of this group. * This also create an animation using all the frames of the sprite and play it. * To stop the animation, call sprite.animations.stop() after the sprite is created. * * Use this to add answer/hint images as a sprite animation. It uses all the frames to animate at the given frame rate. * The width of the frame will be set to the width of the image divided by the number of frames. * The height of the frame will be set to the height of the image. * @param {number} x * @param {number} y * @param {string} key The image asset key that is already loaded * @param {string|number} frame The initial frame to show * @param {number|undefined} [numOfFrames] The number of frames. Default 1 * @param {string|undefined} [animationName] Name the animation * @param {number|undefined} [frameRate] Default 10. Higher number means it will play faster. * @param {boolean|undefined} [loopEn] Enable or disable looping. Default is true * @param {Function|undefined} [onComplete] Called when the animation play is completed * @return {Object} Phaser.Sprite */ Genari.Group.prototype.addImageAsSpriteAnimation = function(x,y, key, frame, numOfFrames, animationName, frameRate, loopEn, onComplete){ return DCGroup.prototype.addImageAsSpriteAnimation.call(this,x,y, key, frame, numOfFrames, animationName, frameRate, loopEn, onComplete); }; /** * Add a text display object to this group * @param {number} x * @param {number} y * @param {string} text * @param {string} style * @override */ Genari.Group.prototype.addTextBox = function(x, y, text, style){ return DCGroup.prototype.addTextBox.call(this, x, y, text, style); }; /** * Add a control button * The buttons are added to Genari.dcGame.gameControl.controlButtons[] array to update them automatically when resized. * * @param {number} x * @param {number} y * @param {string} key The asset name that is already loaded * @param {Function} downAction method of an object will be called when clicked * @param {Function} upAction method of an object will be called when button is up * @param {Object} listenerContext the object to which the methods are attached to. * @param {number|undefined} [alpha] alpha of the button. 1 = opaque, 0 = completely transparent (invisible) * @param {boolean|undefined} [fixedToCamera] Set to false to allow it move with camera * @param {number|undefined} [btnWidth] Optional. Set this value to change the width of the button * @param {number|undefined} [btnHeight] Optional. Set this value to change the height of the button * @return {Object} Phaser button **/ Genari.Group.prototype.addControlButton = function(x, y, key, downAction, upAction, listenerContext, alpha, fixedToCamera, btnWidth, btnHeight) { return DCGroup.prototype.addControlButton.call(this, x, y, key, downAction, upAction, listenerContext, alpha, fixedToCamera, btnWidth, btnHeight); }; /** * Set tileMap to be use with this group. All tileMap related operations will performed with this tileMap * @param tileMap * @override */ Genari.Group.prototype.setTileMap = function(tileMap){ DCGroup.prototype.setTileMap.call(this, tileMap); }; /** * Pause animation of all objects in this group * @override */ Genari.Group.prototype.pause = function(){ DCGroup.prototype.pause.call(this); }; /** * Resume animation of all objects in this group * @override */ Genari.Group.prototype.resume = function(){ DCGroup.prototype.resume.call(this); }; /** * Add a sprite to the group * @param {number} x * @param {number} y * @param {string} key * @param {number|undefined} [frame] * @return {Object} Phaser.DisplayObject (Phaser.Sprite) * @override */ Genari.Group.prototype.create = function(x, y, key, frame){ return DCGroup.prototype.create.call(this, x, y, key, frame); }; /** * Set property of all display objects in this group * @param {string} propertyName * @param {string|number} value * @override */ Genari.Group.prototype.setAll = function(propertyName, value){ DCGroup.prototype.setAll.call(this, propertyName, value); }; /** * Create group items from tilemap * We can import sprites and location information from tileemap into a Phaser Group. * See http://phaser.io/docs/2.4.4/Phaser.Tilemap.html#createFromObjects * * @param {Object} tileMap Phaser.Tilemap * @param {string} name The object layer name in Tiled. * @param {number|string} gid Object name in the object layer in Tiled * @param {string} key The loaded tileset image asset key. This must be loaded previously. * @param {number | string} [frame] If the sprite image contains multiple frames you can specify which one to use here. * @param {boolean} [exists] Default true. The default exists state of the Sprite. * @param {boolean} [autoCull] Default false. The default autoCull state of the Sprite. Sprites that are autoCulled are culled from the camera if out of its range. * @param {Object} [CustomClass] Phaser.Sprite. If you wish to create your own class, rather than Phaser.Sprite, pass the class here. Your class must extend Phaser.Sprite and have the same constructor parameters. * @param {boolean} [adjustY] true By default the Tiled map editor uses a bottom-left coordinate system. Phaser uses top-left. So most objects will appear too low down. This parameter moves them up by their height. * @override */ Genari.Group.prototype.createFromObjects = function(tileMap, name, gid, key, frame, exists, autoCull, CustomClass, adjustY){ DCGroup.prototype.createFromObjects.call(this, tileMap, name, gid, key, frame, exists, autoCull, CustomClass, adjustY); }; /** * Import objects from an object layer in a TileMap. We can use this as locations of objects that need to created * The returned Phaser.Group can be iterated using forEach() and get location information "x", "y" and * other attributes you have defined in the tileMap. * * // Usage example: * var importedObjs = this.createRefObjsFromTileMap(....); * importedObjs.forEach( function(obj){ console.log(obj["x"], obj["y"]); }; * * @param {Object|undefined} group. Phaser.Group If given, the reference objects are created in this group. If not given, one is created. * @param {Object} tileMap Phaser.Tilemap * @param {string} name The object layer name in tileMap. * @param {number|string} gid Object name in the object layer in tileMap * @param {string} key The loaded tileset image asset key. This must be loaded before this is called. * @param {number | string} [frame] If the Sprite image contains multiple frames you can specify which one to use here. * @param {boolean} [exists] true The default exists state of the Sprite. * @param {boolean} [autoCull] false The default autoCull state of the Sprite. Sprites that are autoCulled are culled from the camera if out of its range. * @param {Object} [CustomClass] Phaser.Sprite If you wish to create your own class, rather than Phaser.Sprite, pass the class here. Your class must extend Phaser.Sprite and have the same constructor parameters. * @param {boolean} [adjustY] true By default the Tiled map editor uses a bottom-left coordinate system. Phaser uses top-left. So most objects will appear too low down. This parameter moves them up by their height. * @return {Object} Phaser.Group with the objects imported. */ Genari.Group.prototype.createRefObjsFromTileMap = function(group, tileMap, name, gid, key, frame, exists, autoCull, CustomClass, adjustY){ return DCGroup.prototype.createRefObjsFromTileMap.call(this, group, tileMap, name, gid, key, frame, exists, autoCull, CustomClass, adjustY); }; /** * Create sprite objects using the location info from Phaser.Tilemap * We use our own sprites (E.g., "coinSprite") that we loaded, which are not part of the tile map * Usage: * ga.groupCoins.addSpritesFromTilemapObjs(tm, objLayerName, 'coin', ga.coinSpriteKey); * * @param {Object} tileMap Phaser.Tilemap that is already added to the stage. * @param {string} objLayerName object layer name in the tilemap, which contains the objects * @param {string} tileMapObjName the name of the objects in the layer. E.g., if we named objects as "coin", set to "coin" * @param {string} spriteKey sprite asset key. This sprite is created at the location of the obj in the tile map. * @param {Array} [frameSequence] The list of frames sequences to be used for animation of the sprite. e.g.:[0,1,2,3,5,7] * @param {number} [frameRate] Animation speed. Default 4 frames per second */ Genari.Group.prototype.addSpritesFromTilemapObjs = function(tileMap, objLayerName, tileMapObjName, spriteKey, frameSequence, frameRate) { DCGroup.prototype.addSpritesFromTilemapObjs.call(this, tileMap, objLayerName, tileMapObjName, spriteKey, frameSequence, frameRate); }; /** * Use tis as an event handler for collision between player and a collectible item * Player hits a collectible object, adds 0.1 score. * Usage: * ga.groupCoins.checkOverlap(this.playerSprite, ga.groupCoins.playerHitsCollectible, null, this); * * @param {Object} collectible The collectible earned by the player. */ Genari.Group.prototype.playerHitsCollectible = function(collectible) { var ga = this.dcGame; Genari.Effect.bubbleScore(collectible, 0.1); collectible["destroy"](); ga.updateScore(0.1); }; /** * Add a sprite. Sprite can have animations set. * @param x * @param y * @param key * @param frame * @override */ Genari.Group.prototype.addSprite = function(x,y, key, frame){ return DCGroup.prototype.addSprite.call(this, x,y, key, frame); }; /** * Draw a line in this group * @param {number} sx * @param {number} sy * @param {number} ex * @param {number} ey * @param {number|undefined} [lineWidth] * @param {number|undefined} [color] * @param {number|undefined} [alpha] * @param {Object|undefined} [previousLine] Phaser.Graphic * @override */ Genari.Group.prototype.drawLine = function(sx, sy, ex, ey, lineWidth, color, alpha, previousLine) { return DCGroup.prototype.drawLine.call(this, sx, sy, ex, ey, lineWidth, color, alpha, previousLine); }; /** * Add an animation for a sprite. * @param {Object} sprite Phaser.Sprite * @param {string|undefined} [animationName] * @param {Array|undefined} [frames] * @param {number|undefined} [frameRate] * @param {boolean|undefined} [loop] * @param {boolean|undefined} [useNumericIndex] * @param {Function|undefined} [onComplete] Called when the animation is completed after play is called on the animation. * @return {Object} Phaser.Animation * @override */ Genari.Group.prototype.addAnimation = function(sprite, animationName, frames, frameRate, loop, useNumericIndex, onComplete){ return DCGroup.prototype.addAnimation.call(this, sprite, animationName, frames, frameRate, loop, useNumericIndex, onComplete); }; /** * Returns an animation that was previously added by name. * @param {Object} sprite Phaser.Sprite * @param {string|undefined} [animationName] * @return {Object} Phaser.Animation * @override */ Genari.Group.prototype.getAnimation = function(sprite, animationName){ return DCGroup.prototype.getAnimation.call(this, sprite, animationName); }; /** * Add an animation to all members of this group. * If we have members that have exactly the same number of frames, * we can assign the same animation name to all with the same squence of farmes. * @param {string} animationName * @param {Array} [frames] * @param {number} [frameRate] * @param {boolean} [loop] * @param {boolean} [useNumericIndex] * @override */ Genari.Group.prototype.addAnimationToAll = function(animationName, frames, frameRate, loop, useNumericIndex){ DCGroup.prototype.addAnimationToAll.call(this, animationName, frames, frameRate, loop, useNumericIndex); }; /** * Play an animation for the sprite and set speed of the sprite if enabled physics. * @param {Object} sprite * @param {string} name Name of the animation sequence, which must be added previously using addAnimation() * @param {number|undefined} [xSpeed] * @param {number|undefined} [ySpeed] * @param {number|undefined} [frameRate] Default 30 * @param {number|undefined} [loop] Default false * @param {number|undefined} [killOnComplete] Default false * @param {Function|undefined} [onComplete] Called when play is completed * @return {Object|undefined} Phaser.Animation * @override */ Genari.Group.prototype.playAnimation = function(sprite, name, xSpeed, ySpeed, frameRate, loop, killOnComplete, onComplete){ return DCGroup.prototype.playAnimation.call(this, sprite, name, xSpeed, ySpeed, frameRate, loop, killOnComplete, onComplete); }; /** * Move a sprite to the location * @param {Object} sprite * @param {number} x * @param {number} y * @param {number} speed * @param {number|undefined|null} [timeToTravel] * @param {string|undefined|null} [animationName] * @param {Function|undefined|null} [callback ]If timeToTravel is set, this will be called after the sprite arrives at the destination * @param {boolean|undefined|null} [flipHorizontally] Flip sprite horizontally if going left * @param {boolean|undefined|null} [flipVertically] Flip sprite vertically if going down * @override */ Genari.Group.prototype.moveToXY = function(sprite, x, y, speed, timeToTravel, animationName, callback, flipHorizontally, flipVertically){ DCGroup.prototype.moveToXY.call(this, sprite, x, y, speed, timeToTravel, animationName, callback, flipHorizontally, flipVertically); }; /** * Move a sprite along the path defined by the points * @param {Object} sprite * @param {Array} points an Array of points [[x,y], [x, y],....] * @param {number} speed * @param {number|undefined|null} [timeToTravel] * @param {string|undefined|null} [animationName] * @param {Function|undefined|null} [callback ]If timeToTravel is set, this will be called after the sprite arrives at the destination * @param {boolean|undefined|null} [flipHorizontally] Flip sprite horizontally if going left * @param {boolean|undefined|null} [flipVertically] Flip sprite vertically if going down * @override */ Genari.Group.prototype.moveAlongPath = function(sprite, points, speed, timeToTravel, animationName, callback, flipHorizontally, flipVertically){ DCGroup.prototype.moveAlongPath.call(this, sprite, points, speed, timeToTravel, animationName, callback, flipHorizontally, flipVertically); }; /** * Get idx child * @param idx * @returns {Object} Phaser display object * @override */ Genari.Group.prototype.getChild = function(idx){ return DCGroup.prototype.getChild.call(this, idx); }; /** * Get X coordinate of idx child * @param idx * @returns {number} * @override */ Genari.Group.prototype.getChildX = function(idx){ return DCGroup.prototype.getChildX.call(this, idx); }; /** * Get Y coordinate of idx child * @param idx * @returns {number} * @override */ Genari.Group.prototype.getChildY = function(idx){ return DCGroup.prototype.getChildY.call(this, idx); }; /** * Set speed * @param {Object} sprite * @param {number} [xSpeed] * @param {number} [ySpeed] * @override */ Genari.Group.prototype.setSpeed = function(sprite, xSpeed, ySpeed){ DCGroup.prototype.setSpeed.call(this, sprite, xSpeed, ySpeed); }; /** * Move a display object * @param {Object} object * @param {number} x * @param {number} y * @override */ Genari.Group.prototype.moveTo = function(object, x, y){ DCGroup.prototype.moveTo.call(this, object, x, y); }; /** * Destroy all display objects in the group * @param destroyChildren * @param soft * @override */ Genari.Group.prototype.destroy = function(destroyChildren, soft){ DCGroup.prototype.destroy.call(this, destroyChildren, soft); }; /** * Use this in callback functions for overlap or collision detection. * One of the object is a member of this group. * Sort the objects based on membership. * The first object returned is a member of this group. * @param {Object} object1 * @param {Object} object2 * @returns {Array} [MemberObject, nonMemberObject] * @override */ Genari.Group.prototype.getObjInGroup = function(object1, object2){ return DCGroup.prototype.getObjInGroup.call(this, object1, object2); }; /** * Scan the tileMapLayer and mark the cells (value >0) that contain tiles. * We then can place pickup items where there are no tiles. * Call this before placing pickup items on a tilemap layer. * @param {Object} tileMapLayer. The layer you created when imported a tileMap. If you've created your map in Tiled then you can get this by looking in Tiled and looking at the Layer name. Or you can open the JSON file it exports and look at the layers[].name value. Either way it must match. * @param {number|undefined} [gridWidth] The width of the grid cell. Default 16 * @param {number|undefined} [gridHeight] The height of the grid cell. Default 16 * @param {number|undefined} [marginXN1] The first marginXN1 columns will be blocked. Default 0 * @param {number|undefined} [marginXN2] The last marginXN2 columns will be blocked. Default 0 * @param {number|undefined} [marginYN1] The first marginYN1 rows will be blocked. Default 0 * @param {number|undefined} [marginYN2] The last marginYN2 rows will be blocked. Default 0 * @return {Array} grid. 2 dimensional array of columns and rows of cells. grid[column:X][row:Y] > 0 if there is a tile. * @override */ Genari.Group.prototype.setupGrid = function(tileMapLayer, gridWidth, gridHeight, marginXN1, marginXN2, marginYN1, marginYN2) { return DCGroup.prototype.setupGrid.call(this, tileMapLayer, gridWidth, gridHeight, marginXN1, marginXN2, marginYN1, marginYN2); }; /** * Configure the grid for this group. * @param {Object} tileMapLayer Phaser.TileMapLayer that you created * @param {number} gridWidth * @param {number} gridHeight * @param {Array} grid. 2 dimensional array of columns and rows of cells. grid[column:X][row:Y] > 0 if there is a tile. * @override */ Genari.Group.prototype.setGrid = function(tileMapLayer, gridWidth, gridHeight, grid) { DCGroup.prototype.setGrid.call(this, tileMapLayer, gridWidth, gridHeight, grid); }; /** * Check if any of the objects in the group is clicked * @param {number} x * @param {number} y * @param {Function} callBack call for each group element under the point * @param {Object} [callBackContext] * @param {Array} [parameters] */ Genari.Group.prototype.checkPointWithin = function(x,y,callBack,callBackContext,parameters) { DCGroup.prototype.checkPointWithin.call(this,x,y,callBack,callBackContext,parameters); }; /********************************************************************************************* * Use this to manage a group of wordbox display objects * * @param {Object} layer Phaser.Group. The rendering layer of this group. * @param {boolean|undefined} [fixedToCamera] Default false. If set to true, it move with camera. The location is then camera offsets. * @param {boolean|undefined} [enableBody] Default true. If set to true, any objects added will have physics enables * @param {number|undefined} [physicsBodyType] Default Phaser.Physics.ARCADE. Alternatives are Phaser.Physics.P2, Phaser.Physics.NINJA * @constructor * @extends {DCWordBoxGroup} ********************************************************************************************/ Genari.WordBoxGroup = function(layer, fixedToCamera, enableBody, physicsBodyType) { if (!(this instanceof Genari.WordBoxGroup)) return new Genari.WordBoxGroup(layer, fixedToCamera, enableBody, physicsBodyType); // make sure this refer to a Genari.Game DCWordBoxGroup.call(this, layer, fixedToCamera, enableBody, physicsBodyType); }; Genari.WordBoxGroup.prototype = Object.create(DCWordBoxGroup.prototype); // extend Genari.Group Genari.WordBoxGroup.prototype.constructor = Genari.WordBoxGroup; // set constructor property /** * Create a sprite (supports physics body), add the image, and text on top of the image. * Other similar functions: * Genari.addSpritesFromTilemapObjs() * Genari.addSpriteTextBox(x,y,...) * Genari.addP2BodyImageTextBoxFromObj() * Genari.addImageTextBox(x,y,...) * @param {number} x * @param {number} y * @param {string|Object} statement the answer data or the sentence to fit in the box. Font is scaled automatically to fit in to box * @param {number|undefined} [score] If statement is not an answer object (object with "word" and "score" attributes), provide this. + means correct, - means incorrect words * @param {string|undefined} [imageKey] Optional image to add * @param {number|undefined} [width] If not given, the image size is used. * @param {number|undefined} [height] * @param {string|undefined} [align] vertical text align. "center", "top", "bottom", Default "center" * @param {number|undefined} [maxFontSize] Default 16 * @return {Object} Phaser sprite Returns the sprite containing the image and text * @override */ Genari.WordBoxGroup.prototype.addImageTextBox = function(x, y, statement, score, imageKey, width, height, align, maxFontSize){ return DCWordBoxGroup.prototype.addImageTextBox.call(this, x, y, statement, score, imageKey, width, height, align, maxFontSize); }; /** * Creates word boxes containing random level answers using tilemap object layer into the game. * @param {Object} tilemap The tile map referred in creating wordbox object. * @param {string} objectLayerName The tile map layer referred in creating wordbox object. * @param {string} wordBoxFrameImgKey Asset key for the word box frame. * @override */ Genari.WordBoxGroup.prototype.addImageTextBoxFromObj = function(tilemap, objectLayerName, wordBoxFrameImgKey){ DCWordBoxGroup.prototype.addImageTextBoxFromObj.call(this, tilemap, objectLayerName, wordBoxFrameImgKey); }; /** * Create a group with arcade physics enabled, and add a sprite. * Text is added on top of the sprite centered correctly. Font size is fixed 20px. * The returned group has body and can be set velocity and collidable. * * @param {number} x * @param {number} y * @param {string|Object} answer answer object obtained from Genari.getRandomAnswer(). This contains score, text and/or image of the an answer * @param {number|undefined} [score] Optional score when user collect. This is stored in the returned Ojbect.score * @param {string|undefined} [spriteKey] Optional sprite to add under the text. E.g., a crate, jelly * @param {number|undefined} [frame] The initial frame number of the sprite * @param {Array|undefined} [spriteScale] [scaleX, scaleY] * @param {Array|undefined} [textOffset] [x, y] * @param {number|undefined} [textBoxWidth] * @param {number|undefined} [textBoxHeight] * @param {string|undefined} [align] vertical text align. "center", "top", "bottom", Default "center" * @param {number|undefined} [maxFontSize] Default 16 * @return {Object} Returns a display group with a Phaser sprite the text * .children[0] contains the text display object * .anchor The anchorPoint * .children[0].x is the text x position inside the display group * .children[0].width is the text width * Use this to center the text in the sprite if not centered correctly: * var text = obj.children[0]; * text.x = -text.width/2; * text.x = -text.height/3; * @override */ Genari.WordBoxGroup.prototype.addSpriteTextBox = function( x, y, answer, score, spriteKey, frame, spriteScale, textOffset, textBoxWidth, textBoxHeight, align, maxFontSize){ return DCWordBoxGroup.prototype.addSpriteTextBox.call(this, x, y, answer, score, spriteKey, frame, spriteScale, textOffset, textBoxWidth, textBoxHeight, align, maxFontSize); }; /** * If player hits correct box, gain score. If player hits incorrect box, lose life. * Usage : ga.groupWordBox.checkOverlap(this.playerSprite, ga.groupWordBox.playerHitsWordBoxScoreOrDie, null, this); * @param {Object} wordBox The word box sprite object collided by the player. */ Genari.WordBoxGroup.prototype.playerHitsWordBoxScoreOrDie = function(wordBox){ ibg_playerHitsWordBoxScoreOrDie.call(this, wordBox); }; /** * Gain points if player shoot incorrect box. * Usage: * ga.groupBullets.checkOverlap(ga.groupWordBox, ga.groupWordBox.bulletHitsWordBoxScore, null, this); * @param {Object} wordBox The shot word box sprite object. * @param {Object} bulletSprite The shot bullet sprite object. */ Genari.WordBoxGroup.prototype.bulletHitsWordBoxScore = function(wordBox, bulletSprite){ ibg_bulletHitsWordBoxScore.call(this, wordBox, bulletSprite); }; /********************************************************************************************* * Use this to manage a group of immovable platform display objects in the game * Sprite added to this group will not move: sprite["body"]["immovable"] = true; * * ** All methods available to Genari.Group is also available for this group. * * @param {Object} layer Phaser.Group. Rendering layer of this group. * @param {boolean|undefined} [fixedToCamera] Default false. If set to true, it move with camera. The location is then camera offsets. * @param {boolean|undefined} [enableBody] Default true. If set to true, any objects added will have physics enables * @param {number|undefined} [physicsBodyType] Default Phaser.Physics.ARCADE. Alternatives are Phaser.Physics.P2, Phaser.Physics.NINJA * @constructor * @extends {DCPlatformGroup} ********************************************************************************************/ Genari.PlatformGroup = function(layer, fixedToCamera, enableBody, physicsBodyType) { if (!(this instanceof Genari.PlatformGroup)) return new Genari.PlatformGroup(layer, fixedToCamera, enableBody, physicsBodyType); // make sure this refer to a Genari.Game DCPlatformGroup.call(this, layer, fixedToCamera, enableBody, physicsBodyType); }; Genari.PlatformGroup.prototype = Object.create(DCPlatformGroup.prototype); // extend Genari.Group Genari.PlatformGroup.prototype.constructor = Genari.PlatformGroup; // set constructor property /** * Add a ground platform at the location. * @param {number} x * @param {number} y * @param {string} key * @override */ Genari.PlatformGroup.prototype.addPlatform = function(x, y, key){ return DCPlatformGroup.prototype.addPlatform.call(this, x, y, key); }; /********************************************************************************************* * Use this to manage a group of platform display objects in the game * * @param {Object} layer Phaser.Group. Rendering layer of this group. * @param {boolean|undefined} [fixedToCamera] Default false. If set to true, it move with camera. The location is then camera offsets. * @param {boolean|undefined} [enableBody] Default true. If set to true, any objects added will have physics enables * @param {number|undefined} [physicsBodyType] Default Phaser.Physics.ARCADE. Alternatives are Phaser.Physics.P2, Phaser.Physics.NINJA * @constructor * @extends {DCBulletGroup} ********************************************************************************************/ Genari.BulletGroup = function(layer, fixedToCamera, enableBody, physicsBodyType) { if (!(this instanceof Genari.BulletGroup)) return new Genari.BulletGroup(layer, fixedToCamera, enableBody, physicsBodyType); // make sure this refer to a Genari.Game DCBulletGroup.call(this, layer, fixedToCamera, enableBody, physicsBodyType); }; Genari.BulletGroup.prototype = Object.create(DCBulletGroup.prototype); // extend Genari.Group Genari.BulletGroup.prototype.constructor = Genari.BulletGroup; // set constructor property /** * Return the number of bullets alive * @return {number} * @override */ Genari.BulletGroup.prototype.getBulletCount = function(){ return DCBulletGroup.prototype.getBulletCount.call(this); }; /** * Add a bullet object to the group * @param {number} x * @param {number} y * @param {string|undefined} [key] Default null * @param {number|undefined} [xSpeed] * @param {number|undefined} [ySpeed] * @param {number|undefined} [maxDistance] Default 100 * @param {number|undefined} [angle] Default 0. Values from 0 to 180 represent clockwise rotation; values from 0 to -180 represent counterclockwise rotation. * @param {boolean|undefined} [animate] Default false. If set to true, animate using all available frames or the given frames * @param {Array|undefined} [frames] Default null (use all available frames). List of frame numbers for the animation * @param {number|undefined} [frameRate] Default 15 * @param {boolean|undefined} [loop] Default true. * @return {Object} Phaser sprite * @override */ Genari.BulletGroup.prototype.addBullet = function(x, y, key, xSpeed, ySpeed, maxDistance, angle, animate, frames, frameRate, loop){ return DCBulletGroup.prototype.addBullet.call(this, x, y, key, xSpeed, ySpeed, maxDistance, angle, animate, frames, frameRate, loop); }; /** * Add a bullet object to the group * ** This method calls addBullet!! Do not call this method from addBullet!! * @param {number} x * @param {number} y * @param {string|undefined} [key] Default null * @param {number|undefined} [speed] * @param {number|undefined} [dirAngle] Bullet direction degrees. 0 right, 90 down, 180 left, 270 (-90) up * @param {number|undefined} [maxDistance] Default 100 * @param {number|undefined} [spriteAngle] Default 0. Angle in degrees. * @param {boolean|undefined} [animate] Default false. If set to true, animate using all available frames or the given frames * @param {Array|undefined} [frames] Default null (use all available frames). List of frame numbers for the animation * @param {number|undefined} [frameRate] Default 15 * @param {boolean|undefined} [loop] Default true * @return {Object} Phaser sprite * @override */ Genari.BulletGroup.prototype.addBulletWithAngle = function(x, y, key, speed, dirAngle, maxDistance, spriteAngle, animate, frames, frameRate, loop) { return DCBulletGroup.prototype.addBulletWithAngle.call(this, x, y, key, speed, dirAngle, maxDistance, spriteAngle, animate, frames, frameRate, loop); }; /** * Add a line to a bullet object * @param {Object} bullet Phaser.Sprite * @param {number|undefined} [sx] * @param {number|undefined} [sy] * @param {number|undefined} [lineWidth] * @param {number|undefined} [color] * @param {number|undefined} [alpha] * @param {number|undefined} [eXOffset] * @param {number|undefined} [eYOffset] * @return {Object} Phaser Graphics Line * @override */ Genari.BulletGroup.prototype.addLineToBullet = function(bullet, sx, sy, lineWidth, color, alpha, eXOffset, eYOffset){ return DCBulletGroup.prototype.addLineToBullet.call(this, bullet, sx, sy, lineWidth, color, alpha, eXOffset, eYOffset); }; /** * Check bullet and kill if travelled the max distance or out of the speed range * Call this in State.update() * @param {Object} [bullet] Phaser display object * @override */ Genari.BulletGroup.prototype.killBullet = function(bullet) { DCBulletGroup.prototype.killBullet.call(this, bullet); }; /** * Check bullet and kill if travelled the max distance or out of the speed range * Call this in State.update() * @param {number} [sx] Line start x if a line is drawn for the bullets * @param {number} [sy] * @override */ Genari.BulletGroup.prototype.updateBullets = function(sx, sy){ DCBulletGroup.prototype.updateBullets.call(this, sx, sy); }; /********************************************************************************************* * Randomly place some pickup items on the tilemap. * This is useful for dungeon or maze games where you want to place some random pickup items on the road or fields. * * First call Genari.Group.setupGrid(tileMapLayer, gridWidth, gridHeight, grid) on this group to prepare this group. * Next call addPickupsOnTileMap * Use this to manage a group of pickups. Extend this for your own pickup. * * @param {Object} layer Phaser.Group. Rendering layer of this group. * @param {boolean|undefined} [fixedToCamera] Default false. If set to true, it move with camera. The location is then camera offsets. * @param {boolean|undefined} [enableBody] Default true. If set to true, any objects added will have physics enables * @param {number|undefined} [physicsBodyType] Default Phaser.Physics.ARCADE. Alternatives are Phaser.Physics.P2, Phaser.Physics.NINJA * @constructor * @extends {DCPickupGroup} ********************************************************************************************/ Genari.PickupGroup = function(layer, fixedToCamera, enableBody, physicsBodyType) { if (!(this instanceof Genari.PickupGroup)) return new Genari.PickupGroup(layer, fixedToCamera, enableBody, physicsBodyType); // make sure this refer to a Genari.Game DCPickupGroup.call(this, layer, fixedToCamera, enableBody, physicsBodyType); }; Genari.PickupGroup.prototype = Object.create(DCPickupGroup.prototype); // extend Genari.Group Genari.PickupGroup.prototype.constructor = Genari.PickupGroup; // set constructor property /** * Add pickup items on the grid of the world * Must setup the grid first by calling setupGrid() * @param {Object} spriteKey * @param {number|undefined} [placementRate] Default 0.5 * @param {boolean|undefined} [animate] Default false * @param {Array|undefined} [frames] Default null, which uses all frames * @param {boolean|undefined} [loop] Default false * @param {Function|undefined} [callBackForPlacement] Default null * @param {Object|undefined} [callbackContext] Default null * @override */ Genari.PickupGroup.prototype.addPickupsOnTileMap = function(spriteKey, placementRate, animate, frames, loop, callBackForPlacement, callbackContext) { DCPickupGroup.prototype.addPickupsOnTileMap.call(this, spriteKey, placementRate, animate, frames, loop, callBackForPlacement, callbackContext); }; /********************************************************************************************* * Represents a level question * A question has question text, question image, question sound, choices (up to 4), and correct answer * @constructor * @extends {DCQuestion} ********************************************************************************************/ Genari.Question = function() { if (!(this instanceof Genari.Question)) { return new Genari.Question(); } DCQuestion.call(this); this.effectOn = false; }; Genari.Question.prototype = Object.create(DCQuestion.prototype); // extend DCQuestion Genari.Question.prototype.constructor = Genari.Question; // set constructor property /** * Get a next random MCQ question. Return null if there are no more questions. * @param {boolean} [resetIdx] Set to true to reset the index: start from the beginning. * @return {Array|undefined} * [ qNo, * "question text", * correctChoiceNo, iconUrl, img1Url, * ["choice1 text", imgUrl], * ["choice2 text", imgUrl], * ["choice3 text", imgUrl], * ["choice4 text", imgUrl] * ] * Returns an empty array if there are no more questions. You can set resetIdx to true to start again. * If there is no image, url = null * See the returned urls for debugging. * For testing, replace files_N.png etc with your own images. * @override **/ Genari.Question.prototype.getNextQuestion = function(resetIdx){ return DCQuestion.prototype.getNextQuestion.call(this, resetIdx); }; /** * @returns {number} * @override */ Genari.Question.prototype.getQuestionNo = function(){ return DCQuestion.prototype.getQuestionNo.call(this); }; /** * @returns {number} * @override */ Genari.Question.prototype.getCorrectChoiceNo = function(){ return DCQuestion.prototype.getCorrectChoiceNo.call(this); }; /** * @param {number} choiceNo Starts from 1 * @returns {string|null} * @override */ Genari.Question.prototype.getChoiceSndKey = function(choiceNo){ return DCQuestion.prototype.getChoiceSndKey.call(this, choiceNo); }; /** * Used for memory card game. * Show the current question. * @param {Function|undefined} [fileComplete] * @param {Function|undefined} [loadComplete] * @param {Object|undefined} [callBackContext] * @override */ Genari.Question.prototype.loadQuestionAssets = function(fileComplete, loadComplete, callBackContext){ DCQuestion.prototype.loadQuestionAssets.call(this, fileComplete, loadComplete, callBackContext); }; /** * Create a box to hold image of the current question and a text box to hold the question text * * @param {number} x * @param {number} y * @param {string} questionFrameImgKey Default "blueBackground" * @param {string} textFrameImgKey Default "blueBackground" * @param {number} imgWidth * @param {number} imgHeight * @param {number} textBoxHeight * @param {number} space * @param {Object} layer * @returns {Array} * @override */ Genari.Question.prototype.addQuestionBoxes = function( x, y, questionFrameImgKey, textFrameImgKey, imgWidth, imgHeight, textBoxHeight, space, layer) { return DCQuestion.prototype.addQuestionBoxes.call( this, x, y, questionFrameImgKey, textFrameImgKey, imgWidth, imgHeight, textBoxHeight, space, layer); }; /** * Add 2 to 4 (answer) choice boxes for the MCQ question of the level. This is used for memory card game * @param x * @param y * @param {string} twoFrameImgKey Used for for an MCQ question with two choices. * @param {string} fourFrameImgKey Used for for an MCQ question with four choices. * @param boxWidth Width of each choice/answer box * @param boxHeight * @param space Gap between buttons/boxes in pixels * @param {Function} [clickHandler] called when user click on the choice/answer * @override */ Genari.Question.prototype.addChoices = function(x, y, twoFrameImgKey, fourFrameImgKey, boxWidth, boxHeight, space, clickHandler) { DCQuestion.prototype.addChoices.call(this, x, y, twoFrameImgKey, fourFrameImgKey, boxWidth, boxHeight, space, clickHandler); }; /** * @override */ Genari.Question.prototype.destroy = function() { DCQuestion.prototype.destroy.call(this); }; /********************************************************************************************* * Draw a world minimap * @param {string} mapSpriteKey Map sprite key * @param {number} x * @param {number} y * @param {Object} playerSprite Phaser.Sprite * @param {number} scaleFactor Scale of the map. The coordinates of monsters around the player are scaled to this factor. E.g., (minimap_width) / (world_width *2) * @param {number} [mapSize] size of the map. Default the size of the sprite * @param {Object} [layer] Phaser Group. The rendering layer * @constructor * @extends {DCPlayerMap} ********************************************************************************************/ Genari.MiniMap = function (mapSpriteKey, x, y, playerSprite, scaleFactor, mapSize, layer) { if (!(this instanceof Genari.MiniMap)) return new Genari.MiniMap(mapSpriteKey, x, y, playerSprite, scaleFactor, mapSize, layer); // make sure this refer to a Genari.Game DCPlayerMap.call(this, mapSpriteKey, x, y, playerSprite, scaleFactor, mapSize, layer); }; Genari.MiniMap.prototype = Object.create(DCPlayerMap.prototype); // extend DCPlayerMap Genari.MiniMap.prototype.constructor = Genari.MiniMap; // set constructor property /** * Draw a dot of monster in the map * @param {Object} monsters Phaser.Sprite * @override */ Genari.MiniMap.prototype.drawMonsters = function (monsters){ DCPlayerMap.prototype.drawMonsters.call(this, monsters); }; /** * Draw a dot of monster in the map * @param {Object} monster Phaser.Sprite * @override */ Genari.MiniMap.prototype.drawLocation = function (monster){ DCPlayerMap.prototype.drawLocation.call(this, monster); }; /** * If a monster died, remove it from the map * @param {Object} monster Phaser.sprite * @override */ Genari.MiniMap.prototype.removeDot = function (monster){ DCPlayerMap.prototype.removeDot.call(this, monster); }; /********************************************************************************************* * Creates a type of progress bar. * @param {number} x The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number} y The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number|undefined} frameWidth Width of the bar * @param {number} frameHeight * @param {number} initialNumber The number to be displayed when the bar is first created. * @param {number} minNumber The number which is represented by the starting point. * @param {number} maxNumber The number which is represented by the ending point. * @param {string} frameKey The sprite key which is used to be the frame of progress bar. * @param {string} barKey The sprite key which is used to be the bar itself. * @param {Object|undefined} [layer] Phaser Group * @param {number|undefined} [barXoffset] The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number|undefined} [barYoffset] The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number|undefined} [barWidth] The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number|undefined} [barHeight] The horizontal position (x-coordinate) of the progress bar, i.e. frame * @constructor * @extends {DCCounterBar} ********************************************************************************************/ Genari.CounterBar = function(x, y, frameWidth, frameHeight, initialNumber, minNumber, maxNumber, frameKey, barKey, layer, barXoffset, barYoffset, barWidth, barHeight) { if (!(this instanceof Genari.CounterBar)) return new Genari.CounterBar( x, y, frameWidth, frameHeight, initialNumber, minNumber, maxNumber, frameKey, barKey, layer, barXoffset, barYoffset, barWidth, barHeight); DCCounterBar.call(this, x, y, frameWidth, frameHeight, initialNumber, minNumber, maxNumber, frameKey, barKey, layer, barXoffset, barYoffset, barWidth, barHeight); }; Genari.CounterBar.prototype = Object.create(DCCounterBar.prototype); // extend DCCounterBar Genari.CounterBar.prototype.constructor = Genari.CounterBar; // set constructor property /** * Set the value of the bar to given value. * @return {number} current value * @override */ Genari.CounterBar.prototype.getValue = function() { return DCCounterBar.prototype.getValue.call(this); }; /** * Set the value of the bar to given value. * @param {number} barValue The value which is to be set. * @override */ Genari.CounterBar.prototype.setValue = function(barValue) { DCCounterBar.prototype.setValue.call(this, barValue); }; /** * Set the value of the bar to given value. * @param {number} xOffset * @param {number} yOffset */ Genari.CounterBar.prototype.moveBar = function(xOffset,yOffset) { DCCounterBar.prototype.moveBar.call(this, xOffset,yOffset); }; /********************************************************************************************* * The class of timer object. * @param {number} x The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number} y The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number|undefined} width Width of the bar * @param {number|undefined} height * @param {number} initialNumber The number to be displayed when the bar is first created. * @param {number} minNumber The number which is represented by the starting point. * @param {number} maxNumber The number which is represented by the ending point. * @param {string} frameKey The sprite key which is used to be the frame of progress bar. * @param {string} barKey The sprite key which is used to be the bar itself. * @param {Object} [layer] Phaser Group * @param {number} [barXoffset] The horizontal position (x-coordinate) of the progress bar, i.e. frame * @param {number} [barYoffset] The horizontal position (x-coordinate) of the progress bar, i.e. frame * @constructor * @extends {DCTimerBar} ********************************************************************************************/ Genari.TimerBar = function(x, y, width, height, initialNumber, minNumber, maxNumber, frameKey, barKey, layer, barXoffset, barYoffset) { if (!(this instanceof Genari.TimerBar)) return new Genari.TimerBar(x, y, width, height, initialNumber, minNumber, maxNumber, frameKey, barKey, layer, barXoffset, barYoffset); DCTimerBar.call(this, x, y, width, height, initialNumber, minNumber, maxNumber, frameKey, barKey, layer, barXoffset, barYoffset); }; Genari.TimerBar.prototype = Object.create(DCTimerBar.prototype); // extend DCTimerBar Genari.TimerBar.prototype.constructor = Genari.TimerBar; // set constructor property /** * Reset time * @override */ Genari.TimerBar.prototype.stopTimer = function() { return DCTimerBar.prototype.stopTimer.call(this); }; /** * Pause timer * @override */ Genari.TimerBar.prototype.pauseTimer = function() { DCTimerBar.prototype.pauseTimer.call(this); }; /** * resume timer * @override */ Genari.TimerBar.prototype.resumeTimer = function() { DCTimerBar.prototype.resumeTimer.call(this); }; /** * Update timer bar and get the remaining time * @return {number} Return the remaining time * @override */ Genari.TimerBar.prototype.updateBar = function() { return DCTimerBar.prototype.updateBar.call(this); }; /** * tick timer * @return {number} Return the remaining time * @override */ Genari.TimerBar.prototype.reduceTime = function() { return DCTimerBar.prototype.reduceTime.call(this); }; /********************************************************************************************* * Creates score box which displays the score. * @param {string} [key] Sprite key * @param {number} [size] size of the number blocks (width and height) * @param {number} [endX] The x-coordinate of the last reel. * @param {number} [y] The y-coordinate of the reels. * @param {Object} [layer] Phaser.Group * * @constructor * @extends {DCScoreBox} ********************************************************************************************/ Genari.ScoreBox = function(key, size, endX, y, layer) { if (!(this instanceof Genari.ScoreBox)) return new Genari.ScoreBox(key, size, endX, y, layer); DCScoreBox.call(this, key, size, endX, y, layer); }; Genari.ScoreBox.prototype = Object.create(DCScoreBox.prototype); // extend DCScoreBox Genari.ScoreBox.prototype.constructor = Genari.ScoreBox; // set constructor property /** * Get the current score value * @return {number} current score * @override */ Genari.ScoreBox.prototype.getValue = function() { return DCScoreBox.prototype.getValue.call(this); }; /** * This function gains the score by given amount of score. * @param {number|Object} score How much score is added. score = {"answer":{"score},..} * @override */ Genari.ScoreBox.prototype.gainScore = function(score) { DCScoreBox.prototype.gainScore.call(this, score); }; /** * This function reduces the score by given amount of score. * @param {number} score How much score is subtracted. * @param {Function} callBack * @override */ Genari.ScoreBox.prototype.reduceScore = function(score, callBack) { DCScoreBox.prototype.reduceScore.call(this, score, callBack); }; /** * Set the value of the score. * @param {number} targetScore The score which is to be displayed on the score box. * @param {Function} [callBack] */ Genari.ScoreBox.prototype.setScore = function(targetScore, callBack) { DCScoreBox.prototype.controlReelSpin.call(this, targetScore, callBack); }; /********************************************************************************** * Create user icon and life text box * @param [layer] * @constructor * @extends {DCHud} *********************************************************************************/ Genari.Hud = function(layer) { if (!(this instanceof Genari.Hud)) return new Genari.Hud(layer); DCHud.call(this, layer); }; Genari.Hud.prototype = Object.create(DCHud.prototype); // extend DCHud Genari.Hud.prototype.constructor = Genari.Hud; // set constructor property /** * Add UserPhoto * @param x * @param y * @param [userPhotoImgKey] user portrait image. Default userIcon * @param [photoFrameImgKey] image asset key for the frame of the photo. Default userIconFrame * @param [height] * @return {Object} Phaser.sprite * @override */ Genari.Hud.prototype.addUserPhoto = function(x, y, userPhotoImgKey, photoFrameImgKey, height){ return DCHud.prototype.addUserPhoto.call(this, x, y, userPhotoImgKey, photoFrameImgKey, height); }; /** * Add Top bar. Hud Background * @param {number|undefined} [x] Default 0 * @param {number|undefined} [y] Default -5 * @param {string|undefined} [key] Phaser.Sprite asset key. Default 'topBarImage' * @param {number|undefined} [width] * @param {number|undefined} [height] * @return {Object|undefined} {Object} Phaser.Sprite * @override */ Genari.Hud.prototype.addTopBar = function(x, y, key, width, height){ return DCHud.prototype.addTopBar.call(this, x, y, key, width, height); }; /** * Add level text * * @param {number} game_width * @param {number} y * @param {string} text * @param {Object} style * @return {Object} Phaser.Sprite * @override */ Genari.Hud.prototype.addLevelText = function(game_width, y, text, style) { return DCHud.prototype.addLevelText.call(this, game_width, y, text, style); }; /** * Add Game objective Text * * @param {number} game_width * @param {number} y * @param {string} text * @param {Object} style * @return {Object} Phaser.Sprite * @override */ Genari.Hud.prototype.addGameObjectiveText = function(game_width, y, text, style) { return DCHud.prototype.addGameObjectiveText.call(this, game_width, y, text, style); }; /** * Add life icon * @param {number|undefined} [x] Default 70 * @param {number|undefined} [y] Default 10 * @param {string|undefined} [iconKey] * @param {number|undefined} [height] Default 40 * @return {Object} Phaser.Sprite * @override */ Genari.Hud.prototype.addLifeIcon = function(x, y, iconKey, height){ return DCHud.prototype.addLifeIcon.call(this, x, y, iconKey, height); }; /** * Add an icon to hud * @param x * @param y * @param iconKey * @param [height] Default 40 * @return {Object} Phaser.Sprite * @override */ Genari.Hud.prototype.addHudIcon = function(x, y, iconKey, height){ return DCHud.prototype.addHudIcon.call(this, x, y, iconKey, height); }; /** * Add score icon * @param x * @param y * @param iconKey * @param [height] Default 48 * @return {Object} Phaser.Sprite * @override */ Genari.Hud.prototype.addScoreIcon = function(x, y, iconKey, height){ return DCHud.prototype.addScoreIcon.call(this, x, y, iconKey, height); }; /** * Add Pause Button * @param {number|undefined} [x] Default 9 * @param {number|undefined} [y] Default 7 * @param {string|undefined} [key] Default 'pauseButton' Phaser.Sprite asset key. * @param {number|undefined} [height] Default 45 * @param {Function|undefined} [callBack] * @param {Object|undefined} [callBackContext] * @param {number|undefined} [overFrame] Default 0 * @param {number|undefined} [outFrame] Default 1 * @param {number|undefined} [downFrame] Default 2 * @param {number|undefined} [upFrame] Default 1 * @return {Object} Phaser.Sprite * @override */ Genari.Hud.prototype.addPauseButton = function(x, y, key, height, callBack, callBackContext, overFrame, outFrame, downFrame, upFrame){ return DCHud.prototype.addPauseButton.call(this, x, y, key, height, callBack, callBackContext, overFrame, outFrame, downFrame, upFrame); }; /** * Add life text box * @param x * @param y * @param text * @param textStyle * @return {Object} Phaser.Text * @override */ Genari.Hud.prototype.addLifeText = function(x, y, text, textStyle){ return DCHud.prototype.addLifeText.call(this, x, y, text, textStyle); }; /** * Add life text box * @param x * @param y * @param text * @param textStyle * @return {Object} Phaser.Text * @override */ Genari.Hud.prototype.addHudText = function(x, y, text, textStyle){ return DCHud.prototype.addHudText.call(this, x, y, text, textStyle); }; /** * Set life text * @param text * @override */ Genari.Hud.prototype.setLifeValue = function(text){ DCHud.prototype.setLifeValue.call(this, text); }; /** * Add a mouse/pointer cursor fixed to the camera and follow the mouse pointer or where the finger touches * @param {string|undefined} [key] * @param {number|undefined} [upFrame] Default 0 Sprite frame for mouse up * @param {number|undefined} [downFrame] Default 1 Sprite frame for mouse down * @param {number|undefined} [collisionRadius] Cursor collision radius for detecting touch of an object. This is for P2 Physics. Default 10 * @param {Function|undefined} [onPointerMoveCallBack] * @param {Object|undefined} [callBackContext] * @returns {Object} Phaser.Sprite */ Genari.Hud.prototype.addPointerCursor = function(key, upFrame, downFrame, collisionRadius, onPointerMoveCallBack, callBackContext) { return ibg_addPointerCursor.call(this, key, upFrame, downFrame, collisionRadius, onPointerMoveCallBack, callBackContext); }; /** * Destroy display objects * @override */ Genari.Hud.prototype.destroy = function(){ DCHud.prototype.destroy.call(this); }; /********************************************************************************** * Create a dial indicator * @param {number} dialX * @param {number} dialY * @param {string} dialSpriteKey * @param {string} needleSpriteKey * @param {string} dialKnobSpriteKey * @param {number|undefined} [dialSign] * @param {number|undefined} [needleAngle] * @param {number|undefined} [needleX] * @param {number|undefined} [needleY] * @param {Object|undefined} [layer] Phaser.Group * @constructor * @extends {DCDial} *********************************************************************************/ Genari.Dial = function(dialX, dialY, dialSpriteKey, needleSpriteKey, dialKnobSpriteKey, dialSign, needleAngle, needleX, needleY, layer) { if (!(this instanceof Genari.Dial)) return new Genari.Dial(dialX, dialY, dialSpriteKey, needleSpriteKey, dialKnobSpriteKey, dialSign, needleAngle, needleX, needleY, layer); DCDial.call(this, dialX, dialY, dialSpriteKey, needleSpriteKey, dialKnobSpriteKey, dialSign, needleAngle, needleX, needleY, layer); }; Genari.Dial.prototype = Object.create(DCDial.prototype); // extend DCHud Genari.Dial.prototype.constructor = Genari.Dial; // set constructor property /** * Set Angle of the needle * @param {number} angle Degrees, clockwise. 0 = right, 90 = down, 180 = right, 270 = up * @override */ Genari.Dial.prototype.setNeedleAngle = function(angle) { DCDial.prototype.setNeedleAngle.call(this, angle); }; /** * Get Angle of the needle * @return {number} angle Degrees, clockwise. 0 = right, 90 = down, 180 = right, 270 = up * @override */ Genari.Dial.prototype.getNeedleAngle = function() { return DCDial.prototype.getNeedleAngle.call(this); }; /********************************************************************************************* * Use this to manage a group of monsters with text or text boxes in 2D world. * * @param {Object} layer Phaser.Group. Rendering layer of this group. * @param {boolean|undefined} [fixedToCamera] Default false. If set to true, it move with camera. The location is then camera offsets. * @param {boolean|undefined} [enableBody] Default true. If set to true, any objects added will have physics enables * @param {number|undefined} [physicsBodyType] Default Phaser.Physics.ARCADE. Alternatives are Phaser.Physics.P2, Phaser.Physics.NINJA * @constructor * @extends {DC2DMonsterGroup} ********************************************************************************************/ Genari.NPCMonsterGroup = function(layer, fixedToCamera, enableBody, physicsBodyType) { if (!(this instanceof Genari.NPCMonsterGroup)) return new Genari.NPCMonsterGroup(layer, fixedToCamera, enableBody, physicsBodyType); // make sure this refer to a Genari.Game DC2DMonsterGroup.call(this, layer, fixedToCamera, enableBody, physicsBodyType); }; Genari.NPCMonsterGroup.prototype = Object.create(DC2DMonsterGroup.prototype); // extend DCMonsterGroup Genari.NPCMonsterGroup.prototype.constructor = Genari.NPCMonsterGroup; // set constructor property /** * Set the type of monsters for this group * @param {boolean} isEnemy Default true. Set to true for enemies. Set to false for supplies * @override */ Genari.NPCMonsterGroup.prototype.setMonsterType = function(isEnemy) { DC2DMonsterGroup.prototype.setMonsterType.call(this, isEnemy); }; /** * Get the type of monsters for this group * @return {boolean} isEnemy * @override */ Genari.NPCMonsterGroup.prototype.getMonsterType = function() { return DC2DMonsterGroup.prototype.getMonsterType.call(this); }; /** * Create a monster with Arcade physics body, add text and optionally add frame of the text * Add animations for this monster using addAnimation, addWalkUpAnimation, ... * Play animation using playWalkAnimation, walk, walkUp, ... * * @param {number} x The spawn point of the monster * @param {number} y * @param {string|Object} answer object, which contains score text and/or image for an answer. Provide the object obtained using Genari.getRandomeAnswer() * @param {number} score score for capturing or destroying this monster. This is optional if answer object is provided. * @param {string} monsterSpriteKey sprite asset key for the monster * @param {string|undefined} [frameImageKey] If provided, a frame box will be created to for the text * @param {number|undefined} [initialMonsterFrame] * @param {Array|undefined} [textOffset] Default [0,0] * @param {number|undefined} [textWidth] Default. sprite width * @param {number|undefined} [textHeight] Default. sprite height * @param {string|undefined} [align] Text box vertical alignment Default "center". "top", "bottom" * @param {number|undefined} [maxFontSize] Default 16 * @return {Object} monster Phaser.Group containing the monster sprite, text, text box frame * @override */ Genari.NPCMonsterGroup.prototype.addMonsterFramedWordBox = function( x, y, answer, score, monsterSpriteKey, frameImageKey, initialMonsterFrame, textOffset, textWidth, textHeight, align, maxFontSize){ return DC2DMonsterGroup.prototype.addMonsterFramedWordBox.call(this, x, y, answer, score, monsterSpriteKey, frameImageKey, initialMonsterFrame, textOffset, textWidth, textHeight, align, maxFontSize); }; /** * Add an animation sequence details for a monster * @param {Object} monster Phaser.Group containing monster sprite * @param {string|undefined} [animationName] Default "walk" * @param {Array|undefined} [frames] If null, all frames are used * @param {number|undefined} [frameRate] Default 60 * @param {boolean|undefined} [loop] Default false * @param {Function|undefined} [onComplete] Called when the animation is completed after play is called on the animation. * @return {Object|undefined} Phaser.Animation * @override */ Genari.NPCMonsterGroup.prototype.addAnimation = function(monster, animationName, frames, frameRate, loop, onComplete) { return DC2DMonsterGroup.prototype.addAnimation.call(this, monster, animationName, frames, frameRate, loop, undefined, onComplete); }; /** * Add walk up animation sequence details for a monster * @param {Object} monster Phaser.Group containing monster sprite * @param {Array|undefined} [frames] If null, all frames are used * @param {number|undefined} [frameRate] Default 60 * @param {boolean|undefined} [loop] Default false * @override */ Genari.NPCMonsterGroup.prototype.addWalkUpAnimation = function(monster, frames, frameRate, loop) { DC2DMonsterGroup.prototype.addWalkUpAnimation.call(this, monster, frames, frameRate, loop); }; /** * Add walk down animation sequence details for a monster * @param {Object} monster Phaser.Group containing monster sprite * @param {Array|undefined} [frames] If null, all frames are used * @param {number|undefined} [frameRate] Default 60 * @param {boolean|undefined} [loop] Default false * @override */ Genari.NPCMonsterGroup.prototype.addWalkDownAnimation = function(monster, frames, frameRate, loop) { DC2DMonsterGroup.prototype.addWalkDownAnimation.call(this, monster, frames, frameRate, loop); }; /** * Add walk left animation sequence details for a monster * @param {Object} monster Phaser.Group containing monster sprite * @param {Array|undefined} [frames] If null, all frames are used * @param {number|undefined} [frameRate] Default 60 * @param {boolean|undefined} [loop] Default false * @override */ Genari.NPCMonsterGroup.prototype.addWalkLeftAnimation = function(monster, frames, frameRate, loop) { DC2DMonsterGroup.prototype.addWalkLeftAnimation.call(this, monster, frames, frameRate, loop); }; /** * Add walk right animation sequence details for a monster * @param {Object} monster Phaser.Group containing monster sprite * @param {Array|undefined} [frames] If null, all frames are used * @param {number|undefined} [frameRate] Default 60 * @param {boolean|undefined} [loop] Default false * @override */ Genari.NPCMonsterGroup.prototype.addWalkRightAnimation = function(monster, frames, frameRate, loop) { DC2DMonsterGroup.prototype.addWalkRightAnimation.call(this, monster, frames, frameRate, loop); }; /** * Play animation * @param {Object} monster Phaser.Group containing monster sprite * @param {number|undefined} [angle] In degrees. Clockwise. 0 = right, 90 = down, 180 = left, 270 = up * @param {number|undefined} [velocity] pixels per second. * @param {string|undefined} [animationName] * @param {number|undefined} [frameRate] Default 60 * @param {boolean|undefined} [loop] Default false * @param {boolean|undefined} [killOnComplete] Default false * @return {boolean} Return true if playing * @override */ Genari.NPCMonsterGroup.prototype.playWalkAnimation = function(monster, angle, velocity, animationName, frameRate , loop, killOnComplete) { return DC2DMonsterGroup.prototype.playWalkAnimation.call(this, monster, angle, velocity, animationName, frameRate , loop, killOnComplete); }; /** * Play walk animation * @param {Object} monster Phaser.Group containing monster sprite * @param {number|undefined} [angle] Default 0=right. In degrees. Clockwise. 0 = left, 90 = down, 180 = right, 270 = up * @param {number|undefined} [velocity] Default the velocity set using setDefaultVelocity(). pixels per second. * @param {string|undefined} [animationName] Default "walk" * @param {number|undefined} [frameRate] Default the frame rate set using setDefaultFrameRate() * @param {boolean|undefined} [loop] Default false * @param {boolean|undefined} [killOnComplete] Default false * @override */ Genari.NPCMonsterGroup.prototype.walk = function(monster, angle, velocity, animationName, frameRate , loop, killOnComplete) { DC2DMonsterGroup.prototype.walk.call(this, monster, angle, velocity, animationName, frameRate , loop, killOnComplete); }; /** * Play walk up animation * @param {Object} monster Phaser.Group containing monster sprite * @param {number|undefined} [angle] In degrees. Clockwise. 0 = left, 90 = down, 180 = right, 270 = up * @param {number|undefined} [velocity] pixels per second. * @param {number|undefined} [frameRate] Default 60 * @param {boolean|undefined} [loop] Default false * @param {boolean|undefined} [killOnComplete] Default false * @override */ Genari.NPCMonsterGroup.prototype.walkUp = function(monster, angle, velocity, frameRate , loop, killOnComplete) { DC2DMonsterGroup.prototype.walkUp.call(this, monster, angle, velocity, frameRate , loop, killOnComplete); }; /** * Play walk down animation * @param {Object} monster Phaser.Group containing monster sprite * @param {number|undefined} [angle] In degrees. Clockwise. 0 = left, 90 = down, 180 = right, 270 = up * @param {number|undefined} [velocity] pixels per second. * @param {number|undefined} [frameRate] Default 60 * @param {boolean|undefined} [loop] Default false * @param {boolean|undefined} [killOnComplete] Default false * @override */ Genari.NPCMonsterGroup.prototype.walkDown = function(monster, angle, velocity, frameRate , loop, killOnComplete) { DC2DMonsterGroup.prototype.walkDown.call(this, monster, angle, velocity, frameRate , loop, killOnComplete); }; /** * Play walk left animation * @param {Object} monster Phaser.Group containing monster sprite * @param {number|undefined} [angle] In degrees. Clockwise. 0 = left, 90 = down, 180 = right, 270 = up * @param {number|undefined} [velocity] pixels per second. * @param {number|undefined} [frameRate] Default 60 * @param {boolean|undefined} [loop] Default false * @param {boolean|undefined} [killOnComplete] Default false * @override */ Genari.NPCMonsterGroup.prototype.walkLeft = function(monster, angle, velocity, frameRate , loop, killOnComplete) { DC2DMonsterGroup.prototype.walkLeft.call(this, monster, angle, velocity, frameRate , loop, killOnComplete); }; /** * Play walk right animation * @param {Object} monster Phaser.Group containing monster sprite * @param {number|undefined} [angle] In degrees. Clockwise. 0 = left, 90 = down, 180 = right, 270 = up * @param {number|undefined} [velocity] pixels per second. * @param {number|undefined} [frameRate] Default 60 * @param {boolean|undefined} [loop] Default false * @param {boolean|undefined} [killOnComplete] Default false * @override */ Genari.NPCMonsterGroup.prototype.walkRight = function(monster, angle, velocity, frameRate , loop, killOnComplete) { DC2DMonsterGroup.prototype.walkRight.call(this, monster, angle, velocity, frameRate , loop, killOnComplete); }; /** * Change the position of text and text box based on the location of the monster * @param {Object} monster Phaser.Group containing monster sprite * @param {number|undefined} [yMin] monster.textBox["height"] + 64 * @override */ Genari.NPCMonsterGroup.prototype.updateWordBoxLocation = function(monster, yMin) { DC2DMonsterGroup.prototype.updateWordBoxLocation.call(this, monster, yMin); }; /** * Change walk direction randomly every N frames * @param playerSprite * @param monster * @param [velocity] Default is the group default velocity * @param [timeInSeconds] change direction every this seconds Default 2 seconds * @override */ Genari.NPCMonsterGroup.prototype.random2DWalk = function(playerSprite, monster, velocity, timeInSeconds){ DC2DMonsterGroup.prototype.random2DWalk.call(this, playerSprite, monster, velocity, timeInSeconds); }; /** * Control the movements of the monster using the 2D grid generated using setupGrid() * * @param monster The monster to control * @param playerSprite Target * @param [timeInSeconds] Default 2. Generate a new route every this seconds. * @param [rx] Alternative target. E.g., a random point in the game world * @param [ry] * @override */ Genari.NPCMonsterGroup.prototype.quickRoute = function(monster, playerSprite, timeInSeconds, rx, ry) { DC2DMonsterGroup.prototype.quickRoute.call(this, monster, playerSprite, timeInSeconds, rx, ry); }; /************************************************************************************ * Board game treasure box groups * This manages a group of treasure box objects for a player. * * @param {Object} layer Phaser.Group Rendering layer of this group. * @param {Genari.BoardPlayer} treasureOwner Treasures are for this player * @param {boolean|undefined} [fixedToCamera] Default false. If set to true, it move with camera. The location is then camera offsets. * @param {boolean|undefined} [enableBody] Default true. If set to true, any objects added will have physics enables * @param {number|undefined} [physicsBodyType] Default Phaser.Physics.ARCADE. Alternatives are Phaser.Physics.P2, Phaser.Physics.NINJA * @constructor * @extends {DCTreasureGroup} ***********************************************************************************/ Genari.BGTreasureGroup = function(layer, treasureOwner, fixedToCamera, enableBody, physicsBodyType) { if (!(this instanceof Genari.BGTreasureGroup)) { return new Genari.BGTreasureGroup(layer, treasureOwner, fixedToCamera, enableBody, physicsBodyType); } DCTreasureGroup.call(this, layer, treasureOwner, fixedToCamera, enableBody, physicsBodyType); }; Genari.BGTreasureGroup.prototype = Object.create(DCTreasureGroup.prototype); // extend DCTreasureGroup Genari.BGTreasureGroup.prototype.constructor = Genari.BGTreasureGroup; // set constructor property /** * Randomly populate the board with treasure boxes * Each box contains a random answer for the game question (E.g., collect all correct answers) * Randomly create treasure boxes * @param {number} numCols Number of column * @param {number} numRows * @param {number} boardX X location of the board on the stage * @param {number} boardY Y location of the board * @param {number} tileWidth Width of each tile * @param {number} tileHeight * @param {string} spriteKey The key of the sprite to be used to visualize the treasure box. * @param {number} boxOpacity The opacity of the created treasure box, ranges from 0 to 1. * @param {number} treasureOpenFrames * @param {number} animationFPS * @param {number} [emptyRowsCols] default 1 * @param {number} [density] Default 0.3 (30%). Set to higher to increase the number of treasureboxes * @override */ Genari.BGTreasureGroup.prototype.createTreasureBoxes = function( numCols, numRows, boardX, boardY, tileWidth, tileHeight, spriteKey, boxOpacity, treasureOpenFrames, animationFPS, emptyRowsCols, density ) { DCTreasureGroup.prototype.createTreasureBoxes.call(this, numCols, numRows, boardX, boardY, tileWidth, tileHeight, spriteKey, boxOpacity, treasureOpenFrames, animationFPS, emptyRowsCols, density); }; /** * Create a treasure box in the location * @param {number} col * @param {number} row * @override */ Genari.BGTreasureGroup.prototype.createTreasureBox = function(col, row) { DCTreasureGroup.prototype.createTreasureBox.call(this, col, row); }; /** * Return a treasurem box if there is a treasure box in the board cell * @param row starts from 1 * @param col starts from 1 * @returns {Object} Phaser.Sprite a treasure box in the location * @override */ Genari.BGTreasureGroup.prototype.getTreasureBox = function(col, row) { return DCTreasureGroup.prototype.getTreasureBox.call(this, col, row); }; /** * Remove any treasure box at a location * * @param {number} [col] column Starts from 1 * @param {number} [row] row Starts from 1 * @override */ Genari.BGTreasureGroup.prototype.removeTreasureBox = function(col, row) { DCTreasureGroup.prototype.removeTreasureBox.call(this, col, row); }; /** * Check if there is a treasure box at the location * @param {number|undefined} [col] column Starts from 1 * @param {number|undefined} [row] row Starts from 1 * @param {Object|undefined} [player] BoardPlayer * @param {Function|undefined} [callBack] callBack(box) this is called if a treasure box if found and after the opening animation is completed * @return {boolean} True if treasure found * @override */ Genari.BGTreasureGroup.prototype.checkTreasureBox = function(col, row, player, callBack) { return DCTreasureGroup.prototype.checkTreasureBox.call(this, col, row, player, callBack); }; /** * @returns {Object} Genari.BoardPlayer * @override */ Genari.BGTreasureGroup.prototype.getTreasureOwner = function(){ return DCTreasureGroup.prototype.getTreasureOwner.call(this); }; /** * @param treasureOwner * @override */ Genari.BGTreasureGroup.prototype.setTreasureOwner = function(treasureOwner){ DCTreasureGroup.prototype.setTreasureOwner.call(this, treasureOwner); }; /************************************************************************************ * Question Dialog Box * * @param {string} correctAnswerSoundKey * @param {string} incorrectAnswerSoundKey * @param {string} yesButtonImageKey * @param {string} noButtonImageKey * @param {Object} [questionFontStyle] font style for the question * @param {Object} [answerFontStyle] font style for answers * @param {string} [questionYOffset] Y offset of the Question Default -110 * @constructor * @extends {DCGameObject} ***********************************************************************************/ Genari.QuestionDialogBox = function(correctAnswerSoundKey, incorrectAnswerSoundKey, yesButtonImageKey, noButtonImageKey, questionFontStyle, answerFontStyle, questionYOffset) { if (!(this instanceof Genari.QuestionDialogBox)) { return new Genari.QuestionDialogBox(correctAnswerSoundKey, incorrectAnswerSoundKey, yesButtonImageKey, noButtonImageKey, questionFontStyle, answerFontStyle, questionYOffset); } DCGameObject.call(this); this.correctAnswerSoundKey = correctAnswerSoundKey; this.incorrectAnswerSoundKey = incorrectAnswerSoundKey; this.yesButtonImageKey = yesButtonImageKey; this.noButtonImageKey = noButtonImageKey; this.questionFontStyle = questionFontStyle || { "font":"24px Arial", "fontWeight":"bold", "align":"center", "fill":'#090187', // stroke color is white "wordWrap":true, "wordWrapWidth":Genari.dcGame.gameDialogBox["width"] }; this.answerFontStyle = answerFontStyle || { "font":"24px Arial", "fontWeight":"normal", "align":"center", "fill":'#941054', // stroke color is white "wordWrap":true, "wordWrapWidth":Genari.dcGame.gameDialogBox["width"] }; this.questionYOffset = questionYOffset || -110; }; Genari.QuestionDialogBox.prototype = Object.create(DCGameObject.prototype); // extend DCGameObject Genari.QuestionDialogBox.prototype.constructor = Genari.QuestionDialogBox; // set constructor property /** * This is the function to open the treasure box. * Make sure this.dcGame.statePlay.isPlaying is set to true before calling. * Otherwise it will not show the dialog box. * @param answer * @param {Function} dialogBoxBtnClickCallback(playerGetBonusTurn) */ Genari.QuestionDialogBox.prototype.showQuestionDialogBox = function(answer, dialogBoxBtnClickCallback) { ibg_showQuestionDialogBox.call(this, answer, dialogBoxBtnClickCallback); }; /** * Called when a button in the treasure box diaglog box is clicked * Check answer * @param {boolean} choice Choice made by the human player: true or false * @param {Object} [answer] Answer * @param {Function} [callback] callback(playerBonusTurn) */ Genari.QuestionDialogBox.prototype.checkTreasureAnswer = function(choice, answer, callback){ ibg_checkTreasureAnswer.call(this, choice, answer, callback); }; /************************************************************************************ * Represents a game board for typical board games comprising of NxM cells * * Creates a board and groups for pads and treasure boxes * ** Must be called in PlayState.create method and after setToBaseScaleMode() as it adds game assets * * @param {Object} boardRenderingLayer The rendering layer for the player pads * @param {Object} playerPadRenderingLayer The rendering layer for the player pads * @param {number} numCols This is total number of columns including the boarder columns. So this should be the number of columns + 2. * @param {number} numRows This is total number of rows including the boarder rows. So this should be the number of ros + 2. * @param {number|undefined} [borderThickness] Pixel width of each side of border from board boundary. * @param {string|undefined} [boardTextColor] * @constructor * @extends {DCGameObject} this provides this.dcGame and this.phaserGame ***********************************************************************************/ Genari.Board = function(boardRenderingLayer, playerPadRenderingLayer, numCols, numRows, borderThickness, boardTextColor) { if (!(this instanceof Genari.Board)) { return new Genari.Board(boardRenderingLayer, playerPadRenderingLayer, numCols, numRows, borderThickness, boardTextColor); } DCGameObject.call(this); this.boardRenderingLayer = boardRenderingLayer; this.playerPadRenderinglayer = playerPadRenderingLayer; this.numCols = numCols; // ** actual number of columns + 2. This includes the boarders. this.numRows = numRows; this.borderThickness = borderThickness||1; this.totalNumberOfPads = 5*5; // set this to the total number of pads this.boardTextColor = boardTextColor||"#111"; // ga.boardTextColor // There are two players for this board this.humanPlayer = null; this.computerPlayer = null; //--------------------------------- // Create an array of cells that hold Pad type (0=empty, 1=humanPlayer, 2=computerPlayer) // row 0 and the last row are boarder rows. No pads in these rows // col 0 and the last col are boarder cols. No pads in these cols this.boardCellStates = []; // boardCellStates[row][col] = 0, 1, 2. for (var row=0; row < this.numRows; row++) { var r = []; for (var col=0; col < this.numCols; col++) { r.push(0); // 0 means no pad is placed in this cell, 1= player, 2=computer } this.boardCellStates.push(r); } //--------------------------------- // Create a group that holds all pads (both player and computer) // Destroy existing pads if (this.groupBoardPad) this.groupBoardPad.destroy(); this.groupBoardPad = null; }; Genari.Board.prototype = Object.create(DCGameObject.prototype); // extend DCGameObject: provides this.dcGame, this.phaserGame Genari.Board.prototype.constructor = Genari.Board; /** * Add board assets onto the game stage. * Must call this in play["create"] after setToBaseScaleMode() as it adds game assets * @param boardTileMap Tilemap load * @param boardLayerName Name of the layer in the tilemap for the board * @param borderImageAssetKey A separate image to be used as the border decoration of the board. */ Genari.Board.prototype.createBoard = function(boardTileMap, boardLayerName, borderImageAssetKey) { ibg_createBoard.call(this, boardTileMap, boardLayerName, borderImageAssetKey); }; /** * Creates the numbers and letters indicating grid positions on board. * Override this to customise for your game. * @param {Object} boardBorderImg Phaser.Image The border object to place the numbers and letters on. * @param {number} fontSize The font size to be used for text displaying board legend. */ Genari.Board.prototype.createBoardLegends = function(boardBorderImg, fontSize) { Genari.createBoardLegends( this.numRows, this.numCols, this.borderThickness, boardBorderImg, {"font":"Arial", "fontSize":fontSize + "px","fill":this.boardTextColor}, this.boardTileMap, this.tileMapBoardLayer, this.boardRenderingLayer ); }; Genari.Board.prototype.getHumanPlayerScore = function(){ return this.groupBoardPad.getNumberOfPads(this.humanPlayer.marbleSpriteKey); }; Genari.Board.prototype.getComputerPlayerScore = function(){ return this.groupBoardPad.getNumberOfPads(this.computerPlayer.marbleSpriteKey); }; /** * Updates the score of human player * @param {number} currentScore * @param {Genari.ScoreBox} [scoreBox] * @returns {number} human score */ Genari.Board.prototype.updateHumanScore = function(currentScore, scoreBox) { // Update human player score if (currentScore !== this.getHumanPlayerScore()) { if(scoreBox) scoreBox.gainScore(this.getHumanPlayerScore() - currentScore); } return this.getHumanPlayerScore(); }; /** * Updates the score of computer player * @param {number} currentScore * @param {Genari.ScoreBox} [scoreBox] * @returns {number} computer score */ Genari.Board.prototype.updateComputerScore = function(currentScore, scoreBox) { // Update computer score if(currentScore !== this.getComputerPlayerScore()) { if(scoreBox) scoreBox.gainScore(this.getComputerPlayerScore() - currentScore); } return this.getComputerPlayerScore(); }; /** * Control the player's move by AI. * Override this to use a different AI */ Genari.Board.prototype.computerMove = function() { this.bestMoveStrategy(); }; /** * Use simple utility to select a current best move. Not looking at any future states. */ Genari.Board.prototype.bestMoveStrategy = function(){ //------------------------------------------------------------------ // Find a best location for computer player var bestMove = this.computerPlayer.getBestLocation(); var col = bestMove[0]; // base 1 var row = bestMove[1]; var validMove = bestMove[2]; this.performComputerMove(col, row, validMove); }; /** * Place a pad at the location for a computer player * ** override this for your game * @param {number} col base 1 * @param {number} row * @param {Array} validMove [isLegal, ....] other necessary parameters */ Genari.Board.prototype.performComputerMove = function(col, row, validMove) { // override and implement your own computer move }; // This function checks if the board is full. Genari.Board.prototype.checkBoardFull = function() { // Get the number of soldiers on the board var numberOfCurrentPads = ( this.groupBoardPad.getNumberOfPads(this.humanPlayer.marbleSpriteKey) + this.groupBoardPad.getNumberOfPads(this.computerPlayer.marbleSpriteKey) ); // Checks if the board is full. return (numberOfCurrentPads === this.totalNumberOfPads); }; // This function pauses the animation of soldiers and any attack sound. Genari.Board.prototype.pauseSoldiers = function() { if(this.groupBoardPad){ this.groupBoardPad.getGroup().forEach(function(soldier) { soldier["children"][0]["animations"]["stop"](); }); } Genari.dcGame.audioStop(Genari.k.fightingSndKey); }; // This function resumes the animation of soldiers Genari.Board.prototype.resumeSoldiers = function() { if(this.groupBoardPad && this.groupBoardPad.getGroup){ this.groupBoardPad.getGroup().forEach(function(soldier) { soldier["children"][0]["animations"]["paused"] = false; }); } }; // This function stops all of soldiers animations. Genari.Board.prototype.stopAnimation = function() { if(this.groupBoardPad && this.groupBoardPad.getGroup){ this.groupBoardPad.getGroup().forEach(function(soldier) { soldier["children"][0]["animations"]["stop"](); }); } }; /** * This function checks whether the player has reached the end of the level. * @returns {boolean} True if the board is full or both players have no more moves */ Genari.Board.prototype.checkReachedEnd = function (){ // Implement for your board game return false; }; /** * Checks whether the player have more pads than the computer. * @returns {boolean} */ Genari.Board.prototype.isHumanPlayerWinning = function() { // Implement for your game return false; }; /************************************************************************************ * Represents a player of a board game. Has information on what kind of marble it uses * * @param {number} playerId The ID of the player. 1 for player, 2 for computer * @param {Genari.Board} board * @param {number} highlightTileIndex The tile index used to highlight available tiles for player to place stone at. * @param {string} marbleSpriteKey * @param {string} soldierSpriteKey * @param {string} marbleAudioKey * @param {string} flipAudioKey * @constructor * @extends {DCGameObject} this provides this.dcGame and this.phaserGame ***********************************************************************************/ Genari.BoardPlayer = function(playerId, board, highlightTileIndex, marbleSpriteKey, soldierSpriteKey, marbleAudioKey, flipAudioKey) { if (!(this instanceof Genari.BoardPlayer)) { return new Genari.BoardPlayer(playerId, board, highlightTileIndex, marbleSpriteKey, soldierSpriteKey, marbleAudioKey, flipAudioKey); } DCGameObject.call(this); this.playerId = playerId; this.board = board; this.marbleSpriteKey = marbleSpriteKey; this.soldierSpriteKey = soldierSpriteKey; this.noMoreMoves = false; //this.bonusTurn = false; this.marblePlaceAudioKey = marbleAudioKey; this.flipAudioKey = flipAudioKey; // This is specific to each player. DO NOT MOVE TO Game this.highlightTileIndex = highlightTileIndex; this.normalTileIndex = Genari.getTheme()["boardTile"]; this.score = 0; }; Genari.BoardPlayer.prototype = Object.create(DCGameObject.prototype); // extend DCGameObject: provides this.dcGame, this.phaserGame Genari.BoardPlayer.prototype.constructor = Genari.BoardPlayer; /** * Flip a pad in GroupBoardPads to this player type. * It removes the Phaser.Sprite and add a new one for the player type * * @param {Object} marble The soldier marble to be flipped. This is the Phaser.Sprite created by GroupBoardPads * @param {boolean} [showHint] True: show hint for the player * @param {Function} [animationCompleteCallback] animationCompleteCallback(col, row) The function called once flipping is done. */ Genari.BoardPlayer.prototype.flipSoldierMarble = function(marble, showHint, animationCompleteCallback){ ibg_flipSoldierMarble.call(this, marble, showHint, animationCompleteCallback); }; /** * Perform flip animation for a Phaser.Sprite in groupBoardPad * @param {number} col The column number of the pad. * @param {number} row The row number of the pad. * @param {boolean} [showHint] True: perform a chained action (show hint for player) after flipping * @param {Function} [animationCompleteCallback] animationCompleteCallback(col, row) Function to be called once done with flipping. */ Genari.BoardPlayer.prototype.flippingAnimation = function(col, row, showHint, animationCompleteCallback){ ibg_flippingAnimation.call(this, col, row, showHint, animationCompleteCallback); }; /** * Create marble pad sprite using this.marbleSpriteKey. * A player sprite is created on top of the marble pad to animate action. * * @param {number} iconX The x coordinate of where the icon will be placed. * @param {number} iconY The y coordinate of where the icon will be placed. * @param {number} [marbleHeight] The height of the marble object in the grid. * @param {number} [soldierHeight] optional. Not used for this class. * @param {string} [soldierSpriteKey] if given, it creates a solider sprite on top of the pad * @return {Object} Phaser.Sprite created using marbleSpriteKey */ Genari.BoardPlayer.prototype.createIcon = function(iconX, iconY, marbleHeight, soldierHeight, soldierSpriteKey) { return ibg_createIcon.call(this, iconX, iconY, marbleHeight, soldierHeight, soldierSpriteKey); }; /** * Add a pad to board for this player * @param {number} row Base 0 The row number to create the soldier at. * @param {number} column Base 0 The column number to create the soldier at. * @param {boolean} [newPlacement] Whether the ped is created not as a result of flipping. */ Genari.BoardPlayer.prototype.addPad = function(column, row, newPlacement) { // Creates the soldier into the group of pads. Genari.dcGame.board.groupBoardPad.addPad( this, // add pad for this player column, // at this cell location row, newPlacement // is this adding for a new or for flipping ); }; /** * Calculate utility of a location for the player. * ** override this for your game * @param col * @param row * @returns {Array} utility value */ Genari.BoardPlayer.prototype.calcLocationUtility = function(col, row){ return [0]; }; /** * Return the best location for the player * ** override this for your game * @returns {Array} [col, row, otherParameters,...] Return the best location */ Genari.BoardPlayer.prototype.getBestLocation = function() { return [0,0,0]; }; /** * Handle a click even on the board for a human player */ Genari.BoardPlayer.prototype.humanPlayerClickHandler = function() { ibg_humanPlayerClickHandler.call(this); }; /** * The function to place a pad at the selected cell for the human player. * Check if it is valid * Flip affect pads * Open chest box if there is a chest, and show the question dialog box * If answer is correct, human player gets the bonus turn * If answer is incorrect, computer move * @param {number} column Starts from 0 The tile column of where to place a new soldier. * @param {number} row Starts from 0 The tile row of where to place a new soldier. */ Genari.BoardPlayer.prototype.placePadForHumanPlayer = function(column, row) { // implement this for your board player }; /************************************************************************************ * Manage a group of Pads (stones) on a Board * @param {Object} layer Phaser.Group. Rendering layer of this group. * @param {Genari.Board} board Board * @param {boolean} [fixedToCamera] If set to true, it move with camera. The location is then camera offsets. * @param {boolean} [enableBody] If set to true, any objects added will have physics enables * @param {number} [physicsBodyType] Default 0. Phaser.Physics.ARCADE, Phaser.Physics.P2, Phaser.Physics.NINJA * @constructor * @extends {Genari.Group} ***********************************************************************************/ Genari.GroupBoardPads = function(layer, board, fixedToCamera, enableBody, physicsBodyType) { if (!(this instanceof Genari.GroupBoardPads)) { return new Genari.GroupBoardPads(layer, board, fixedToCamera, enableBody, physicsBodyType); // make sure this refer to a DCGame } Genari.Group.call(this, layer, fixedToCamera, enableBody, physicsBodyType); this.board = board; }; Genari.GroupBoardPads.prototype = Object.create(Genari.Group.prototype); Genari.GroupBoardPads.prototype.constructor = Genari.GroupBoardPads; /** * Add a new pad to the group * @param {Genari.BoardPlayer} player * @param {number} row Base 0 The row number to create the soldier object at. * @param {number} column Based 0 The column number to create the soldier object at. * @param {boolean} [newlyPlaced] Whether the soldier is a newly created soldier. * @return {Array} [marble, soldier] Both are sprites: [player.marbleSpriteKey, player.soldierSpriteKey] */ Genari.GroupBoardPads.prototype.addPad = function(player, column, row, newlyPlaced) { return ibg_addPad.call(this, player, column, row, newlyPlaced); }; /** * Reset battle animations for soldiers with no opponenents around * * @param {Array} board The board cells states array of the board game. * @param soldier The current soldier object. * @param soldierLeft The soldier object on the left side of the current soldier. * @param soldierRight The soldier object on the right side of the current soldier. */ Genari.GroupBoardPads.prototype.clearBattleWhenNoOpponent = function(board, soldier, soldierLeft, soldierRight) { ibg_clearBattleWhenNoOpponent.call(this, board, soldier, soldierLeft, soldierRight); }; /** * Calculates the number of soldiers a player * @param {string} marbleKey Player's marble key * @returns {number} The number of soldiers that the player has. */ //Genari.GroupBoardPads.prototype.getNumberOfPads = function(marbleKey) { // implement for your board game // return 0; //}; /********************************************************************************************* * Create a dice sprite on the given rendering layer. * Usage * First create the dice with a dice price (6 faces) and a highlighting image * Next enable click by setting diceSprite.inputEnabled to true * Next call clickDice() a pointer is clicked. This will roll the dice and call the callback function * In the callback functionn check the face value. * Use the highlighting feature to show that the dice is enabled for clicking. * * @class Genari.DiceGroup Dice display object of the game * @param {Object} layer Phaser.Group. Rendering layer of this group. * @param {boolean|undefined} [fixedToCamera] Default false. If set to true, it move with camera. The location is then camera offsets. * @param {boolean|undefined} [enableBody] Default true. If set to true, any objects added will have physics enables * @param {number|undefined} [physicsBodyType] Default Phaser.Physics.ARCADE. Alternatives are Phaser.Physics.P2, Phaser.Physics.NINJA * @param {number} [x] The initial x position of the dice * @param {number} [y] The initial x position of the dice * @param {string} [diceSpritekey] * @param {string} [diceHighlightImgKey] * @param {string} [diceRollSndKey] * @constructor * @extends {DCDiceGroup} ********************************************************************************************/ Genari.DiceGroup = function(layer, fixedToCamera, enableBody, physicsBodyType, x, y, diceSpritekey, diceHighlightImgKey, diceRollSndKey) { if (!(this instanceof Genari.DiceGroup)) return new Genari.DiceGroup(layer, fixedToCamera, enableBody, physicsBodyType); // make sure this refer to a DCGame DCDiceGroup.call(this, layer, fixedToCamera, enableBody, physicsBodyType, x, y, diceSpritekey, diceHighlightImgKey, diceRollSndKey); }; Genari.DiceGroup.prototype = Object.create(DCDiceGroup.prototype); Genari.DiceGroup.prototype.constructor = Genari.DiceGroup; /** * Return the current face of the dice: 1-6 * @return {number} Return the current face of the dice: 1-6 */ Genari.DiceGroup.prototype.getFace = function() { return DCDiceGroup.prototype.getFace.call(this); }; /** * It checks first if this.diceSprite.inputEnabled == true * It then check the location of the active pointer and check if it hit the dice sprite. * If the pointer hits the sprite, * it rolls the dice for one second, * set this.diceSprite.inputEnabled to false and * call the callback * @param {Function} callback this is called after the dice rolled. * @param {Object} context of the callback function * @returns {void|*} */ Genari.DiceGroup.prototype.clickDice = function(callback, context) { return DCDiceGroup.prototype.clickDice.call(this, callback, context); }; /** * Roll the dice and generate a random result. * The SnakeAndLadderControl class calls this function on user interaction * and other situations like free roll or when the computer player's turn * to roll the dice. * @param callback * @param callbackContext */ Genari.DiceGroup.prototype.roll = function(callback, callbackContext) { // play the dice rolling sound effect //ga.audioAssets[ga.diceRollSndKey]["play"](); this.dcGame.audioPlay(this.diceRollSndKey); return DCDiceGroup.prototype.roll.call(this, callback, callbackContext); }; // Show the dice highlight Genari.DiceGroup.prototype.showHighlight = function() { return DCDiceGroup.prototype.showHighlight.call(this); }; // Hide the dice highlight Genari.DiceGroup.prototype.hideHighlight = function() { return DCDiceGroup.prototype.hideHighlight.call(this); }; /************************************************************* * Rendering Layer. Layers created later will be displayed on top of the layers created earlier. * Add objects to this layer to control rendering * @constructor * @extends {DCLayer} *************************************************************/ Genari.Layer = function(){ if( !(this instanceof Genari.Layer)){ return new Genari.Layer(); } DCLayer.call(this); // create layer }; Genari.Layer.prototype = Object.create(DCLayer.prototype); // extend DBGame Genari.Layer.prototype.constructor = Genari.Layer; /** * Add a game object (sprite, image, tilemap layer, etc) to this rendering layer * @param {Object} gameObj * @override */ Genari.Layer.prototype.add = function(gameObj){ DCLayer.prototype.add.call(this, gameObj); }; /** * Call this to destroy an existing layer object. * @override */ Genari.Layer.prototype.destroy = function(){ DCLayer.prototype.destroy.call(this); }; /** * Call this to destroy an existing layer object. * @override */ Genari.Layer.prototype.removeChildren = function(){ DCLayer.prototype.removeChildren.call(this); }; //------------------------------------------------------------------ if(myClassLoader) myClassLoader(); // DEVELOPER_CODE REMOVE_FOR_THEME }; // DEVELOPER_CODE REMOVE_FOR_THEME