Files
mixly3/boards/default_src/python_pyodide/others/pixi-sprite.js

664 lines
24 KiB
JavaScript

import PIXI from 'pixi.js';
import $ from 'jquery';
const mixlySprite = {
stage: new PIXI.Container(),
pointer: { x: 0, y: 0 },
backgroundSprite: null,
sprites: {},
texts: {},
counter: 0,
keys: {},
state: false,
running: false,
repeatPlay: () => { },
displayTag: false,
processingDisplayEvent: null,
successDisplayEvents: [],
successProcessingDisplayEvents: [],
startTime: performance.now(),
timer: 0,
lastFrameTime: null,
lastSecond: null,
targetFPS: 60,
frameCount: 0,
currentFPS: 60,
canvasHeight: 450,
canvasWidth: 800
};
mixlySprite.gameLoop = () => {
if (mixlySprite.state == true) {
mixlySprite.repeatPlay();
mixlySprite.gameLoopDisplay();
}
mixlySprite.timer = performance.now() - mixlySprite.startTime;
}
mixlySprite.animate = (currentTime) => {
const deltaTime = currentTime - mixlySprite.lastFrameTime;
if (deltaTime >= 1000 / mixlySprite.targetFPS) {
mixlySprite.frameCount++;
mixlySprite.gameLoop();
mixlySprite.renderer.render(mixlySprite.stage);
mixlySprite.lastFrameTime = currentTime;
}
if (currentTime - mixlySprite.lastSecond >= 1000) {
mixlySprite.currentFPS = mixlySprite.frameCount;
mixlySprite.frameCount = 0;
mixlySprite.lastSecond = currentTime;
}
requestAnimationFrame(mixlySprite.animate);
}
mixlySprite.createBackground = (img, mode = 0) => {
var player;
if (mode == 0) {
// eslint-disable-next-line new-cap
player = new PIXI.Sprite.fromImage(`../common/media/spriteimg/${img}.png`);
}
player.name = 'background';
player.anchor.set(0.5);
player.x = mixlySprite.canvasWidth / 2;
player.y = mixlySprite.canvasHeight / 2;
// const $canvas = $('#spriteContainer canvas');
// const canvasWidth = $canvas.width();
// const canvasHeight = $canvas.height();
// player.width = ($('body').width() / 2);
// player.height = ($('body').width() / 2)/canvasWidth*canvasHeight;
player.width = mixlySprite.canvasWidth;
player.height = mixlySprite.canvasHeight;
player.interactive = true;
player.buttonMode = true;
player.isDown = false;
player.isUp = true;
player.on('mousedown', function () {
this.isDown = true;
this.isUp = false;
if (mixlySprite.state) this.runningMouseDown();
})
.on('mouseup', function () {
this.isDown = false;
this.isUp = true;
})
.on('mouseupoutside', function () {
this.isDown = false;
this.isUp = true;
});
player.runningMouseDown = new Function("");
if (mixlySprite.backgroundSprite && mixlySprite.backgroundSprite.parent) {
// 如果子节点已经在父节点中,需要先移除
mixlySprite.stage.removeChild(mixlySprite.backgroundSprite);
}
mixlySprite.backgroundSprite = player;
mixlySprite.stage.addChildAt(mixlySprite.backgroundSprite, 0);
return 0;
}
mixlySprite.createASprite = (img, x = mixlySprite.canvasWidth / 2, y = mixlySprite.canvasHeight / 2, name = '', mode = 0) => {
if (name == '') {
name = 'sprite' + (++mixlySprite.counter);
}
var player;
if (mode == 0) {
// eslint-disable-next-line new-cap
player = new PIXI.Sprite.fromImage(`../common/media/spriteimg/${img}.png`);
}
if (!mixlySprite.sprites[name] && !mixlySprite.texts[name]) {
player.name = name;
player.anchor.set(0.5);
player.x = x;
player.y = y;
player.interactive = true;
player.buttonMode = true;
player.isDown = false;
player.isUp = true;
player.on('mousedown', function (event) {
this.isDown = true;
this.isUp = false;
if (!mixlySprite.state) {
this.data = event.data;
this.alpha = 0.5;
this.dragging = true;
} else this.runningMouseDown();
})
.on('mouseup', function () {
this.isDown = false;
this.isUp = true;
if (!mixlySprite.state) {
this.alpha = 1;
this.dragging = false;
this.data = null;
}
})
.on('mouseupoutside', function () {
this.isDown = false;
this.isUp = true;
if (!mixlySprite.state) {
this.alpha = 1;
this.dragging = false;
this.data = null;
}
})
.on('mousemove', function () {
if (!mixlySprite.state)
if (this.dragging) {
var newPosition = this.data.getLocalPosition(this.parent);
this.position.x = newPosition.x;
this.position.y = newPosition.y;
}
})
player.runningMouseDown = new Function("");
player.show = function () {
this.visible = true;
};
player.hide = function () {
this.visible = false;
};
player.enlarge = function (s) {
const ratio = this.height / this.width;
var measure = Math.sqrt(this.height * this.width);
measure += s;
this.width = Math.sqrt(measure * measure / ratio);
this.height = this.width * ratio;
};
player.enlargeTo = function (s) {
var ratio = this.height / this.width;
this.width = Math.sqrt(s * s / ratio);
this.height = this.width * ratio;
};
player.expandTo = async function (s, time = 1) {
if (mixlySprite.running) {
mixlySprite.displayTag = true;
mixlySprite.processingDisplayEvent = {
sprite: this,
targetS: s,
totalTime: time * 1000,
startTime: performance.now(),
displayType: 'expand'
};
var prom = new Promise((resolve) => {
if (mixlySprite.displayTag === false) {
resolve();
} else {
const checkTagInterval = setInterval(() => {
if (mixlySprite.displayTag === false) {
clearInterval(checkTagInterval);
resolve();
}
}, 10);
}
});
return await prom;
}
mixlySprite.successProcessingDisplayEvents.push({
sprite: this,
targetS: s,
totalTime: time * 1000,
startTime: performance.now(),
displayType: 'expand'
});
return 0;
};
player.move = function (step) {
this.x += step * Math.cos(this.rotation);
this.y += step * Math.sin(this.rotation);
};
player.moveTo = function (x, y) {
this.x = x;
this.y = y;
};
player.slideTo = async function (x, y, time = 1) {
if (mixlySprite.running) {
mixlySprite.displayTag = true;
mixlySprite.processingDisplayEvent = {
sprite: this,
targetX: x,
targetY: y,
totalTime: time * 1000,
startTime: performance.now(),
displayType: 'slide'
};
var prom = new Promise((resolve) => {
const checkTagInterval = setInterval(() => {
if (mixlySprite.displayTag === false) {
clearInterval(checkTagInterval);
resolve();
}
}, 10);
});
return await prom;
}
mixlySprite.successProcessingDisplayEvents.push({
sprite: this,
targetX: x,
targetY: y,
totalTime: time * 1000,
startTime: performance.now(),
displayType: 'slide'
});
return 0;
};
player.addX = function (step) {
this.x += step;
};
player.addY = function (step) {
this.y += step;
};
player.rotate = function (degree) {
this.rotation += Math.PI / 180 * degree;
};
player.rotateTo = function (degree) {
this.rotation = Math.PI / 180 * degree;
};
player.circleTo = async function (degree, time = 1) {
if (mixlySprite.running) {
mixlySprite.displayTag = true;
mixlySprite.processingDisplayEvent = {
sprite: this,
targetDegree: degree,
totalTime: time * 1000,
startTime: performance.now(),
displayType: 'circle'
};
var prom = new Promise((resolve) => {
if (mixlySprite.displayTag === false) {
resolve();
} else {
const checkTagInterval = setInterval(() => {
if (mixlySprite.displayTag === false) {
clearInterval(checkTagInterval);
resolve();
}
}, 10);
}
});
return await prom;
}
mixlySprite.successProcessingDisplayEvents.push({
sprite: this,
targetDegree: degree,
totalTime: time * 1000,
startTime: performance.now(),
displayType: 'circle'
});
return 0;
};
player.hit = function (sprite) {
return mixlySprite.hitTestRectangle(this, sprite);
};
player.outOfScreen = function () {
return this.y >= mixlySprite.renderer.height || this.y <= 0 || this.x <= 0 || this.x >= mixlySprite.renderer.width;
};
player.mouseAction = function (func) {
this.runningMouseDown = func;
};
// new
player.setScale = function (h = 0, w = 0) {
if (h == 0) h = this.height;
if (w == 0) w = this.width;
this.height = h;
this.width = w;
}
player.filterGray = function () {
const grayscaleFilter = new PIXI.filters.ColorMatrixFilter();
grayscaleFilter.blackAndWhite();
this.filters = [grayscaleFilter];
}
player.filterBrighter = function () {
const brightnessFilter = new PIXI.filters.ColorMatrixFilter();
brightnessFilter.brightness(1.25); // 增加亮度
this.filters = [brightnessFilter];
}
player.filterOrigin = function () {
this.filters = null;
}
mixlySprite.stage.addChild(player);
mixlySprite.sprites[name] = player;
}
return name;
}
mixlySprite.clearAllSprites = () => {
if (mixlySprite.backgroundSprite && mixlySprite.backgroundSprite.parent) mixlySprite.backgroundSprite.parent.removeChild(mixlySprite.backgroundSprite);
for (const name in mixlySprite.sprites) {
mixlySprite.sprites[name].parent.removeChild(mixlySprite.sprites[name]);
delete mixlySprite.sprites[name];
}
for (const name in mixlySprite.texts) {
mixlySprite.texts[name].parent.removeChild(mixlySprite.texts[name]);
delete mixlySprite.texts[name];
}
mixlySprite.counter = 0;
mixlySprite.clearTimer();
return 0;
}
mixlySprite.createText = (text, x = mixlySprite.canvasWidth / 2, y = mixlySprite.canvasHeight / 2, name = '') => {
if (name == '') {
name = 'text' + (++mixlySprite.counter);
}
if (!mixlySprite.sprites[name] && !mixlySprite.texts[name]) {
var textObj = new PIXI.Text(text);
textObj.name = name;
textObj.x = x;
textObj.y = y;
textObj.interactive = true;
textObj.buttonMode = true;
textObj.on('mousedown', function (event) {
this.isDown = true;
this.isUp = false;
if (!mixlySprite.state) {
this.data = event.data;
this.alpha = 0.5;
this.dragging = true;
} else this.runningMouseDown();
})
.on('mouseup', function () {
this.isDown = false;
this.isUp = true;
if (!mixlySprite.state) {
this.alpha = 1;
this.dragging = false;
this.data = null;
}
})
.on('mouseupoutside', function () {
this.isDown = false;
this.isUp = true;
if (!mixlySprite.state) {
this.alpha = 1;
this.dragging = false;
this.data = null;
}
})
.on('mousemove', function () {
if (!mixlySprite.state)
if (this.dragging) {
var newPosition = this.data.getLocalPosition(this.parent);
this.position.x = newPosition.x;
this.position.y = newPosition.y;
}
});
textObj.runningMouseDown = new Function("");
textObj.changeText = function (text) {
this.text = text;
};
textObj.show = function () {
this.visible = true;
};
textObj.hide = function () {
this.visible = false;
};
mixlySprite.stage.addChild(textObj);
mixlySprite.texts[name] = textObj;
}
return name;
}
mixlySprite.hitTestRectangle = (r1, r2) => {
let hit, combinedHalfWidths, combinedHalfHeights, vx, vy;
hit = false;
r1.centerX = r1.x + r1.width / 2;
r1.centerY = r1.y + r1.height / 2;
r2.centerX = r2.x + r2.width / 2;
r2.centerY = r2.y + r2.height / 2;
r1.halfWidth = r1.width / 2;
r1.halfHeight = r1.height / 2;
r2.halfWidth = r2.width / 2;
r2.halfHeight = r2.height / 2;
vx = r1.centerX - r2.centerX;
vy = r1.centerY - r2.centerY;
combinedHalfWidths = r1.halfWidth + r2.halfWidth;
combinedHalfHeights = r1.halfHeight + r2.halfHeight;
if (Math.abs(vx) < combinedHalfWidths) {
if (Math.abs(vy) < combinedHalfHeights) {
hit = true;
} else {
hit = false;
}
} else {
hit = false;
}
return hit;
};
mixlySprite.repeat = (func) => {
mixlySprite.repeatPlay = func;
}
mixlySprite.isKeyboardHit = (keyvalue) => {
if (!mixlySprite.keys[keyvalue]) {
let key = mixlySprite.keyboard(keyvalue);
mixlySprite.keys[keyvalue] = key;
}
return mixlySprite.keys[keyvalue].isDown;
}
mixlySprite.keyboardListener = (keyvalue, func) => {
if (!mixlySprite.keys[keyvalue]) {
let key = mixlySprite.keyboard(keyvalue);
key.press = function () {
if (mixlySprite.state) func();
};
mixlySprite.keys[keyvalue] = key;
} else {
mixlySprite.keys[keyvalue].press = function () {
if (mixlySprite.state) func();
};
}
}
mixlySprite.keyboard = (value) => {
let key = {};
key.value = value;
key.isDown = false;
key.isUp = true;
key.press = undefined;
key.release = undefined;
key.downHandler = event => {
if (event.key === key.value) {
if (key.isUp && key.press) key.press();
key.isDown = true;
key.isUp = false;
event.preventDefault();
}
};
key.upHandler = event => {
if (event.key === key.value) {
if (key.isDown && key.release) key.release();
key.isDown = false;
key.isUp = true;
event.preventDefault();
}
};
const downListener = key.downHandler.bind(key);
const upListener = key.upHandler.bind(key);
window.addEventListener(
"keydown", downListener, false
);
window.addEventListener(
"keyup", upListener, false
);
key.unsubscribe = () => {
window.removeEventListener("keydown", downListener);
window.removeEventListener("keyup", upListener);
};
return key;
}
mixlySprite.clearTimer = () => {
mixlySprite.startTime = performance.now();
}
mixlySprite.gameLoopDisplay = () => {
if (mixlySprite.processingDisplayEvent) {
const pSE = mixlySprite.processingDisplayEvent;
switch (pSE.displayType) {
case 'slide':
if (performance.now() >= pSE.totalTime + pSE.startTime) {
pSE.sprite.moveTo(pSE.targetX, pSE.targetY);
mixlySprite.displayTag = false;
mixlySprite.processingDisplayEvent = null;
} else {
var leftLoops = mixlySprite.currentFPS * (pSE.totalTime + pSE.startTime - performance.now()) / 1000;
if (leftLoops >= 1) {
pSE.sprite.addX((pSE.targetX - pSE.sprite.x) / leftLoops);
pSE.sprite.addY((pSE.targetY - pSE.sprite.y) / leftLoops);
}
}
break;
case 'expand':
if (performance.now() >= pSE.totalTime + pSE.startTime) {
pSE.sprite.enlargeTo(pSE.targetS);
mixlySprite.displayTag = false;
mixlySprite.processingDisplayEvent = null;
} else {
var leftLoops = mixlySprite.currentFPS * (pSE.totalTime + pSE.startTime - performance.now()) / 1000;
if (leftLoops >= 1) {
pSE.sprite.enlarge((pSE.targetS - Math.sqrt(pSE.sprite.height * pSE.sprite.width)) / leftLoops);
}
}
break;
case 'circle':
if (performance.now() >= pSE.totalTime + pSE.startTime) {
pSE.sprite.rotateTo(pSE.targetDegree);
mixlySprite.displayTag = false;
mixlySprite.processingDisplayEvent = null;
} else {
var leftLoops = mixlySprite.currentFPS * (pSE.totalTime + pSE.startTime - performance.now()) / 1000;
if (leftLoops >= 1) {
pSE.sprite.rotate((pSE.targetDegree - pSE.sprite.rotation * 180 / Math.PI) / leftLoops);
}
}
break;
}
}
if (!mixlySprite.running) {
if (mixlySprite.successProcessingDisplayEvents.length) {
for (var pSEindex = mixlySprite.successProcessingDisplayEvents.length - 1; pSEindex >= 0; pSEindex--) {
const pSE = mixlySprite.successProcessingDisplayEvents[pSEindex];
switch (pSE.displayType) {
case 'slide':
if (performance.now() >= pSE.totalTime + pSE.startTime) {
pSE.sprite.moveTo(pSE.targetX, pSE.targetY);
mixlySprite.successProcessingDisplayEvents.splice(pSEindex, 1);
} else {
var leftLoops = mixlySprite.currentFPS * (pSE.totalTime + pSE.startTime - performance.now()) / 1000;
if (leftLoops >= 1) {
pSE.sprite.addX((pSE.targetX - pSE.sprite.x) / leftLoops);
pSE.sprite.addY((pSE.targetY - pSE.sprite.y) / leftLoops);
}
}
break;
case 'expand':
if (performance.now() >= pSE.totalTime + pSE.startTime) {
pSE.sprite.enlargeTo(pSE.targetS);
mixlySprite.successProcessingDisplayEvents.splice(pSEindex, 1);
} else {
var leftLoops = mixlySprite.currentFPS * (pSE.totalTime + pSE.startTime - performance.now()) / 1000;
if (leftLoops >= 1) {
pSE.sprite.enlarge((pSE.targetS - Math.sqrt(pSE.sprite.height * pSE.sprite.width)) / leftLoops);
}
}
break;
case 'circle':
if (performance.now() >= pSE.totalTime + pSE.startTime) {
pSE.sprite.rotateTo(pSE.targetDegree);
mixlySprite.successProcessingDisplayEvents.splice(pSEindex, 1);
} else {
var leftLoops = mixlySprite.currentFPS * (pSE.totalTime + pSE.startTime - performance.now()) / 1000;
if (leftLoops >= 1) {
pSE.sprite.rotate((pSE.targetDegree - pSE.sprite.rotation * 180 / Math.PI) / leftLoops);
}
}
break;
}
}
}
}
}
mixlySprite.changeWidth = (w) => {
const $canvas = $(mixlySprite.renderer.view);
const canvasWidth = $canvas.width();
const canvasHeight = $canvas.height();
$canvas.width(w);
$canvas.height(w / canvasWidth * canvasHeight);
}
mixlySprite.kill = () => {
mixlySprite.state = false;
mixlySprite.repeatPlay = new Function();
for (let i in mixlySprite.keys) {
mixlySprite.keys[i].unsubscribe();
delete mixlySprite.keys[i];
}
mixlySprite.processingDisplayEvent = null;
mixlySprite.displayTag = false;
mixlySprite.running = false;
mixlySprite.clearTimer();
}
mixlySprite.runit = (container) => {
const $container = $(container);
$container.empty();
// Keep the scale mode to nearest
PIXI.SCALE_MODES.DEFAULT = PIXI.SCALE_MODES.NEAREST;
mixlySprite.renderer = PIXI.autoDetectRenderer(mixlySprite.canvasWidth, mixlySprite.canvasHeight, { backgroundColor: 0x00FFFFFF });
$container.append(mixlySprite.renderer.view);
// Create mixlySprite.stage container
// mixlySprite.stage = new PIXI.Container();
mixlySprite.pointer = { x: 0, y: 0 };
mixlySprite.stage.sortableChildren = true;
mixlySprite.stage.interactive = true;
mixlySprite.stage.on("mousemove", (event = PIXI.InteractionEvent) => {
mixlySprite.pointer.x = event.data.global.x;
mixlySprite.pointer.y = event.data.global.y;
});
mixlySprite.lastFrameTime = 0;
mixlySprite.running = true;
if (!mixlySprite.lastFrameTime) {
mixlySprite.lastFrameTime = performance.now();
mixlySprite.lastSecond = performance.now();
}
mixlySprite.animate(performance.now());
mixlySprite.repeatPlay = new Function();
for (let i in mixlySprite.keys) {
mixlySprite.keys[i].unsubscribe();
delete mixlySprite.keys[i];
}
if (mixlySprite.backgroundSprite) {
mixlySprite.backgroundSprite.runningMouseDown = new Function();
}
for (let i in mixlySprite.sprites) {
mixlySprite.sprites[i].runningMouseDown = new Function();
}
for (let i in mixlySprite.texts) {
mixlySprite.texts[i].runningMouseDown = new Function();
}
mixlySprite.processingDisplayEvent = null;
mixlySprite.displayTag = false;
mixlySprite.clearTimer();
mixlySprite.changeWidth($('body').width() / 2);
mixlySprite.state = true;
}
window.mixlySprite = mixlySprite;
export default mixlySprite;