diff --git a/app/assets.json b/app/assets.json deleted file mode 100644 index c48e61a..0000000 --- a/app/assets.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "assets": [ - {"type": "music" , "name": "msx_stage" , "options": {}} - ,{"type": "music" , "name": "msx_stage_critical" , "options": {}} - ,{"type": "music" , "name": "msx_stage_results" , "options": {}} - ,{"type": "sound_effects", "name": "sfx_confirm" } - ,{"type": "sound_effects", "name": "sfx_select" } - ,{"type": "sound_effects", "name": "sfx_swap" } - ,{"type": "sound_effects", "name": "sfx_countdown_blip" } - ,{"type": "sound_effects", "name": "sfx_countdown_ding" } - ,{"type": "sound_effects", "name": "sfx_drop0" } - ,{"type": "sound_effects", "name": "sfx_drop1" } - ,{"type": "sound_effects", "name": "sfx_drop2" } - ,{"type": "sound_effects", "name": "sfx_drop3" } - ,{"type": "sound_effects", "name": "sfx_pop0" } - ,{"type": "sound_effects", "name": "sfx_pop1" } - ,{"type": "sound_effects", "name": "sfx_pop2" } - ,{"type": "sound_effects", "name": "sfx_pop3" } - ,{"type": "image" , "name": "bg_blue" } - ,{"type": "image" , "name": "logo" } - ,{"type": "image" , "name": "bg_green" } - ,{"type": "image" , "name": "bg_purple" } - ,{"type": "image" , "name": "menu_bg" } - ,{"type": "image" , "name": "menu_frame_content" } - ,{"type": "image" , "name": "menu_frame_corner" } - ,{"type": "image" , "name": "menu_item_column" } - ,{"type": "image" , "name": "menu_item_content" } - ,{"type": "image" , "name": "menu_cursor" } - ,{"type": "image" , "name": "menu_pause_cursor" } - ,{"type": "image" , "name": "menu_pause" } - ,{"type": "image" , "name": "pause" } - ,{"type": "image" , "name": "puzzle_menu" } - ,{"type": "image" , "name": "playfield_vs_frame" } - ,{"type": "image" , "name": "playfield_vs_bg" } - ,{"type": "image" , "name": "mode_puzzle_bg" } - ,{"type": "image" , "name": "playfield_wall0" } - ,{"type": "image" , "name": "playfield_wall1" } - ,{"type": "image" , "name": "bauble_times" } - ,{"type": "image" , "name": "font" } - ,{"type": "spritesheet" , "name": "garbage_thumb" , "options": {"x": 48 , "y": 32, "frames": 4}} - ,{"type": "spritesheet" , "name": "ints_small" , "options": {"x": 16 , "y": 16, "frames": 18}} - ,{"type": "spritesheet" , "name": "ints_large" , "options": {"x": 16 , "y": 24, "frames": 18}} - ,{"type": "spritesheet" , "name": "playfield_cursor" , "options": {"x": 76 , "y": 44, "frames": 2}} - ,{"type": "spritesheet" , "name": "playfield_countdown", "options": {"x": 124, "y": 76, "frames": 4}} - ,{"type": "spritesheet" , "name": "panels" , "options": {"x": 32 , "y": 32, "frames": 56}} - ,{"type": "spritesheet" , "name": "garbage" , "options": {"x": 32 , "y": 32, "frames": 14}} - ,{"type": "spritesheet" , "name": "star_counter" , "options": {"x": 32 , "y": 32, "frames": 12}} - ,{"type": "spritesheet" , "name": "bauble" , "options": {"x": 6 , "y": 32, "frames": 6}} - ,{"type": "spritesheet" , "name": "bauble_num" , "options": {"x": 12 , "y": 18, "frames": 10}} - ,{"type": "spritesheet" , "name": "bauble_num_small" , "options": {"x": 10 , "y": 18, "frames": 10}} - ,{"type": "spritesheet" , "name": "zephyr" , "options": {"x": 48 , "y": 48, "frames": 84}} - ,{"type": "spritesheet" , "name": "particle_clear" , "options": {"x": 16 , "y": 16, "frames": 32}} - ,{"type": "spritesheet" , "name": "particle_garbage" , "options": {"x": 32 , "y": 32, "frames": 4}} - ,{"type": "spritesheet" , "name": "mode_vs_level" , "options": {"x": 28 , "y": 28, "frames": 20}} - ] -} - diff --git a/app/assets/assets.json b/app/assets/assets.json new file mode 100644 index 0000000..efe0ca8 --- /dev/null +++ b/app/assets/assets.json @@ -0,0 +1,79 @@ +{ + "music": { + "msx_stage" : {} + ,"msx_stage_critical" : {} + ,"msx_stage_results" : {} + }, + "sound_effects" : [ + "sfx_confirm" + ,"sfx_select" + ,"sfx_swap" + ,"sfx_countdown_blip" + ,"sfx_countdown_ding" + ,"sfx_drop0" + ,"sfx_drop1" + ,"sfx_drop2" + ,"sfx_drop3" + ,"sfx_pop0" + ,"sfx_pop1" + ,"sfx_pop2" + ,"sfx_pop3" + ], + "images": [ + "bg_blue" + ,"logo" + ,"bg_green" + ,"bg_purple" + ,"menu_bg" + ,"menu_frame_content" + ,"menu_frame_corner" + ,"menu_item_column" + ,"menu_item_content" + ,"menu_cursor" + ,"menu_pause_cursor" + ,"menu_pause" + ,"pause" + ,"puzzle_menu" + ,"playfield_vs_frame" + ,"playfield_vs_bg" + ,"mode_puzzle_bg" + ,"playfield_wall0" + ,"playfield_wall1" + ,"bauble_times" + ,"font" + ], + "spritesheets" : { + "garbage_thumb" : {"size": "48x32" , "frames": 4} + ,"ints_small" : {"size": "16x16" , "frames": 18} + ,"ints_large" : {"size": "16x24" , "frames": 18} + ,"playfield_cursor" : {"size": "76x44" , "frames": 2} + ,"playfield_countdown": {"size": "124x76", "frames": 4} + ,"panels" : {"size": "32x32" , "frames": 56} + ,"garbage" : {"size": "32x32" , "frames": 14} + ,"star_counter" : {"size": "32x32" , "frames": 12} + ,"bauble" : {"size": "6x32" , "frames": 6} + ,"bauble_num" : {"size": "12x18" , "frames": 10} + ,"bauble_num_small" : {"size": "10x18" , "frames": 10} + ,"particle_clear" : {"size": "16x16" , "frames": 32} + ,"particle_garbage" : {"size": "32x32" , "frames": 4} + ,"mode_vs_level" : {"size": "28x28" , "frames": 20} + ,"zephyr" : {"size": "48x48" , "frames": 84, "animations": { + "stand" : [0,1,2,3,4,5,6,7] + ,"attack" : [12,13,14,15,16,17,18,19,20] + ,"attacked" : [24,25,26,27,28,29,30,31,32] + ,"lost" : [36,37,38,39,40,41,42,43,44,45,46,47] + ,"losing" : [48,49,50,51] + ,"charge" : [60,61,62,63,64,65] + ,"won" : [72,73,74,75,76,77,78,79,80,81] + }}, + "kindle" : {"size": "48x48" , "frames": 84, "animations": { + "stand" : [0,1,2,3,4,5,6,7] + ,"attack" : [12,13,14,15,16,17,18,19] + ,"attacked" : [24,25,26,27,28,29,30,31,32] + ,"lost" : [36,37,38,39,40,41,42,43,44,45,46,47] + ,"losing" : [48,49,50,51,52,53,54,55] + ,"charge" : [60,61,62,63,64,65] + ,"won" : [72,73,74,75,76,77,78,79,80,81] + }} + } +} diff --git a/app/assets/images/bauble.png b/app/assets/spritesheets/bauble.png similarity index 100% rename from app/assets/images/bauble.png rename to app/assets/spritesheets/bauble.png diff --git a/app/assets/images/bauble_num.png b/app/assets/spritesheets/bauble_num.png similarity index 100% rename from app/assets/images/bauble_num.png rename to app/assets/spritesheets/bauble_num.png diff --git a/app/assets/images/bauble_num_small.png b/app/assets/spritesheets/bauble_num_small.png similarity index 100% rename from app/assets/images/bauble_num_small.png rename to app/assets/spritesheets/bauble_num_small.png diff --git a/app/assets/images/garbage.png b/app/assets/spritesheets/garbage.png similarity index 100% rename from app/assets/images/garbage.png rename to app/assets/spritesheets/garbage.png diff --git a/app/assets/images/garbage_thumb.png b/app/assets/spritesheets/garbage_thumb.png similarity index 100% rename from app/assets/images/garbage_thumb.png rename to app/assets/spritesheets/garbage_thumb.png diff --git a/app/assets/images/ints_large.png b/app/assets/spritesheets/ints_large.png similarity index 100% rename from app/assets/images/ints_large.png rename to app/assets/spritesheets/ints_large.png diff --git a/app/assets/images/ints_small.png b/app/assets/spritesheets/ints_small.png similarity index 100% rename from app/assets/images/ints_small.png rename to app/assets/spritesheets/ints_small.png diff --git a/app/assets/spritesheets/kindle.png b/app/assets/spritesheets/kindle.png new file mode 100644 index 0000000..728778d Binary files /dev/null and b/app/assets/spritesheets/kindle.png differ diff --git a/app/assets/images/mode_vs_level.png b/app/assets/spritesheets/mode_vs_level.png similarity index 100% rename from app/assets/images/mode_vs_level.png rename to app/assets/spritesheets/mode_vs_level.png diff --git a/app/assets/images/panels.png b/app/assets/spritesheets/panels.png similarity index 100% rename from app/assets/images/panels.png rename to app/assets/spritesheets/panels.png diff --git a/app/assets/images/particle_clear.png b/app/assets/spritesheets/particle_clear.png similarity index 100% rename from app/assets/images/particle_clear.png rename to app/assets/spritesheets/particle_clear.png diff --git a/app/assets/images/particle_garbage.png b/app/assets/spritesheets/particle_garbage.png similarity index 100% rename from app/assets/images/particle_garbage.png rename to app/assets/spritesheets/particle_garbage.png diff --git a/app/assets/images/playfield_countdown.png b/app/assets/spritesheets/playfield_countdown.png similarity index 100% rename from app/assets/images/playfield_countdown.png rename to app/assets/spritesheets/playfield_countdown.png diff --git a/app/assets/images/playfield_cursor.png b/app/assets/spritesheets/playfield_cursor.png similarity index 100% rename from app/assets/images/playfield_cursor.png rename to app/assets/spritesheets/playfield_cursor.png diff --git a/app/assets/images/star_counter.png b/app/assets/spritesheets/star_counter.png similarity index 100% rename from app/assets/images/star_counter.png rename to app/assets/spritesheets/star_counter.png diff --git a/app/assets/images/zephyr.png b/app/assets/spritesheets/zephyr.png similarity index 100% rename from app/assets/images/zephyr.png rename to app/assets/spritesheets/zephyr.png diff --git a/src/renderer/components/character.ts b/src/renderer/components/character.ts index de66c9e..55eee65 100644 --- a/src/renderer/components/character.ts +++ b/src/renderer/components/character.ts @@ -1,4 +1,5 @@ -import game from 'core/game' +import assets from 'core/assets' +import game from 'core/game' export default class ComponentCharacter { private playfield_num : number @@ -14,6 +15,7 @@ export default class ComponentCharacter { private stopped : boolean public current_animation : string private last_animation : string + private name : string /** * A Sprite is added to the object and several animation objects * @@ -22,10 +24,11 @@ export default class ComponentCharacter { * @param {integer} y default 0 * @param {integer} pi playfield number */ - create(sprite, x = 0, y = 0, pi) { + create(name, x = 0, y = 0, pi) { + this.name = name this.playfield_num = pi // sprite creation - this.sprite = game.add.sprite(x, y, sprite, 0) + this.sprite = game.add.sprite(x, y, name, 0) this.sprite.anchor.setTo(0.5) this.sprite.scale.set(2) this.sprite.smoothed = false @@ -34,17 +37,19 @@ export default class ComponentCharacter { if (pi == 1) { this.sprite.scale.x = -2 - this.x -= -60 + this.x += 40 + } else { + this.x -= 40 } this.animations = new Map() - this.add_animation("stand", 8, 0) - this.add_animation("attack", 9, 12, "stand") - this.add_animation("attacked", 9, 24, "stand") - this.add_animation("lost", 12, 36, "", true) - this.add_animation("losing", 4, 48) - this.add_animation("charge", 6, 60) - this.add_animation("won", 10, 72, "", true) + this.add_animation(this.name, "stand") + this.add_animation(this.name, "attack" , "stand") + this.add_animation(this.name, "attacked", "stand") + this.add_animation(this.name, "lost", "", true) + this.add_animation(this.name, "losing") + this.add_animation(this.name, "charge") + this.add_animation(this.name, "won", "", true) this.tick_counter = 0 this.frame_counter = 0 @@ -57,22 +62,19 @@ export default class ComponentCharacter { * Add an animation object with information to the Map object inside this character, * the defined name can then be called from the Map to return the animation object * - * @param {String} name simple name to be called by the animations map + * @param {string} character key + * @param {string} name simple name to be called by the animations map * @param {integer} hframes amount of horizontal frames to run through * @param {integer} offset amount of offset to start the hframes counting from * @param {String} return_to_animation the animation.name to return to after finishing the animation * @param {boolean} stop_animation if the animation cycle should in general stop */ - add_animation(name, hframes, offset, return_to_animation = "", stop_animation = false) { + add_animation(key, name, return_to_animation = "", stop_animation = false) { const animation = { - frames : [], + frames : assets.spritesheets[key].animations[name], stop_animation : stop_animation, parent_animation : return_to_animation } - - let ct = 0; - for (let frame = offset; frame < offset + hframes; frame++) - animation.frames[ct++] = frame this.animations.set(name, animation) } diff --git a/src/renderer/components/playfield.ts b/src/renderer/components/playfield.ts index 80d9126..9ed81ab 100644 --- a/src/renderer/components/playfield.ts +++ b/src/renderer/components/playfield.ts @@ -169,12 +169,6 @@ export default class Playfield { //this.score_lbl.create() // for mode_puzzle, couting all swaps this.swap_counter = 0; - this.character.create( - "zephyr", - game.world.centerX - 30, - game.world.centerY - 100, - this.pi - ); } get clear(){ @@ -197,6 +191,12 @@ export default class Playfield { this.cursor.create(this) if (this.has_ai) { this.ai.create(this, this.cursor) } this.wall.create(this,this.x,this.y) + this.character.create( + (this.pi === 0) ? 'zephyr' : 'kindle', + game.world.centerX, + game.world.centerY - 100, + this.pi + ); } create_stack(data){ this._stack = [] diff --git a/src/renderer/core/assets.ts b/src/renderer/core/assets.ts new file mode 100644 index 0000000..c9ae0f2 --- /dev/null +++ b/src/renderer/core/assets.ts @@ -0,0 +1,75 @@ +import * as fs from 'fs' +import game from 'core/game' +import Store from 'common/store' +const store = new Store() + +class Assets { + private static _instance: Assets + private dir : string + private assets : { + music : {}, + sound_effects : Array, + images : Array, + spritesheets : {} + } + + public static get Instance(){ + return this._instance || (this._instance = new this()) + } + + constructor(){ + this.dir = store.get('asset-dir') + } + + preload(){ + game.load.json('assets', this.json) + } + + load(){ + this.assets = game.cache.getJSON('assets') + } + + get music() { return this.assets.music } + get sound_effects(){ return this.assets.sound_effects } + get images() { return this.assets.images } + get spritesheets() { return this.assets.spritesheets } + + /** + * @param type either music, sound_effects, image, spritesheet + * @param name name of the asset + * @returns the path based on type + */ + path(kind : string, name : string) { + const filename = this.filename(kind,name) + const external = this.dir + '/' + filename + const internal = './assets' + '/' + filename + if (fs.existsSync(external)) { + return external + } else { + return internal + } + } + + get json(){ + const filename = 'assets.json' + const external = this.dir + '/' + filename + const internal = './assets' + '/' + filename + if (fs.existsSync(external)) { + return external + } else { + return internal + } + } + + filename(kind : string, name : string){ + switch (kind) { + case "music" : return `music/${name}.mp3` + case "sound_effects" : return `sound_effects/${name}.ogg` + case "images" : return `images/${name}.png` + case "spritesheets" : return `spritesheets/${name}.png` + } + } +} + +const assets = Assets.Instance +export default assets diff --git a/src/renderer/states/load.ts b/src/renderer/states/load.ts index 93f01d1..419afc4 100644 --- a/src/renderer/states/load.ts +++ b/src/renderer/states/load.ts @@ -1,6 +1,6 @@ import { ipcRenderer as ipc } from "electron"; - import game from 'core/game' +import assets from 'core/assets' import State from 'states/base' import controls from 'core/controls' import Store from 'common/store' @@ -16,30 +16,23 @@ ipc.on('asset-list', (e, files) => external_assets = files) * Uses signals to detect once everything has been loaded correctly */ export default class LoadState extends State { - private all_assets : Array<{}> - private external_asset_dir : string - get name(): string { return 'load'; } - /** preload a json file where all assets preconfigs */ - preload() { - game.load.json('assets', './assets.json'); + preload(){ + assets.preload() } create() { - this.external_asset_dir = store.get('asset-dir') - this.all_assets = game.cache.getJSON('assets').assets - this.load_assets(); - - game.load.onLoadComplete.add(() => { + assets.load() + this.load_assets() + game.load.onLoadComplete.add(() => { controls.create() game.sounds.create() game.state.start('menu') }, this) - - game.load.start(); + game.load.start() } - + /** Loads all assets in the assets folder * if any assets with the same name, data type etc exist in the * external assets folder -> external asset is loaded instead of the @@ -49,44 +42,40 @@ export default class LoadState extends State { * they behave under the restrictions defined in assets.json */ load_assets() { - this.all_assets.forEach(e => { - let type : string = e["type"]; - let name : string = e["name"]; - let load_external = external_assets.find(a => a === name) - let path : string = this.asset_path(type, name, load_external) + this.load_music() + this.load_sound_effects() + this.load_images() + this.load_spritesheets() + } + - switch (type) { - case "music" : game.load.audio(name, path); break; - case "sound_effects": game.load.audio(name, path); break; - case "image" : game.load.image(name, path); break; - case "spritesheet" : - let props = e["options"]; - game.load.spritesheet(name, path, props.x, props.y, props.frames); - break; - } + load_music(){ + Object.keys(assets.music).forEach(function(key){ + game.load.audio(key,assets.path('music', key)) }) } - /** - * @param type either music, sound_effects, image, spritesheet - * @param name name of the asset - * @param external if the path should be external or not - * @returns the path based on type - */ - asset_path(type : string, name : string, external) { - if (!external) - switch (type) { - case "music": return `./assets/music/${name}.mp3` - case "sound_effects": return `./assets/sound_effects/${name}.ogg` - case "image": return `./assets/images/${name}.png` - case "spritesheet": return `./assets/images/${name}.png` - } - else - switch (type) { - case "music": return this.external_asset_dir + `/${name}.mp3` - case "sound_effects": return this.external_asset_dir + `/${name}.ogg` - case "image": return this.external_asset_dir + `/${name}.png` - case "spritesheet": return this.external_asset_dir + `/${name}.png` - } + load_sound_effects(){ + assets.sound_effects.forEach(function(key){ + game.load.audio(key,assets.path('sound_effects',key)) + }) + } + + load_images(){ + assets.images.forEach(function(key){ + game.load.image(key,assets.path('images',key)) + }) + } + + load_spritesheets(){ + let data,pos + Object.keys(assets.spritesheets).forEach(function(key) { + data = assets.spritesheets[key] + pos = data.size.split('x') + game.load.spritesheet(key,assets.path('spritesheets',key), + parseInt(pos[0]), + parseInt(pos[1]), + parseInt(data.frames)) + }) } }