kopia lustrzana https://github.com/backface/turtlestitch
optimized color collision detection
rodzic
57010f6894
commit
2ff0b557ac
|
@ -3,11 +3,13 @@
|
|||
## in development:
|
||||
* **New Features:**
|
||||
* **Notable Changes:**
|
||||
* optimized color collision detection
|
||||
* **Notable Fixes:**
|
||||
* **Translation Updates:**
|
||||
|
||||
### 2019-11-29
|
||||
* new dev version
|
||||
* objects, threads: optimized color collision detection
|
||||
|
||||
## v5.3.7:
|
||||
* **Notable Fixes:**
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
<script type="text/javascript" src="src/morphic.js?version=2019-11-12"></script>
|
||||
<script type="text/javascript" src="src/widgets.js?version=2019-10-16"></script>
|
||||
<script type="text/javascript" src="src/blocks.js?version=2019-11-12"></script>
|
||||
<script type="text/javascript" src="src/threads.js?version=2019-11-19"></script>
|
||||
<script type="text/javascript" src="src/objects.js?version=2019-11-15"></script>
|
||||
<script type="text/javascript" src="src/threads.js?version=2019-11-29"></script>
|
||||
<script type="text/javascript" src="src/objects.js?version=2019-11-29"></script>
|
||||
<script type="text/javascript" src="src/gui.js?version=2019-11-29"></script>
|
||||
<script type="text/javascript" src="src/paint.js?version=2019-06-27"></script>
|
||||
<script type="text/javascript" src="src/lists.js?version=2019-11-15"></script>
|
||||
|
|
203
src/objects.js
203
src/objects.js
|
@ -84,7 +84,7 @@ BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, BooleanSlotMorph,
|
|||
localize, TableMorph, TableFrameMorph, normalizeCanvas, VectorPaintEditorMorph,
|
||||
HandleMorph, AlignmentMorph, Process, XML_Element, WorldMap, copyCanvas*/
|
||||
|
||||
modules.objects = '2019-November-15';
|
||||
modules.objects = '2019-November-29';
|
||||
|
||||
var SpriteMorph;
|
||||
var StageMorph;
|
||||
|
@ -890,29 +890,6 @@ SpriteMorph.prototype.initBlocks = function () {
|
|||
category: 'sensing',
|
||||
spec: 'color %clr is touching %clr ?'
|
||||
},
|
||||
colorFiltered: {
|
||||
dev: true,
|
||||
type: 'reporter',
|
||||
category: 'sensing',
|
||||
spec: 'filter %clr tolerance %n %',
|
||||
defaults: [null, 15]
|
||||
},
|
||||
reportFuzzyTouchingColor: {
|
||||
dev: true,
|
||||
only: SpriteMorph,
|
||||
type: 'predicate',
|
||||
category: 'sensing',
|
||||
spec: 'touching %clr tolerance %n ?',
|
||||
defaults: [null, 15]
|
||||
},
|
||||
reportFuzzyColorIsTouchingColor: {
|
||||
dev: true,
|
||||
only: SpriteMorph,
|
||||
type: 'predicate',
|
||||
category: 'sensing',
|
||||
spec: 'color %clr is touching %clr tolerance %n ?',
|
||||
defaults: [null, null, 15]
|
||||
},
|
||||
reportAspect: {
|
||||
type: 'reporter',
|
||||
category: 'sensing',
|
||||
|
@ -1980,46 +1957,6 @@ SpriteMorph.prototype.rotationCenter = function () {
|
|||
return this.position().add(this.rotationOffset);
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.colorFiltered = function (aColor, tolerance) {
|
||||
// answer a new Morph containing my image filtered by aColor
|
||||
// ignore transparency (alpha)
|
||||
var morph = new Morph(),
|
||||
ext = this.extent(),
|
||||
ctx,
|
||||
src,
|
||||
clr,
|
||||
i,
|
||||
dta;
|
||||
|
||||
src = normalizeCanvas(this.image, true).getContext('2d').getImageData(
|
||||
0,
|
||||
0,
|
||||
ext.x,
|
||||
ext.y
|
||||
);
|
||||
morph.image = newCanvas(ext, true);
|
||||
morph.bounds = this.bounds.copy();
|
||||
ctx = morph.image.getContext('2d');
|
||||
dta = ctx.createImageData(ext.x, ext.y);
|
||||
for (i = 0; i < ext.x * ext.y * 4; i += 4) {
|
||||
clr = new Color(
|
||||
src.data[i],
|
||||
src.data[i + 1],
|
||||
src.data[i + 2]
|
||||
);
|
||||
if ((tolerance && clr.isCloseTo(aColor, false, tolerance)) ||
|
||||
clr.eq(aColor)
|
||||
) {
|
||||
dta.data[i] = src.data[i];
|
||||
dta.data[i + 1] = src.data[i + 1];
|
||||
dta.data[i + 2] = src.data[i + 2];
|
||||
dta.data[i + 3] = 255;
|
||||
}
|
||||
}
|
||||
ctx.putImageData(dta, 0, 0);
|
||||
return morph;
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.getImageData = function () {
|
||||
// used for video motion detection.
|
||||
// Get sprite image data scaled to 1 an converted to ABGR array,
|
||||
|
@ -2490,9 +2427,6 @@ SpriteMorph.prototype.blockTemplates = function (category) {
|
|||
blocks.push('-');
|
||||
blocks.push(watcherToggle('reportThreadCount'));
|
||||
blocks.push(block('reportThreadCount'));
|
||||
blocks.push(block('colorFiltered'));
|
||||
blocks.push(block('reportFuzzyTouchingColor'));
|
||||
blocks.push(block('reportFuzzyColorIsTouchingColor'));
|
||||
blocks.push(block('reportStackSize'));
|
||||
blocks.push(block('reportFrameCount'));
|
||||
}
|
||||
|
@ -4294,18 +4228,80 @@ SpriteMorph.prototype.goBack = function (layers) {
|
|||
this.parent.changed();
|
||||
};
|
||||
|
||||
// SpriteMorph collision detection optimization
|
||||
// SpriteMorph collision detection
|
||||
|
||||
SpriteMorph.prototype.reportTouchingColor = function (aColor) {
|
||||
var stage = this.parentThatIsA(StageMorph),
|
||||
data, len, i;
|
||||
|
||||
if (stage) {
|
||||
if (this.wantsRedraw && this.isWarped) {
|
||||
this.endWarp();
|
||||
this.startWarp();
|
||||
}
|
||||
data = this.overlappingPixels(stage);
|
||||
if (!data) {return false; }
|
||||
len = data[0].length;
|
||||
for (i = 3; i < len; i += 4) {
|
||||
if (data[0][i] && data[1][i]) {
|
||||
if (
|
||||
data[1][i - 3] === aColor.r &&
|
||||
data[1][i - 2] === aColor.g &&
|
||||
data[1][i - 1] === aColor.b
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.reportColorIsTouchingColor = function (
|
||||
thisColor,
|
||||
thatColor
|
||||
) {
|
||||
var stage = this.parentThatIsA(StageMorph),
|
||||
data, len, i;
|
||||
|
||||
if (stage) {
|
||||
if (this.wantsRedraw && this.isWarped) {
|
||||
this.endWarp();
|
||||
this.startWarp();
|
||||
}
|
||||
data = this.overlappingPixels(stage);
|
||||
if (!data) {return false; }
|
||||
len = data[0].length;
|
||||
for (i = 3; i < len; i += 4) {
|
||||
if (data[0][i] && data[1][i]) {
|
||||
if (
|
||||
data[0][i - 3] === thisColor.r &&
|
||||
data[0][i - 2] === thisColor.g &&
|
||||
data[0][i - 1] === thisColor.b &&
|
||||
data[1][i - 3] === thatColor.r &&
|
||||
data[1][i - 2] === thatColor.g &&
|
||||
data[1][i - 1] === thatColor.b
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.overlappingPixels = function (otherSprite) {
|
||||
// overrides method from Morph because Sprites aren't nested Morphs
|
||||
var oRect = this.bounds.intersect(otherSprite.bounds),
|
||||
thisImg = this.image,
|
||||
thatImg = otherSprite.image;
|
||||
|
||||
if (oRect.width() < 1 || oRect.height() < 1 ||
|
||||
!this.image || !otherSprite.image ||
|
||||
!this.image.width || !this.image.height ||
|
||||
!otherSprite.image.width || !otherSprite.image.height
|
||||
|
||||
if (otherSprite instanceof StageMorph) {
|
||||
// only check for color collision
|
||||
thatImg = otherSprite.thumbnail(otherSprite.extent(), this, true);
|
||||
}
|
||||
if (oRect.width() < 1 || oRect.height() < 1 || !thisImg || !thatImg ||
|
||||
!thisImg.width || !thisImg.height || !thatImg.width || !thatImg.height
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
@ -7675,52 +7671,6 @@ StageMorph.prototype.clearProjectionLayer = function () {
|
|||
this.changed();
|
||||
};
|
||||
|
||||
StageMorph.prototype.colorFiltered = function (
|
||||
aColor,
|
||||
excludedSprite,
|
||||
tolerance
|
||||
) {
|
||||
// answer a new Morph containing my image filtered by aColor
|
||||
// ignore the excludedSprite, because its collision is checked
|
||||
// ignore transparency (alpha)
|
||||
var morph = new Morph(),
|
||||
ext = this.extent(),
|
||||
img = this.thumbnail(ext, excludedSprite),
|
||||
ctx,
|
||||
src,
|
||||
clr,
|
||||
i,
|
||||
dta;
|
||||
|
||||
src = normalizeCanvas(img, true).getContext('2d').getImageData(
|
||||
0,
|
||||
0,
|
||||
ext.x,
|
||||
ext.y
|
||||
);
|
||||
morph.bounds = this.bounds.copy();
|
||||
morph.image = newCanvas(ext, true);
|
||||
ctx = morph.image.getContext('2d');
|
||||
dta = ctx.createImageData(ext.x, ext.y);
|
||||
for (i = 0; i < ext.x * ext.y * 4; i += 4) {
|
||||
clr = new Color(
|
||||
src.data[i],
|
||||
src.data[i + 1],
|
||||
src.data[i + 2]
|
||||
);
|
||||
if ((tolerance && clr.isCloseTo(aColor, false, tolerance)) ||
|
||||
clr.eq(aColor)
|
||||
) {
|
||||
dta.data[i] = src.data[i];
|
||||
dta.data[i + 1] = src.data[i + 1];
|
||||
dta.data[i + 2] = src.data[i + 2];
|
||||
dta.data[i + 3] = 255;
|
||||
}
|
||||
}
|
||||
ctx.putImageData(dta, 0, 0);
|
||||
return morph;
|
||||
};
|
||||
|
||||
// StageMorph video capture
|
||||
|
||||
StageMorph.prototype.startVideo = function() {
|
||||
|
@ -8570,7 +8520,6 @@ StageMorph.prototype.blockTemplates = function (category) {
|
|||
blocks.push('-');
|
||||
blocks.push(watcherToggle('reportThreadCount'));
|
||||
blocks.push(block('reportThreadCount'));
|
||||
blocks.push(block('colorFiltered'));
|
||||
blocks.push(block('reportStackSize'));
|
||||
blocks.push(block('reportFrameCount'));
|
||||
}
|
||||
|
@ -8843,18 +8792,20 @@ StageMorph.prototype.edit = SpriteMorph.prototype.edit;
|
|||
|
||||
// StageMorph thumbnail
|
||||
|
||||
StageMorph.prototype.thumbnail = function (extentPoint, excludedSprite) {
|
||||
/*
|
||||
answer a new Canvas of extentPoint dimensions containing
|
||||
my thumbnail representation keeping the originial aspect ratio
|
||||
*/
|
||||
StageMorph.prototype.thumbnail = function (
|
||||
extentPoint,
|
||||
excludedSprite,
|
||||
nonRetina
|
||||
) {
|
||||
// answer a new Canvas of extentPoint dimensions containing
|
||||
// my thumbnail representation keeping the originial aspect ratio
|
||||
var myself = this,
|
||||
src = this.image,
|
||||
scale = Math.min(
|
||||
(extentPoint.x / src.width),
|
||||
(extentPoint.y / src.height)
|
||||
),
|
||||
trg = newCanvas(extentPoint),
|
||||
trg = newCanvas(extentPoint, nonRetina),
|
||||
ctx = trg.getContext('2d'),
|
||||
fb,
|
||||
fimg;
|
||||
|
|
|
@ -61,7 +61,7 @@ StageMorph, SpriteMorph, StagePrompterMorph, Note, modules, isString, copy,
|
|||
isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph, Color,
|
||||
TableFrameMorph, ColorSlotMorph, isSnapObject, Map, newCanvas, Symbol*/
|
||||
|
||||
modules.threads = '2019-November-19';
|
||||
modules.threads = '2019-November-29';
|
||||
|
||||
var ThreadManager;
|
||||
var Process;
|
||||
|
@ -4053,66 +4053,6 @@ Process.prototype.objectTouchingObject = function (thisObj, name) {
|
|||
);
|
||||
};
|
||||
|
||||
Process.prototype.reportTouchingColor = function (aColor, tolerance) {
|
||||
// also check for any parts (subsprites)
|
||||
var thisObj = this.blockReceiver(),
|
||||
stage;
|
||||
|
||||
if (thisObj) {
|
||||
stage = thisObj.parentThatIsA(StageMorph);
|
||||
if (stage) {
|
||||
if (thisObj.isTouching(
|
||||
stage.colorFiltered(aColor, thisObj, tolerance))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return thisObj.parts.some(
|
||||
function (any) {
|
||||
return any.isTouching(
|
||||
stage.colorFiltered(aColor, any, tolerance)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Process.prototype.reportFuzzyTouchingColor =
|
||||
Process.prototype.reportTouchingColor;
|
||||
|
||||
Process.prototype.reportColorIsTouchingColor = function (
|
||||
color1,
|
||||
color2,
|
||||
tolerance
|
||||
) {
|
||||
// also check for any parts (subsprites)
|
||||
var thisObj = this.blockReceiver(),
|
||||
stage;
|
||||
|
||||
if (thisObj) {
|
||||
stage = thisObj.parentThatIsA(StageMorph);
|
||||
if (stage) {
|
||||
if (thisObj.colorFiltered(color1, tolerance).isTouching(
|
||||
stage.colorFiltered(color2, thisObj, tolerance)
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
return thisObj.parts.some(
|
||||
function (any) {
|
||||
return any.colorFiltered(color1, tolerance).isTouching(
|
||||
stage.colorFiltered(color2, any, tolerance)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Process.prototype.reportFuzzyColorIsTouchingColor =
|
||||
Process.prototype.reportColorIsTouchingColor;
|
||||
|
||||
Process.prototype.reportAspect = function (aspect, location) {
|
||||
// sense colors and sprites anywhere,
|
||||
// use sprites to read/write data encoded in colors.
|
||||
|
|
Ładowanie…
Reference in New Issue