1
0
Fork 0

Use atlas to pack images

This commit is contained in:
Michaël Lemaire 2017-07-27 00:54:56 +02:00
parent eaa52e9b75
commit 8530ab88f3
58 changed files with 96 additions and 61 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
coverage
/node_modules
/out/vendor
/out/assets/atlas*
/out/build.*
/graphics/**/*.blend?*
/typings/

View File

@ -21,13 +21,11 @@ The only hard dependency of the toolchain is Python3.
If you want to build on your computer, clone the repository, then run:
./spacetac install # Install dependencies
./spacetac run build # Build the final JS
./spacetac run pack # Pack the images and sounds
./spacetac test # Run unit tests
./spacetac start # Start development server, and open game in web browser
After making changes to sources, you need to recompile:
./spacetac run build
## Credits
* **[Michaël Lemaire](https://thunderk.net/)** - Code and graphics

View File

@ -85,6 +85,12 @@ Common UI
* Mobile: display tooltips larger and on the side of screen where the finger is not
* Mobile: targetting in two times, using a draggable target indicator
Technical
---------
* Pack all images in atlases
* Pack sounds
Network
-------

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -7,6 +7,7 @@
"shell": "${SHELL} || true",
"postinstall": "typings install && rm -rf out/vendor && mkdir -p out/vendor && cp -r node_modules/phaser/build out/vendor/phaser && cp -r node_modules/phaser-plugin-scene-graph/dist out/vendor/phaser-plugin-scene-graph && cp -r node_modules/parse/dist out/vendor/parse && cp -r node_modules/jasmine-core/lib/jasmine-core out/vendor/jasmine",
"build": "tsc -p .",
"pack": "rm -f out/assets/atlas* && find graphics/exported -name '*.png' -print0 | xargs -0 gf-pack --name out/assets/atlas --fullpath --width 1024 --height 1024 --square --powerOfTwo --trim",
"pretest": "tsc -p .",
"test": "karma start spec/support/karma.conf.js && remap-istanbul -i out/coverage/coverage.json -o out/coverage -t html",
"prestart": "tsc -p . || true",
@ -22,6 +23,7 @@
"devDependencies": {
"babel-polyfill": "^6.23.0",
"codecov": "^2.2.0",
"gamefroot-texture-packer": "git+https://github.com/Gamefroot/Gamefroot-Texture-Packer.git#f3687111afc94f80ea8f2877c188fb8e2004e8ff",
"jasmine": "^2.6.0",
"karma": "^1.7.0",
"karma-coverage": "^1.1.1",
@ -39,4 +41,4 @@
"phaser": "^2.6.2",
"phaser-plugin-scene-graph": "^1.0.4"
}
}
}

View File

@ -175,11 +175,39 @@ module TS.SpaceTac.UI {
}
/**
* Get the first image found in cache
* Get a new image from an atlas name
*/
getImage(...keys: string[]): string {
let found = first(keys, key => this.game.cache.checkImageKey(key));
return found ? found : "default";
newImage(name: string, x = 0, y = 0): Phaser.Image {
let info = this.getImageInfo(name);
let result = this.game.add.image(x, y, info.key, info.frame);
result.name = name;
return result;
}
/**
* Get an image from atlases
*/
getImageInfo(name: string): { key: string, frame: number } {
// TODO Cache
let i = 1;
while (this.game.cache.checkImageKey(`atlas-${i}`)) {
let data = this.game.cache.getFrameData(`atlas-${i}`);
let frames = data.getFrames();
let frame = first(frames, frame => Preload.getKey(frame.name) == `graphics-exported-${name}`);
if (frame) {
return { key: `atlas-${i}`, frame: frame.index };
}
i++;
}
return { key: "default", frame: 0 };
}
/**
* Get the first image found in atlases
*/
getFirstImage(...names: string[]): { key: string, frame: number } {
let infos = names.map(name => this.getImageInfo(name));
return first(infos, info => info.key != "default") || infos[0];
}
}
}

View File

@ -34,8 +34,6 @@ module TS.SpaceTac.UI {
this.loadImage("battle/actionbar/background.png");
this.loadSheet("battle/actionbar/icon.png", 88, 88);
this.loadSheet("battle/actionbar/power.png", 58, 21);
this.loadImage("battle/actionbar/action-move.png");
this.loadImage("battle/actionbar/action-endturn.png");
this.loadSheet("battle/actionbar/button-menu.png", 79, 132);
this.loadImage("battle/arena/background.png");
this.loadImage("battle/arena/blast.png");
@ -85,31 +83,10 @@ module TS.SpaceTac.UI {
this.loadImage("character/upgrade-available.png");
this.loadImage("character/price-tag.png");
this.loadImage("character/experience.png");
this.loadImage("equipment/ironhull.png");
this.loadImage("equipment/forcefield.png");
this.loadImage("equipment/nuclearreactor.png");
this.loadImage("equipment/rocketengine.png");
this.loadImage("equipment/gatlinggun.png");
this.loadImage("equipment/powerdepleter.png");
this.loadImage("equipment/submunitionmissile.png");
this.loadImage("equipment/repairdrone.png");
this.loadImage("equipment/shieldtransfer.png");
this.loadImage("equipment/damageprotector.png");
// Load ships
this.loadShip("avenger");
this.loadShip("breeze");
this.loadShip("commodore");
this.loadShip("creeper");
this.loadShip("falcon");
this.loadShip("flea");
this.loadShip("jumper");
this.loadShip("rhino");
this.loadShip("scout");
this.loadShip("tomahawk");
this.loadShip("trapper");
this.loadShip("whirlwind");
this.loadShip("xander");
// Load image atlases
// TODO automatic range
range(3).forEach(i => this.loadAtlas(i + 1));
// Load sounds
this.loadSound("ui/button-down.wav");
@ -144,12 +121,8 @@ module TS.SpaceTac.UI {
return path.replace(/\//g, "-").replace(/\.[a-z0-9]+$/, '');
}
/**
* Load a ship's sprite and portrait
*/
loadShip(name: string) {
this.loadImage("ship/" + name + "/sprite.png");
this.loadImage("ship/" + name + "/portrait.png");
loadAtlas(index: number) {
this.load.atlasJSONHash(`atlas-${index}`, `assets/atlas-${index}.png`, `assets/atlas-${index}.json`);
}
loadSheet(path: string, frame_width: number, frame_height = frame_width) {

View File

@ -64,8 +64,8 @@ module TS.SpaceTac.UI {
this.addChild(this.layer_selected);
// Icon layer
let icon = this.battleview.getImage(`battle-actionbar-action-${action.code}`, `equipment-${action.equipment ? action.equipment.code : "---"}`);
this.layer_icon = new Phaser.Image(this.game, this.width / 2, this.height / 2, icon, 0);
let icon = this.battleview.getFirstImage(`action-${action.code}`, `equipment-${action.equipment ? action.equipment.code : "---"}`);
this.layer_icon = new Phaser.Image(this.game, this.width / 2, this.height / 2, icon.key, icon.frame);
this.layer_icon.anchor.set(0.5, 0.5);
this.layer_icon.scale.set(0.25, 0.25);
this.addChild(this.layer_icon);

View File

@ -7,8 +7,8 @@ module TS.SpaceTac.UI {
* Fill the tooltip
*/
static fill(filler: TooltipFiller, ship: Ship, action: BaseAction, position: number) {
let icon = filler.view.getImage(`equipment-${action.equipment ? action.equipment.code : "---"}`, `battle-actionbar-action-${action.code}`);
filler.addImage(0, 0, icon, 0.5);
let icon = filler.view.getFirstImage(`equipment-${action.equipment ? action.equipment.code : "---"}`, `action-${action.code}`);
filler.addImage(0, 0, icon.key, icon.frame, 0.5);
filler.addText(150, 0, action.equipment ? action.equipment.name : action.name, "#ffffff", 24);

View File

@ -45,7 +45,8 @@ module TS.SpaceTac.UI {
this.activation.visible = false;
this.add(this.activation);
this.sprite = new Phaser.Button(this.game, 0, 0, battleview.getImage(`equipment-${drone.code}`, `battle-actions-deploy-${drone.code}`));
let info = battleview.getFirstImage(`equipment-${drone.code}`, `battle-actions-deploy-${drone.code}`);
this.sprite = new Phaser.Button(this.game, 0, 0, info.key, undefined, undefined, info.frame, info.frame);
this.sprite.anchor.set(0.5, 0.5);
this.sprite.scale.set(0.1, 0.1);
this.add(this.sprite);

View File

@ -52,7 +52,8 @@ module TS.SpaceTac.UI {
this.add(this.effects_radius);
// Add ship sprite
this.sprite = new Phaser.Button(this.game, 0, 0, "ship-" + ship.model.code + "-sprite");
let info = this.battleview.getImageInfo(`ship-${ship.model.code}-sprite`);
this.sprite = new Phaser.Button(this.game, 0, 0, info.key, undefined, undefined, info.frame, info.frame);
this.sprite.rotation = ship.arena_angle;
this.sprite.anchor.set(0.5, 0.5);
this.sprite.scale.set(0.25);

View File

@ -28,7 +28,7 @@ module TS.SpaceTac.UI {
fleet1.ships.forEach((ship, index) => {
let ship_card = view.game.add.image(-100 + index * 96, -26, "battle-splash-shipcard", 0);
ship_card.anchor.set(0.5);
let ship_portrait = view.game.add.image(0, 0, `ship-${ship.model.code}-portrait`);
let ship_portrait = view.newImage(`ship-${ship.model.code}-portrait`);
ship_portrait.scale.set(0.3);
ship_portrait.anchor.set(0.5);
ship_card.addChild(ship_portrait);
@ -49,7 +49,7 @@ module TS.SpaceTac.UI {
fleet2.ships.forEach((ship, index) => {
let ship_card = view.game.add.image(-104 + index * 96, -32, "battle-splash-shipcard", 1);
ship_card.anchor.set(0.5);
let ship_portrait = view.game.add.image(0, 0, `ship-${ship.model.code}-portrait`);
let ship_portrait = view.newImage(`ship-${ship.model.code}-portrait`);
ship_portrait.scale.set(0.3);
ship_portrait.anchor.set(0.5);
ship_card.angle = 180;

View File

@ -31,7 +31,7 @@ module TS.SpaceTac.UI {
this.player_indicator.angle = 90;
this.addChild(this.player_indicator);
this.portrait = new Phaser.Image(this.game, 18, 9, "ship-" + ship.model.code + "-portrait", 0);
this.portrait = this.view.newImage(`ship-${ship.model.code}-portrait`, 18, 9);
this.portrait.scale.set(0.332, 0.332);
this.addChild(this.portrait);

View File

@ -21,7 +21,7 @@ module TS.SpaceTac.UI.Specs {
tooltip.setShip(ship);
let content = (<any>tooltip).container.content;
expect(content.children[0].data.key).toBe("ship-fake-portrait");
expect(content.children[0].name).toBe("ship-fake-portrait");
expect(content.children[1].text).toBe("Fury");
expect(content.children[2].text).toBe("Plays in 2 turns");
expect(content.children[3].text).toBe("Hull\n58");

View File

@ -24,7 +24,7 @@ module TS.SpaceTac.UI {
filler.configure(10, 6, this.battleview.arena.getBoundaries());
filler.addImage(0, 0, `ship-${ship.model.code}-portrait`, 0.5);
filler.addImageA(0, 0, `ship-${ship.model.code}-portrait`, 0.5);
let enemy = ship.getPlayer() != this.battleview.player;
filler.addText(140, 0, ship.name, enemy ? "#cc0d00" : "#ffffff", 22, false, true);

View File

@ -223,7 +223,9 @@ module TS.SpaceTac.UI {
this.ship = action.equipment.attached_to.ship;
this.action = action;
this.move_ghost.loadTexture(`ship-${this.ship.model.code}-sprite`);
let info = this.view.getImageInfo(`ship-${this.ship.model.code}-sprite`);
this.move_ghost.loadTexture(info.key);
this.move_ghost.frame = info.frame;
this.move_ghost.scale.set(0.25);
} else {
this.ship = null;

View File

@ -35,8 +35,8 @@ module TS.SpaceTac.UI {
price: number
constructor(sheet: CharacterSheet, equipment: Equipment, container: CharacterEquipmentContainer) {
let icon = sheet.view.getImage(`equipment-${equipment.code}`, `battle-actions-${equipment.action.code}`);
super(sheet.game, 0, 0, icon);
let icon = sheet.view.getImageInfo(`equipment-${equipment.code}`);
super(sheet.game, 0, 0, icon.key, undefined, undefined, icon.frame, icon.frame);
this.sheet = sheet;
this.item = equipment;

View File

@ -16,7 +16,7 @@ module TS.SpaceTac.UI {
this.sheet = sheet;
this.ship = ship;
let portrait_pic = new Phaser.Image(this.game, 0, 0, `ship-${ship.model.code}-portrait`);
let portrait_pic = sheet.view.newImage(`ship-${ship.model.code}-portrait`);
portrait_pic.anchor.set(0.5, 0.5);
this.addChild(portrait_pic);

View File

@ -100,13 +100,22 @@ module TS.SpaceTac.UI {
/**
* Add an image to the content
*/
addImage(x: number, y: number, key: string, scale = 1): void {
let image = new Phaser.Image(this.container.game, x, y, key);
addImage(x: number, y: number, key: string, frame = 0, scale = 1): void {
let image = new Phaser.Image(this.container.game, x, y, key, frame);
image.data.key = key;
image.scale.set(scale);
this.container.content.add(image);
}
/**
* Add an image to the content, coming from an atlas
*/
addImageA(x: number, y: number, name: string, scale = 1): void {
let image = this.view.newImage(name, x, y);
image.scale.set(scale);
this.container.content.add(image);
}
/**
* Add a text to the content
*/

View File

@ -43,9 +43,10 @@ module TS.SpaceTac.UI {
this.removeAll(true);
this.fleet.ships.forEach((ship, index) => {
let offset = LOCATIONS[index];
let sprite = this.game.add.image(offset[0], offset[1] + 150, `ship-${ship.model.code}-sprite`, 0, this);
let sprite = this.map.newImage(`ship-${ship.model.code}-sprite`, offset[0], offset[1] + 150);
sprite.scale.set(64 / sprite.width);
sprite.anchor.set(0.5, 0.5);
this.add(sprite);
});
this.ship_count = this.fleet.ships.length;

View File

@ -1025,6 +1025,15 @@ function-bind@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
"gamefroot-texture-packer@git+https://github.com/Gamefroot/Gamefroot-Texture-Packer.git#f3687111afc94f80ea8f2877c188fb8e2004e8ff":
version "1.1.1"
resolved "git+https://github.com/Gamefroot/Gamefroot-Texture-Packer.git#f3687111afc94f80ea8f2877c188fb8e2004e8ff"
dependencies:
async "^1.4.0"
glob "^5.0.14"
mustache "^2.1.3"
optimist "~0.6.0"
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
@ -1075,7 +1084,7 @@ glob-parent@^2.0.0:
dependencies:
is-glob "^2.0.0"
glob@^5.0.15:
glob@^5.0.14, glob@^5.0.15:
version "5.0.15"
resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
dependencies:
@ -2020,6 +2029,10 @@ multipipe@^0.1.2:
dependencies:
duplexer2 "0.0.2"
mustache@^2.1.3:
version "2.3.0"
resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.0.tgz#4028f7778b17708a489930a6e52ac3bca0da41d0"
nan@^2.3.0:
version "2.6.2"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
@ -2154,7 +2167,7 @@ opn@latest:
dependencies:
is-wsl "^1.1.0"
optimist@^0.6.1:
optimist@^0.6.1, optimist@~0.6.0:
version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
dependencies: