pxt-common-packages
Version:
Microsoft MakeCode (PXT) common packages
157 lines (145 loc) • 5.3 kB
text/typescript
namespace effects {
//% fixedInstances
export class ImageEffect implements BackgroundEffect {
// If used in an animation, this should be used as the default delay between method calls
protected preferredDelay: number;
protected effect: (image: Image, fastRandom?: Math.FastRandom) => void;
protected fastRandom: Math.FastRandom;
private times: number;
constructor(defaultRate: number, effectFactory: (image: Image, fastRandom?: Math.FastRandom) => void) {
this.effect = effectFactory;
this.fastRandom = new Math.FastRandom();
this.preferredDelay = defaultRate;
this.times = undefined;
}
/**
* Apply this effect to the image of the current sprite
* @param sprite
*/
applyTo(sprite: Sprite) {
if (!sprite || !sprite.image) return;
const clonedImage = sprite.image.clone();
this.change(clonedImage)
sprite.setImage(clonedImage);
}
/**
* Change the given image with this effect
* @param input
*/
change(input: Image) {
this.effect(input, this.fastRandom);
}
/**
* Make this effect occur repeatedly on the background image
* @param times number of times effect should occur
* @param delay delay between instances of the effect
*/
startScreenEffect(times?: number, delay?: number): void {
if (!game.currentScene().background.hasBackgroundImage()) return;
const wasRunning = this.times != undefined;
this.times = times ? times : 15;
if (!wasRunning) {
control.runInParallel(() => {
while (this.times > 0) {
this.change(scene.backgroundImage());
pause(delay ? delay : this.preferredDelay);
--this.times;
}
this.times = undefined;
});
}
}
}
//% fixedInstance whenUsed block="dissolve"
export const dissolve = new ImageEffect(100, (input: Image, r: Math.FastRandom) => {
for (let i = (input.width * input.height) >> 5; i > 0; --i) {
const x = r.randomRange(0, input.width)
const y = r.randomRange(0, input.height)
const w = r.randomRange(1, 3);
const h = r.randomRange(1, 3);
input.drawRect(x, y, w, h, 0);
}
});
//% fixedInstance whenUsed block="melt"
export const melt = new ImageEffect(125, (input: Image, r: Math.FastRandom) => {
const rounds = (input.width * input.height) >> 5;
for (let j = 0; j < rounds; ++j) {
let x = r.randomRange(0, input.width - 1)
let y = r.randomRange(0, input.height - 3)
let c = input.getPixel(x, y)
input.setPixel(x, y + 1, c)
input.setPixel(x, y + 2, c)
}
});
//% fixedInstance whenUsed block="slash"
export const slash = new ImageEffect(125, (input: Image, r: Math.FastRandom) => {
const rounds = 12;
for (let j = 0; j < rounds; ++j) {
let horizontal = r.randomBool();
let length = r.randomRange(5, 50);
let x = r.randomRange(0, input.width - (horizontal ? length : 1));
let y = r.randomRange(0, input.height - (horizontal ? 3 : length));
input.drawLine(x, y, horizontal ? x + length : x, horizontal ? y : y + length, 1);
}
});
//% fixedInstance whenUsed block="splatter"
export const splatter = new ImageEffect(125, (input: Image, r: Math.FastRandom) => {
const imgs: Image[] = [
img`
. 1 .
1 1 1
. 1 1`,
img`
. 1 1 .
1 1 1 1
. 1 1 .`,
img`
. 1 1 1 .
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
. 1 1 1 .`,
img`
. . 1 1 . .
. 1 1 1 1 .
1 1 1 1 1 1
1 1 1 1 1 1
. 1 1 1 1 .
. . 1 1 . .`,
img`
. . 1 1 1. .
. 1 1 1 1 1 .
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
. 1 1 1 1 1 .
. . 1 1 1. .`,
img`
. . 1 1 1 1 . .
. 1 1 1 1 1 1 .
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
. 1 1 1 1 1 1 .
. . 1 1 1 1 . .`,
img`
. . . 1 1 1 . . .
. . 1 1 1 1 1 . .
. 1 1 1 1 1 1 1 .
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
. 1 1 1 1 1 1 1 .
. . 1 1 1 1 1 . .
. . . 1 1 1 . . .`,
];
const rounds = 12;
for (let j = 0; j < rounds; ++j) {
const im = imgs[r.randomRange(0, imgs.length - 1)];
const x = r.randomRange(0, input.width - im.width / 2);
const y = r.randomRange(0, input.height - im.height / 2);
input.drawTransparentImage(im, x, y);
}
});
}