1
0
mirror of https://github.com/psychopy/psychojs.git synced 2025-05-10 18:50:54 +00:00

added proper dot lifecycle update for sqr and circle fields.

This commit is contained in:
lightest 2024-03-21 03:22:50 +00:00
parent 9308bacbfd
commit 1efeff268e
2 changed files with 72 additions and 22 deletions

View File

@ -149,7 +149,9 @@ async function experimentInit() {
size: [512, 512], size: [512, 512],
pos: [0, 0], pos: [0, 0],
units: "pix", units: "pix",
depth: 0 depth: 0,
dotLife: 60,
fieldShape: "circle"
}) })
); );

View File

@ -122,42 +122,93 @@ export class DotStim extends VisualStim
this.size = util.to_unit(DotStim.#DEFAULT_STIM_SIZE_PX, "pix", this.win, this.units); this.size = util.to_unit(DotStim.#DEFAULT_STIM_SIZE_PX, "pix", this.win, this.units);
} }
this._positioningFunctions = {
"sqr": this._getRandomPositionWithinSquareField,
"circle": this._getRandomPosWithinCircleField
};
this._size_px = util.to_px(this.size, this.units, this.win); this._size_px = util.to_px(this.size, this.units, this.win);
this._dotsLife = new Float32Array(nDots);
// TODO: DEBUG.
// const s = new PIXI.Sprite(PIXI.Texture.WHITE);
// s.width = this._size_px[ 0 ];
// s.height = this._size_px[ 1 ];
// s.tint = 0xff0000;
// this._pixi.addChild(s);
this._spawnDots(); this._spawnDots();
} }
_getRandomPositionWithinSquareField(fieldWidth, fieldHeight) _getRandomPositionWithinSquareField()
{ {
const x = Math.random() * fieldWidth; const fieldWidth = this._size_px[ 0 ];
const y = Math.random() * fieldHeight; const fieldHeight = this._size_px[ 1 ];
const x = Math.min(Math.random() * fieldWidth, fieldWidth - this._dotSize);
const y = Math.min(Math.random() * fieldHeight, fieldHeight - this._dotSize);
return { x, y }; return { x, y };
} }
_getRandomPosWithinCircleField(fieldRadius) _getRandomPosWithinCircleField()
{ {
const f = Math.random(); const fieldRadius = this._size_px[ 0 ] * 0.5 - this._dotSize * 0.5;
const x = Math.cos(f) * fieldRadius; const f = Math.random() * 2 * Math.PI - Math.PI;
const y = Math.sin(f) * fieldRadius; const r = Math.random();
const x = Math.cos(f) * fieldRadius * r + this._size_px[0] * 0.5;
const y = Math.sin(f) * fieldRadius * r + this._size_px[1] * 0.5;
return { x, y }; return { x, y };
} }
_configureDot()
{
const positioningFunc = this._positioningFunctions[ this._fieldShape ];
return {
position: positioningFunc.call(this),
lifetime: Math.random() * this._dotLife
};
}
_spawnDots() _spawnDots()
{ {
let i; let i;
let p;
let dot; let dot;
let dotConfig;
for (i = 0; i < this._nDots; i ++) for (i = 0; i < this._nDots; i ++)
{ {
p = this._getRandomPositionWithinSquareField(this._size_px[0], this._size_px[1]);
dot = new PIXI.Sprite(PIXI.Texture.WHITE); dot = new PIXI.Sprite(PIXI.Texture.WHITE);
dot.x = p.x; dotConfig = this._configureDot();
dot.y = p.y; dot.x = dotConfig.position.x;
dot.y = dotConfig.position.y;
dot.width = this._dotSize; dot.width = this._dotSize;
dot.height = this._dotSize; dot.height = this._dotSize;
this._pixi.addChild(dot); this._pixi.addChild(dot);
this._dotsLife[ i ] = dotConfig.lifetime;
}
}
_updateDots()
{
if (this._dotLife === 0)
{
return;
}
let dotConfig;
let i;
for (i = 0; i < this._nDots; i++)
{
this._dotsLife[ i ] = Math.max(0, this._dotsLife[ i ] - 1);
if (this._dotsLife[ i ] === 0)
{
dotConfig = this._configureDot();
this._pixi.children[ i ].x = dotConfig.position.x;
this._pixi.children[ i ].y = dotConfig.position.y;
this._dotsLife[ i ] = dotConfig.lifetime;
}
} }
} }
@ -351,8 +402,8 @@ export class DotStim extends VisualStim
if (this._pixi !== undefined) if (this._pixi !== undefined)
{ {
const anchorNum = this._anchorTextToNum(this._anchor); const anchorNum = this._anchorTextToNum(this._anchor);
this._pixi.pivot.x = anchorNum[0] * this._pixi.scale.x * this._pixi.width; this._pixi.pivot.x = anchorNum[0] * this._pixi.scale.x * this._size_px[0];
this._pixi.pivot.y = anchorNum[1] * this._pixi.scale.y * this._pixi.height; this._pixi.pivot.y = anchorNum[1] * this._pixi.scale.y * this._size_px[1];
} }
} }
@ -363,18 +414,15 @@ export class DotStim extends VisualStim
*/ */
_updateIfNeeded() _updateIfNeeded()
{ {
if (!this._needUpdate) // Always update dots.
this._updateDots();
if (!this._needPixiUpdate)
{ {
return; return;
} }
this._needUpdate = false;
// update the PIXI representation, if need be: this._needPixiUpdate = false;
if (this._needPixiUpdate)
{
this._needPixiUpdate = false;
this._size_px = util.to_px(this._size, this.units, this.win);
}
this._pixi.zIndex = -this._depth; this._pixi.zIndex = -this._depth;
this.opacity = this._opacity; this.opacity = this._opacity;