Skip to content

Commit

Permalink
feat: Nine-slice Graphic (#3241)
Browse files Browse the repository at this point in the history
- Added a new `ex.NineSlice` `Graphic` for creating arbitrarily resizable rectangular regions, useful for creating UI, backgrounds, and other resizable elements.
  ```typescript
  var nineSlice = new ex.NineSlice({
    width: 300,
    height: 100,
    source: inputTile,
    sourceConfig: {
      width: 64,
      height: 64,
      topMargin: 5,
      leftMargin: 7,
      bottomMargin: 5,
      rightMargin: 7
    },
    destinationConfig: {
      drawCenter: true,
      horizontalStretch: ex.NineSliceStretch.Stretch,
      verticalStretch: ex.NineSliceStretch.Stretch
    }
  });

  actor.graphics.add(nineSlice);
  ```
  • Loading branch information
jyoung4242 authored Oct 30, 2024
1 parent 3510f93 commit c980349
Show file tree
Hide file tree
Showing 24 changed files with 1,087 additions and 50 deletions.
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,29 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Added

- Added a new `ex.NineSlice` `Graphic` for creating arbitrarily resizable rectangular regions, useful for creating UI, backgrounds, and other resizable elements.
```typescript
var nineSlice = new ex.NineSlice({
width: 300,
height: 100,
source: inputTile,
sourceConfig: {
width: 64,
height: 64,
topMargin: 5,
leftMargin: 7,
bottomMargin: 5,
rightMargin: 7
},
destinationConfig: {
drawCenter: true,
horizontalStretch: ex.NineSliceStretch.Stretch,
verticalStretch: ex.NineSliceStretch.Stretch
}
});

actor.graphics.add(nineSlice);
```
- Added a method to force graphics on screen `ex.GraphicsComponent.forceOnScreen`
- Added new `ex.Slide` scene transition, which can slide a screen shot of the current screen: `up`, `down`, `left`, or `right`. Optionally you can add an `ex.EasingFunction`, by default `ex.EasingFunctions.Linear`
```typescript
Expand Down
106 changes: 56 additions & 50 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,39 @@ process.env.CHROME_BIN = require('puppeteer').executablePath();
console.log('Chromium', process.env.CHROMIUM_BIN);

const isAppveyor = process.env.APPVEYOR_BUILD_NUMBER ? true : false;
const KarmaJasmineSeedReporter = function(baseReporterDecorator) {
const KarmaJasmineSeedReporter = function (baseReporterDecorator) {
baseReporterDecorator(this);

this.onBrowserComplete = function(browser, result) {
this.onBrowserComplete = function (browser, result) {
if (result.order && result.order.random && result.order.seed) {
this.write('\n%s: Randomized with seed %s\n', browser.name, result.order.seed);
}
};

this.onRunComplete = function() {
}
this.onRunComplete = function () {};
};

const seedReporter = {
'reporter:jasmine-seed': ['type', KarmaJasmineSeedReporter], // 1. 'jasmine-seed' is a name that can be referenced in karma.conf.js
const seedReporter = {
'reporter:jasmine-seed': ['type', KarmaJasmineSeedReporter] // 1. 'jasmine-seed' is a name that can be referenced in karma.conf.js
};

const SlowSpecsReporter = function(baseReporterDecorator) {
const SlowSpecsReporter = function (baseReporterDecorator) {
baseReporterDecorator(this);
let slowSpecs = [];
this.specSuccess = this.specFailure = function (browser, result) {
const seconds = (result.time) / 1000;
const seconds = result.time / 1000;
slowSpecs.push({
time: result.time,
name: result.fullName,
message:`Spec ${result.fullName} took ${seconds} seconds\n`
message: `Spec ${result.fullName} took ${seconds} seconds\n`
});
};

this.onBrowserComplete = function(browser, result) {
this.write('\n')
this.onBrowserComplete = function (browser, result) {
this.write('\n');
slowSpecs.sort((a, b) => {
return b.time - a.time;
})
});
for (const spec of slowSpecs.slice(0, 20)) {
let color = '\u001b[32m'; // green
let timeSeconds = spec.time/1000;
Expand All @@ -57,8 +56,8 @@ const SlowSpecsReporter = function(baseReporterDecorator) {
};
};
const timingReporter = {
'reporter:jasmine-slow': ['type', SlowSpecsReporter], // 1.
}
'reporter:jasmine-slow': ['type', SlowSpecsReporter] // 1.
};

const TimeoutSpecsReporter = function(baseReporterDecorator, logger, emitter) {
baseReporterDecorator(this);
Expand All @@ -78,6 +77,10 @@ const timeoutReporter = {

module.exports = (config) => {
config.set({
browserConsoleLogOptions: {
terminal: true,
level: ''
},
singleRun: true,
frameworks: ['jasmine', 'webpack'],
plugins: [
Expand All @@ -101,20 +104,20 @@ module.exports = (config) => {
},
proxies: {
// smooths over loading files because karma prepends '/base/' to everything
'/src/' : '/base/src/'
'/src/': '/base/src/'
},
files: [
'src/spec/_boot.ts',
{ pattern: 'src/spec/images/**/*.mp3', included: false, served: true },
{ pattern: 'src/spec/images/**/*.ogg', included: false, served: true },
{ pattern: 'src/spec/images/**/*.svg', included: false, served: true },
{ pattern: 'src/spec/images/**/*.png', included: false, served: true },
{ pattern: 'src/spec/images/**/*.gif', included: false, served: true },
{ pattern: 'src/spec/images/**/*.txt', included: false, served: true },
{ pattern: 'src/spec/images/**/*.css', included: false, served: true },
{ pattern: 'src/spec/images/**/*.woff2', included: false, served: true },
{ pattern: 'src/spec/fonts/**/*.ttf', included: false, served: true },
],
files: [
'src/spec/_boot.ts',
{ pattern: 'src/spec/images/**/*.mp3', included: false, served: true },
{ pattern: 'src/spec/images/**/*.ogg', included: false, served: true },
{ pattern: 'src/spec/images/**/*.svg', included: false, served: true },
{ pattern: 'src/spec/images/**/*.png', included: false, served: true },
{ pattern: 'src/spec/images/**/*.gif', included: false, served: true },
{ pattern: 'src/spec/images/**/*.txt', included: false, served: true },
{ pattern: 'src/spec/images/**/*.css', included: false, served: true },
{ pattern: 'src/spec/images/**/*.woff2', included: false, served: true },
{ pattern: 'src/spec/fonts/**/*.ttf', included: false, served: true }
],
mime: { 'text/x-typescript': ['ts', 'tsx'] },
preprocessors: {
'./src/spec/_boot.ts': ['webpack']
Expand All @@ -125,14 +128,14 @@ module.exports = (config) => {
resolve: {
extensions: ['.ts', '.js'],
alias: {
"@excalibur": path.resolve(__dirname, './src/engine/')
'@excalibur': path.resolve(__dirname, './src/engine/')
}
},
plugins: [
new webpack.DefinePlugin({
'process.env.__EX_VERSION': '\'test-runner\'',
'process.env.__EX_VERSION': "'test-runner'",
'process.env.NODE_ENV': JSON.stringify('test')
}),
})
],
module: {
rules: [
Expand Down Expand Up @@ -176,16 +179,13 @@ module.exports = (config) => {
}
},
webpackMiddleware: {
// webpack-dev-middleware configuration
// i. e.
stats: 'normal'
// webpack-dev-middleware configuration
// i. e.
stats: 'normal'
},
reporters: ['jasmine-order', 'progress', /*'spec'*/, 'coverage-istanbul','jasmine-seed', 'jasmine-slow', 'jasmine-timeout'],
coverageReporter: {
reporters: [
{ type: 'html', dir: 'coverage/' },
{ type: 'lcovonly', dir: 'coverage/', file: 'lcov.info' },
{ type: 'text-summary' }]
reporters: [{ type: 'html', dir: 'coverage/' }, { type: 'lcovonly', dir: 'coverage/', file: 'lcov.info' }, { type: 'text-summary' }]
},
coverageIstanbulReporter: {
// reports can be any that are listed here: https://github.com/istanbuljs/istanbuljs/tree/aae256fb8b9a3d19414dcf069c592e88712c32c6/packages/istanbul-reports/lib
Expand All @@ -195,32 +195,38 @@ module.exports = (config) => {
dir: path.join(__dirname, 'coverage')
},
browsers: ['ChromiumHeadless_with_audio'],
browserDisconnectTolerance : 1,
browserDisconnectTolerance: 1,
browserDisconnectTimeout: 60000, // appveyor is slow :(
browserNoActivityTimeout: 60000, // appveyor is slow :(
customLaunchers: {
ChromeHeadless_with_audio: {
base: 'ChromeHeadless',
flags: ['--autoplay-policy=no-user-gesture-required', '--mute-audio', '--disable-gpu', '--no-sandbox']
base: 'ChromeHeadless',
flags: ['--autoplay-policy=no-user-gesture-required', '--mute-audio', '--disable-gpu', '--no-sandbox']
},
ChromiumHeadless_with_audio: {
base: 'ChromiumHeadless',
flags: [
'--autoplay-policy=no-user-gesture-required',
'--mute-audio',
'--disable-gpu',
'--no-sandbox',
'--enable-precise-memory-info',
'--js-flags="--max_old_space_size=8192"'
]
base: 'ChromiumHeadless',
flags: [
'--autoplay-policy=no-user-gesture-required',
'--mute-audio',
'--disable-gpu',
'--no-sandbox',
'--enable-precise-memory-info',
'--js-flags="--max_old_space_size=8192"'
]
},
ChromiumHeadless_with_debug: {
base: 'ChromiumHeadless',
flags: ['--remote-debugging-port=9334', '--no-sandbox', '--disable-web-security']
},
Chromium_with_debug: {
base: 'Chromium',
flags: ['--remote-debugging-address=0.0.0.0', '--remote-debugging-port=9222', '--disable-web-security', '--mute-audio', '--no-sandbox']
flags: [
'--remote-debugging-address=0.0.0.0',
'--remote-debugging-port=9222',
'--disable-web-security',
'--mute-audio',
'--no-sandbox'
]
}
}
});
Expand Down
Binary file added sandbox/tests/9-slice/InputTile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions sandbox/tests/9-slice/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>9-Slice</title>
</head>
<body>
<script src="../../lib/excalibur.js"></script>
<script src="./index.js"></script>
</body>
</html>
35 changes: 35 additions & 0 deletions sandbox/tests/9-slice/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
var game = new ex.Engine({
width: 600,
height: 400,
displayMode: ex.DisplayMode.FitScreenAndFill,
pixelArt: true
});

var inputTile = new ex.ImageSource('./InputTile.png');

var actor = new ex.Actor({
pos: ex.vec(200, 200)
});
game.add(actor);
var nineSlice = new ex.NineSlice({
width: 300,
height: 100,
source: inputTile,
sourceConfig: {
width: 64,
height: 64,
topMargin: 5,
leftMargin: 7,
bottomMargin: 5,
rightMargin: 7
},
destinationConfig: {
drawCenter: true,
horizontalStretch: ex.NineSliceStretch.Stretch,
verticalStretch: ex.NineSliceStretch.Stretch
}
});

actor.graphics.add(nineSlice);
var loader = new ex.Loader([inputTile]);
game.start(loader).then(() => {});
Loading

0 comments on commit c980349

Please sign in to comment.