Skip to content

Commit 5bd9fa8

Browse files
- Adds portrait support (closes #15)
1 parent beb1577 commit 5bd9fa8

File tree

7 files changed

+105
-28
lines changed

7 files changed

+105
-28
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@
3434
- Automatic template background
3535
- Sets up the size the game so that it is scaled only when absolutely necessary
3636
- Refer to src/utils/utils.ts for an explanation on the background_template and the sizing/scaling style
37+
- Landscape and Portrait support
3738

38-
### TODO:
39+
### TODO (in no particular order):
3940

4041
- Clean up generateAssetsClass.js
4142
- Get Custom/Local Web Fonts hashed by Webpack (to avoid cache issues)
@@ -214,7 +215,9 @@ Run the following specifying some or all of the options;
214215

215216
**The '--' after setupGameSize is not a mistake; it is required to pass arguments along to the script.**
216217

217-
You can either provide the width **and** height (defaults 800 and 500 respectively) and as long as they result in an aspect ratio of what's set in the script or by --aspect-ratio (default 1.6 or 16:10), or you can provide the width **or** height and the one you didn't provide will be calculated for you.
218+
You can either provide the width **and** height (defaults 800 and 500 respectively) and as long as they result in an aspect ratio of what's set in the script or by --aspect-ratio, or you can provide the width **or** height and the one you didn't provide will be calculated for you using the aspect ratio of what's set in the script or by --aspect-ratio.
219+
220+
Provide --aspect-ratio to change the desired aspect ratio (default 1.6 or 16:10). The script checks to make sure the width and height match the aspect ratio so you get warned early about an incorrect dimension (maximum precision of 3 decimal places).
218221

219222
Providing --scale-mode will set this.game.scale.scaleMode to the corresponding Phaser.ScaleManager.SCALE_MODE (default USER_SCALE).
220223

package-lock.json

Lines changed: 29 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "phaser-npm-webpack-typescript-starter-project",
33
"productName": "phaser-npm-webpack-typescript-starter-project",
4-
"version": "1.10.0",
4+
"version": "1.11.0",
55
"main": "electron-main.js",
66
"scripts": {
77
"webpack:dev": "webpack --config webpack.dev.config.js --progress --colors",
@@ -41,6 +41,7 @@
4141
"expose-loader": "^0.7.5",
4242
"file-loader": "^2.0.0",
4343
"html-webpack-plugin": "^3.2.0",
44+
"imagejs": "^0.0.9",
4445
"npm-check": "^5.9.0",
4546
"phaser-ce": "^2.11.1",
4647
"pngjs-image": "^0.11.7",

scripts/setupGameSize.js

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
var PNGImage = require('pngjs-image');
2+
var ImageJS = require('imagejs');
23
var commander = require('commander');
34
var shell = require('shelljs');
45

6+
var filename = './assets/images/background_template.png';
57
var defaultWidth = 800;
68
var defaultHeight = 500;
79
var defaultAspectRatio = 1.6;
@@ -29,6 +31,8 @@ var baseWidth = Math.round(commander.width);
2931
var baseHeight = Math.round(commander.height);
3032
var maxWidth = baseWidth;
3133
var maxHeight = baseHeight;
34+
var midHeight = -1;
35+
var isPortrait = false;
3236
var scaleMode = commander.scaleMode;
3337

3438
if (scaleMode === null) {
@@ -58,22 +62,45 @@ if (scaleMode === 'USER_SCALE') {
5862
baseWidth = Math.round(baseHeight * aspectRatio);
5963
} else if (baseHeight === -1) {
6064
baseHeight = Math.round(baseWidth / aspectRatio);
61-
} else if (baseWidth < baseHeight) {
65+
}
66+
67+
if (baseWidth < baseHeight) {
6268
var temp = baseHeight;
6369
baseHeight = baseWidth;
6470
baseWidth = temp;
71+
72+
isPortrait = true;
6573
}
6674

67-
var providedAspectRatio = parseFloat((baseWidth / baseHeight).toFixed(2));
75+
var providedAspectRatio = parseFloat((baseWidth / baseHeight).toFixed(3));
76+
if (aspectRatio < 1) {
77+
aspectRatio = parseFloat((baseWidth / baseHeight).toFixed(3));
78+
}
6879
if (providedAspectRatio !== aspectRatio) {
6980
throw 'Base width and height must result in a ' + aspectRatio + ' aspect ratio (width / height).\nYou only need to provide either width or height and the other will be calculated for you.';
7081
}
7182

83+
var iPhone4Resolution = {
84+
width: 960,
85+
height: 640
86+
};
87+
88+
var iPhone5Resolution = {
89+
width: 1136,
90+
height: 640
91+
}
92+
93+
var iPadResolution = {
94+
width: 1024,
95+
height: 768
96+
}
97+
7298
// Calculated based of the long and narrow (aspect ratio wise) iOS device, the iPhone 5 (1136 x 640)
73-
maxWidth = Math.round(1136 * (baseHeight / 640));
99+
maxWidth = Math.round(iPhone5Resolution.width * (baseHeight / iPhone5Resolution.height));
74100
// Calculated based of the short and wide (aspect ratio wise) iOS device, the iPad (1024 x 768)
75-
maxHeight = Math.round(768 * (baseWidth / 1024));
76-
var midHeight = Math.round(640 * (baseWidth / 960));
101+
maxHeight = Math.round(iPadResolution.height * (baseWidth / iPadResolution.width));
102+
// Calculated based of the middle (aspect ratio wise) iOS device, the iPhone 4 (960 x 640)
103+
midHeight = Math.round(iPhone4Resolution.height * (baseWidth / iPhone4Resolution.width));
77104

78105
image = PNGImage.createImage(maxWidth, maxHeight);
79106

@@ -112,10 +139,31 @@ if (scaleMode === 'USER_SCALE') {
112139
maxHeight = baseHeight;
113140
}
114141

142+
if (baseWidth < baseHeight) {
143+
var temp = baseHeight;
144+
baseHeight = baseWidth;
145+
baseWidth = temp;
146+
147+
maxWidth = baseWidth;
148+
maxHeight = baseHeight;
149+
150+
isPortrait = true;
151+
}
152+
115153
image = PNGImage.createImage(maxWidth, maxHeight);
116154
image.fillRect(0, 0, maxWidth, maxHeight, greenColor);
117155
}
118156

157+
if (isPortrait) {
158+
var temp = baseHeight;
159+
baseHeight = baseWidth;
160+
baseWidth = temp;
161+
162+
var temp = maxHeight;
163+
maxHeight = maxWidth;
164+
maxWidth = temp;
165+
}
166+
119167
shell.ls('webpack.*.config.js').forEach(function (file) {
120168
shell.sed('-i', /\/\*\[\[DEFAULT_GAME_WIDTH\*\/\S*\/\*DEFAULT_GAME_WIDTH\]\]\*\//, '/*[[DEFAULT_GAME_WIDTH*/' + baseWidth + '/*DEFAULT_GAME_WIDTH]]*/', file);
121169
shell.sed('-i', /\/\*\[\[DEFAULT_GAME_HEIGHT\*\/\S*\/\*DEFAULT_GAME_HEIGHT\]\]\*\//, '/*[[DEFAULT_GAME_HEIGHT*/' + baseHeight + '/*DEFAULT_GAME_HEIGHT]]*/', file);
@@ -132,9 +180,13 @@ shell.ls('electron-main.js').forEach(function (file) {
132180
if (!commander.noPng) {
133181
shell.mkdir('-p', 'assets/images/');
134182

135-
image.writeImage('./assets/images/background_template.png', function (error) {
136-
if (error) {
137-
throw error;
183+
image.writeImage(filename, function (error) {
184+
if (!error && isPortrait) {
185+
var bitmap = new ImageJS.Bitmap();
186+
bitmap.readFile(filename).then(function() {
187+
var rotatedBitmap = bitmap.rotate({ degrees: 90, fit: "custom", width: maxWidth, height: maxHeight });
188+
rotatedBitmap.writeFile(filename);
189+
});
138190
}
139191
});
140192
}

src/app.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ function startApp(): void {
2727
let gameHeight: number = DEFAULT_GAME_HEIGHT;
2828

2929
if (SCALE_MODE === 'USER_SCALE') {
30-
let screenMetrics: Utils.ScreenMetrics = Utils.ScreenUtils.calculateScreenMetrics(gameWidth, gameHeight);
30+
let screenMetrics: Utils.ScreenMetrics = Utils.ScreenUtils.calculateScreenMetrics(gameWidth, gameHeight, MAX_GAME_WIDTH, MAX_GAME_HEIGHT);
3131

3232
gameWidth = screenMetrics.gameWidth;
3333
gameHeight = screenMetrics.gameHeight;

src/states/boot.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ export default class Boot extends Phaser.State {
3030
// Any desktop specific stuff here
3131
} else {
3232
// Any mobile specific stuff here
33-
34-
// Comment the following and uncomment the line after that to force portrait mode instead of landscape
35-
this.game.scale.forceOrientation(true, false);
36-
// this.game.scale.forceOrientation(false, true);
3733
}
3834

3935
// Use DEBUG to wrap code that should only be included in a DEBUG build of the game

src/utils/utils.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ export class ScreenMetrics {
3636
export class ScreenUtils {
3737
public static screenMetrics: ScreenMetrics;
3838

39-
public static calculateScreenMetrics(defaultWidth: number, defaultHeight: number, orientation: ScreenOrientation = ScreenOrientation.LANDSCAPE, maxGameWidth?: number, maxGameHeight?: number): ScreenMetrics {
39+
public static calculateScreenMetrics(defaultWidth: number, defaultHeight: number, maxGameWidth?: number, maxGameHeight?: number): ScreenMetrics {
4040
// Just to give some explanation as to the numbers and colors in the included background;
4141
// The GREEN is the safe area and will be displayed fully on any device and is based on 16:10 aspect ratio, build your actual gameplay here
4242
// The YELLOW is the extra area that will be visible on devices with a 3:2 aspect ratio (iPhone 4S and below)
43-
// The BLUE is the extra area that will be visible on devices with a 4:3 aspect ratio (iPads)
44-
// The RED is the extra area that will be visible on devices with a 16:9 aspect ratio (iPhone 5 and above) (this is probably the most common ratio overall...)
43+
// The RED is the extra area that will be visible on devices with a 4:3 aspect ratio (iPads)
44+
// The BLUE is the extra area that will be visible on devices with a 16:9 aspect ratio (iPhone 5 and above) (this is probably the most common ratio overall...)
4545
// The GREY area will most likely never be seen, unless some device has a really odd aspect ratio (and with Android, I wouldn't be surprised if there is a few out there)
4646

4747
this.screenMetrics = new ScreenMetrics();
@@ -52,6 +52,8 @@ export class ScreenUtils {
5252
this.screenMetrics.defaultGameWidth = defaultWidth;
5353
this.screenMetrics.defaultGameHeight = defaultHeight;
5454

55+
let orientation: ScreenOrientation = ((this.screenMetrics.defaultGameWidth < this.screenMetrics.defaultGameHeight) ? ScreenOrientation.PORTRAIT : ScreenOrientation.LANDSCAPE);
56+
5557
// Swap width and height if necessary to match the specified orientation
5658
let dimensionsOppositeForLandscape: boolean = ((this.screenMetrics.windowWidth < this.screenMetrics.windowHeight) && orientation === ScreenOrientation.LANDSCAPE);
5759
let dimensionsOppositeForPortrait: boolean = ((this.screenMetrics.windowHeight < this.screenMetrics.windowWidth) && orientation === ScreenOrientation.PORTRAIT);
@@ -62,19 +64,14 @@ export class ScreenUtils {
6264

6365
// Calculate the max width and max height if not provided; ratios are based off iPad (4:3) and iPhone 5+ (16:9) as the extremes in both width and height
6466
if (!maxGameWidth || !maxGameHeight) {
65-
if (orientation === ScreenOrientation.LANDSCAPE) {
66-
this.screenMetrics.maxGameWidth = Math.round(this.screenMetrics.defaultGameWidth * (MAX_GAME_WIDTH / DEFAULT_GAME_WIDTH));
67-
this.screenMetrics.maxGameHeight = Math.round(this.screenMetrics.defaultGameHeight * (MAX_GAME_HEIGHT / DEFAULT_GAME_HEIGHT));
68-
} else {
69-
this.screenMetrics.maxGameWidth = Math.round(this.screenMetrics.defaultGameWidth * (MAX_GAME_HEIGHT / DEFAULT_GAME_HEIGHT));
70-
this.screenMetrics.maxGameHeight = Math.round(this.screenMetrics.defaultGameHeight * (MAX_GAME_WIDTH / DEFAULT_GAME_WIDTH));
71-
}
67+
this.screenMetrics.maxGameWidth = Math.round(this.screenMetrics.defaultGameWidth * (MAX_GAME_WIDTH / DEFAULT_GAME_WIDTH));
68+
this.screenMetrics.maxGameHeight = Math.round(this.screenMetrics.defaultGameHeight * (MAX_GAME_HEIGHT / DEFAULT_GAME_HEIGHT));
7269
} else {
7370
this.screenMetrics.maxGameWidth = maxGameWidth;
7471
this.screenMetrics.maxGameHeight = maxGameHeight;
7572
}
7673

77-
let defaultAspectRatio: number = ((orientation === ScreenOrientation.LANDSCAPE) ? (DEFAULT_GAME_WIDTH / DEFAULT_GAME_HEIGHT) : (DEFAULT_GAME_HEIGHT / DEFAULT_GAME_WIDTH));
74+
let defaultAspectRatio: number = (DEFAULT_GAME_WIDTH / DEFAULT_GAME_HEIGHT);
7875
let windowAspectRatio: number = (this.screenMetrics.windowWidth / this.screenMetrics.windowHeight);
7976

8077
if (windowAspectRatio > defaultAspectRatio) {

0 commit comments

Comments
 (0)