diff options
Diffstat (limited to 'objects.js')
| -rw-r--r-- | objects.js | 287 |
1 files changed, 186 insertions, 101 deletions
@@ -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) { @@ -4570,76 +4703,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(); }; |
