summaryrefslogtreecommitdiff
path: root/objects.js
diff options
context:
space:
mode:
Diffstat (limited to 'objects.js')
-rw-r--r--objects.js287
1 files changed, 186 insertions, 101 deletions
diff --git a/objects.js b/objects.js
index b115b3b..0276f8f 100644
--- a/objects.js
+++ b/objects.js
@@ -202,13 +202,47 @@ SpriteMorph.prototype.bubbleMaxTextWidth = 130;
SpriteMorph.prototype.initBlocks = function () {
SpriteMorph.prototype.blocks = {
+ // Map (Snap! in Your Own World)
+ userLon: {
+ type: 'reporter',
+ category: 'motion',
+ spec: 'user\'s longitude'
+ },
+ userLat: {
+ type: 'reporter',
+ category: 'motion',
+ spec: 'user\'s latitude'
+ },
+ findLocation: {
+ type: 'reporter',
+ category: 'motion',
+ spec: 'latitude, longitude of %s',
+ defaults: ['Tiergarten Berlin']
+ },
+ reportGeocode: {
+ type: 'reporter',
+ category: 'motion',
+ spec: 'address at longitude: %n latitude: %n'
+ },
+ overpassQuery: {
+ type: 'reporter',
+ category: 'sensing',
+ spec: 'overpass query %s'
+ },
+ focusMap: {
+ type: 'command',
+ category: 'motion',
+ spec: 'set focus to longitude: %n latitude: %n with zoom %n',
+ defaults: [0, 0, 12]
+ },
+
// Motion
forward: {
only: SpriteMorph,
type: 'command',
category: 'motion',
- spec: 'move %n steps',
- defaults: [10]
+ spec: 'move %n meters',
+ defaults: [2]
},
turn: {
only: SpriteMorph,
@@ -230,6 +264,12 @@ SpriteMorph.prototype.initBlocks = function () {
category: 'motion',
spec: 'point in direction %dir'
},
+ direction: {
+ only: SpriteMorph,
+ type: 'reporter',
+ category: 'motion',
+ spec: 'direction'
+ },
doFaceTowards: {
only: SpriteMorph,
type: 'command',
@@ -240,7 +280,7 @@ SpriteMorph.prototype.initBlocks = function () {
only: SpriteMorph,
type: 'command',
category: 'motion',
- spec: 'go to x: %n y: %n',
+ spec: 'go to longitude: %n latitude: %n',
defaults: [0, 0]
},
doGotoObject: {
@@ -253,35 +293,35 @@ SpriteMorph.prototype.initBlocks = function () {
only: SpriteMorph,
type: 'command',
category: 'motion',
- spec: 'glide %n secs to x: %n y: %n',
+ spec: 'glide %n secs to longitude: %n latitude: %n',
defaults: [1, 0, 0]
},
changeXPosition: {
only: SpriteMorph,
type: 'command',
category: 'motion',
- spec: 'change x by %n',
+ spec: 'change longitude by %n',
defaults: [10]
},
setXPosition: {
only: SpriteMorph,
type: 'command',
category: 'motion',
- spec: 'set x to %n',
+ spec: 'set longitude to %n',
defaults: [0]
},
changeYPosition: {
only: SpriteMorph,
type: 'command',
category: 'motion',
- spec: 'change y by %n',
+ spec: 'change latitude by %n',
defaults: [10]
},
setYPosition: {
only: SpriteMorph,
type: 'command',
category: 'motion',
- spec: 'set y to %n',
+ spec: 'set latitude to %n',
defaults: [0]
},
bounceOffEdge: {
@@ -294,19 +334,13 @@ SpriteMorph.prototype.initBlocks = function () {
only: SpriteMorph,
type: 'reporter',
category: 'motion',
- spec: 'x position'
+ spec: 'longitude'
},
yPosition: {
only: SpriteMorph,
type: 'reporter',
category: 'motion',
- spec: 'y position'
- },
- direction: {
- only: SpriteMorph,
- type: 'reporter',
- category: 'motion',
- spec: 'direction'
+ spec: 'latitude'
},
// Looks
@@ -1376,12 +1410,50 @@ SpriteMorph.prototype.init = function (globals) {
this.isDraggable = true;
this.isDown = false;
+ this.myPolylineIndex = window.polylineIndex++;
+
this.heading = 90;
this.changed();
this.drawNew();
this.changed();
};
+SpriteMorph.prototype.updateMarker = function () {
+ var myself = this;
+
+ if (!this.parent) return; // not loaded yet, xPosition is not available
+
+ if (window.spriteGroup.hasLayer(this.marker)) {
+ // if it is created the first time, it cannot be removed
+ window.spriteGroup.removeLayer(this.marker);
+ }
+ if (this.isVisible == false) return;
+
+ // create a new marker with the sprite as icon
+ this.icon = L.spriteIcon({
+ iconAnchor: [this.rotationOffset.x, this.rotationOffset.y],
+ canvas: this.image
+ });
+ // X position is longitude, Y latitude
+ this.marker = L.marker([this.yPosition(), this.xPosition()],
+ {icon: this.icon, title: this.name, draggable: this.draggable});
+
+ // add event handlers
+ this.marker.on('click', function () {
+ myself.mouseClickLeft();
+ });
+
+ // apply graphic effects that do not apply to the icon canvas
+ this.marker.setOpacity(this.alpha);
+ if (this.parent) {
+ var layer = this.parent.children.indexOf(this);
+ this.marker.setZIndexOffset(layer);
+ }
+
+ // display that marker
+ this.marker.addTo(window.spriteGroup);
+};
+
// SpriteMorph duplicating (fullCopy)
SpriteMorph.prototype.fullCopy = function () {
@@ -1430,6 +1502,8 @@ SpriteMorph.prototype.fullCopy = function () {
dp.rotatesWithAnchor = part.rotatesWithAnchor;
c.attachPart(dp);
});
+ // makes updateMarker() create a new marker
+ c.marker = null;
return c;
};
@@ -1564,6 +1638,7 @@ SpriteMorph.prototype.drawNew = function () {
}
}
this.version = Date.now();
+ this.updateMarker(); // Snap! YOW
};
SpriteMorph.prototype.endWarp = function () {
@@ -1742,6 +1817,16 @@ SpriteMorph.prototype.blockTemplates = function (category) {
}
if (cat === 'motion') {
+ blocks.push(block('userLon'));
+ blocks.push(block('userLat'));
+ blocks.push('-');
+ blocks.push(block('reportGeocode'));
+ blocks.push(block('findLocation'));
+ blocks.push('-');
+ blocks.push(block('focusMap'));
+ blocks.push('-');
+
+ blocks.push('=');
blocks.push(block('forward'));
blocks.push(block('turn'));
@@ -1759,8 +1844,6 @@ SpriteMorph.prototype.blockTemplates = function (category) {
blocks.push(block('changeYPosition'));
blocks.push(block('setYPosition'));
blocks.push('-');
- blocks.push(block('bounceOffEdge'));
- blocks.push('-');
blocks.push(watcherToggle('xPosition'));
blocks.push(block('xPosition'));
blocks.push(watcherToggle('yPosition'));
@@ -1951,6 +2034,8 @@ SpriteMorph.prototype.blockTemplates = function (category) {
blocks.push(block('doSetFastTracking'));
blocks.push('-');
blocks.push(block('reportDate'));
+ blocks.push('-');
+ blocks.push(block('overpassQuery'));
// for debugging: ///////////////
@@ -2622,7 +2707,7 @@ SpriteMorph.prototype.doSwitchToCostume = function (id) {
(id instanceof Array ? id[0] : null)
)
) {
- costume = null;
+ this.costume = null;
} else {
if (id === -1) {
this.doWearPreviousCostume();
@@ -2634,7 +2719,7 @@ SpriteMorph.prototype.doSwitchToCostume = function (id) {
if (costume === null) {
num = parseFloat(id);
if (num === 0) {
- costume = null;
+ this.costume = null;
} else {
costume = arr[num - 1] || null;
}
@@ -2773,6 +2858,7 @@ SpriteMorph.prototype.clonify = function (stage) {
SpriteMorph.prototype.removeClone = function () {
if (this.isClone) {
// this.stopTalking();
+ window.spriteGroup.removeLayer(this.marker);
this.parent.threads.stopAllForReceiver(this);
this.destroy();
this.parent.cloneCount -= 1;
@@ -2791,11 +2877,13 @@ SpriteMorph.prototype.removeClone = function () {
SpriteMorph.prototype.hide = function () {
SpriteMorph.uber.hide.call(this);
this.parts.forEach(function (part) {part.hide(); });
+ this.updateMarker();
};
SpriteMorph.prototype.show = function () {
SpriteMorph.uber.show.call(this);
this.parts.forEach(function (part) {part.show(); });
+ this.updateMarker();
};
// SpriteMorph pen color
@@ -2863,6 +2951,7 @@ SpriteMorph.prototype.comeToFront = function () {
this.parent.add(this);
this.changed();
}
+ this.updateMarker();
};
SpriteMorph.prototype.goBack = function (layers) {
@@ -2873,6 +2962,7 @@ SpriteMorph.prototype.goBack = function (layers) {
this.parent.removeChild(this);
this.parent.children.splice(layer - newLayer, null, this);
this.parent.changed();
+ this.updateMarker();
};
// SpriteMorph collision detection optimization
@@ -3143,6 +3233,9 @@ SpriteMorph.prototype.clearEffects = function () {
// SpriteMorph talk bubble
SpriteMorph.prototype.stopTalking = function () {
+ if (window.map.hasLayer(this.popup)) {
+ window.map.removeLayer(this.popup);
+ }
var bubble = this.talkBubble();
if (bubble) {bubble.destroy(); }
};
@@ -3157,6 +3250,13 @@ SpriteMorph.prototype.bubble = function (data, isThought, isQuestion) {
this.stopTalking();
if (data === '' || isNil(data)) {return; }
+
+ // Snap! YOW
+ this.popup = L.popup()
+ .setLatLng([this.yPosition(), this.xPosition()])
+ .setContent(data)
+ .addTo(window.map);
+
bubble = new SpriteBubbleMorph(
data,
stage ? stage.scale : 1,
@@ -3233,6 +3333,38 @@ SpriteMorph.prototype.drawLine = function (start, dest) {
).intersect(this.parent.visibleBounds()).spread();
if (this.isDown) {
+ var stage = this.parent;
+ var destLatLng =
+ [stage.dimensions.y / 2 - to.y, to.x - stage.dimensions.x / 2];
+
+ if (!window.polylines[this.myPolylineIndex]) {
+ // add a new line with start and end points
+ window.polylines[this.myPolylineIndex] = L.polyline([
+ [stage.dimensions.y / 2 - from.y,
+ from.x - stage.dimensions.x / 2],
+ destLatLng,
+ ],
+ {color: this.color.toString(), weight: this.size})
+ .addTo(window.penLines);
+ } else {
+ var latlngs = window.polylines[this.myPolylineIndex].getLatLngs();
+ for (var j = 0; j < latlngs.length; j++) {
+ // If a distance between two points is <= 1 meter,
+ // call them "the same"
+ if (latlngs[j].distanceTo(destLatLng) <= 1) {
+ var polyLL = window.polylines[this.myPolylineIndex]
+ .spliceLatLngs(j, latlngs.length)
+ .concat([destLatLng]);
+ L.polygon(polyLL,
+ {color: this.color.toString(), weight: this.size})
+ .addTo(window.penShapes);
+ break;
+ }
+ }
+
+ window.polylines[this.myPolylineIndex].addLatLng(destLatLng);
+ }
+
context.lineWidth = this.size;
context.strokeStyle = this.color.toString();
if (this.useFlatLineEnds) {
@@ -3268,6 +3400,9 @@ SpriteMorph.prototype.moveBy = function (delta, justMe) {
part.moveBy(delta);
});
}
+ if (!this.isDown) {
+ this.myPolylineIndex = window.polylineIndex++;
+ }
};
SpriteMorph.prototype.slideBackTo = function (situation, inSteps) {
@@ -3320,6 +3455,19 @@ SpriteMorph.prototype.nestingBounds = function () {
// SpriteMorph motion primitives
+SpriteMorph.prototype.forward = function (meters) {
+ // FIXME this is an approximation
+ var kilometers = meters / 1000;
+ var diffLat, diffLon;
+ diffLat = Math.cos(radians(this.heading)) * (1 / 110.54 * kilometers);
+ diffLon = Math.sin(radians(this.heading))
+ * (1 / (111.32 * Math.cos(radians(this.yPosition()))) * kilometers);
+
+ var diffPoint = new Point(diffLon, 0 - diffLat);
+ this.setPosition(this.position().add(diffPoint));
+ this.updateMarker();
+};
+
Morph.prototype.setPosition = function (aPoint, justMe) {
// override the inherited default to make sure my parts follow
// unless it's justMe
@@ -3329,22 +3477,6 @@ Morph.prototype.setPosition = function (aPoint, justMe) {
}
};
-SpriteMorph.prototype.forward = function (steps) {
- var dest,
- dist = steps * this.parent.scale || 0;
-
- if (dist >= 0) {
- dest = this.position().distanceAngle(dist, this.heading);
- } else {
- dest = this.position().distanceAngle(
- Math.abs(dist),
- (this.heading - 180)
- );
- }
- this.setPosition(dest);
- this.positionTalkBubble();
-};
-
SpriteMorph.prototype.setHeading = function (degrees) {
var x = this.xPosition(),
y = this.yPosition(),
@@ -3434,6 +3566,7 @@ SpriteMorph.prototype.gotoXY = function (x, y, justMe) {
}
this.setPosition(dest, justMe);
this.positionTalkBubble();
+ this.updateMarker();
};
SpriteMorph.prototype.silentGotoXY = function (x, y, justMe) {
@@ -4565,76 +4698,28 @@ StageMorph.prototype.drawNew = function () {
};
StageMorph.prototype.drawOn = function (aCanvas, aRect) {
- // make sure to draw the pen trails canvas as well
- var rectangle, area, delta, src, context, w, h, sl, st, ws, hs;
- if (!this.isVisible) {
- return null;
- }
- rectangle = aRect || this.bounds;
- area = rectangle.intersect(this.bounds).round();
- if (area.extent().gt(new Point(0, 0))) {
- delta = this.position().neg();
- src = area.copy().translateBy(delta).round();
- context = aCanvas.getContext('2d');
- context.globalAlpha = this.alpha;
-
- sl = src.left();
- st = src.top();
- w = Math.min(src.width(), this.image.width - sl);
- h = Math.min(src.height(), this.image.height - st);
-
- if (w < 1 || h < 1) {
- return null;
- }
- context.drawImage(
- this.image,
- src.left(),
- src.top(),
- w,
- h,
- area.left(),
- area.top(),
- w,
- h
- );
+ var map = document.getElementById('map');
+ ide = this.parentThatIsA(IDE_Morph);
- // pen trails
- ws = w / this.scale;
- hs = h / this.scale;
- context.save();
- context.scale(this.scale, this.scale);
- try {
- context.drawImage(
- this.penTrails(),
- src.left() / this.scale,
- src.top() / this.scale,
- ws,
- hs,
- area.left() / this.scale,
- area.top() / this.scale,
- ws,
- hs
- );
- } catch (err) { // sometimes triggered only by Firefox
- // console.log(err);
- context.restore();
- context.drawImage(
- this.penTrails(),
- 0,
- 0,
- this.dimensions.x,
- this.dimensions.y,
- this.left(),
- this.top(),
- this.dimensions.x * this.scale,
- this.dimensions.y * this.scale
- );
- }
- context.restore();
+ if (!ide.isAppMode) {
+ map.style.left = this.left() + 'px';
+ map.style.top = this.top() + 'px';
+ map.style.width = this.dimensions.x * this.scale + 'px';
+ map.style.height = this.dimensions.y * this.scale + 'px';
+ } else {
+ map.style.left = ide.left() + 'px';
+ map.style.top = this.top() + 'px';
+ map.style.width = ide.extent().x + 'px';
+ map.style.height = (ide.extent().y - this.top()) + 'px';
}
+ window.map.invalidateSize();
};
StageMorph.prototype.clearPenTrails = function () {
+ window.map.removeLayer(window.penTrails);
+ window.penTrails = L.layerGroup().addTo(window.map);
+ window.penShapes = L.layerGroup().addTo(window.penTrails);
+ window.penLines = L.layerGroup().addTo(window.penTrails);
this.trailsCanvas = newCanvas(this.dimensions);
this.changed();
};