Rotation and getBounds() in Phaser - rotation

I'm using Phaser 2.3.0 and I want to know the bounds of a rotated sprite.
But when I change sprite.rotation, the values of sprite.getBounds() don't change:
sprite = game.add.sprite(0, 0, "img"); // game.load.spritesheet("img", "grid.png", 32, 32);
console.log(sprite.getBounds()); // Object { x: 0, y: 0, width: 32, height: 32, type: 22 }
sprite.rotation = 0.52; // 30°
console.log(sprite.getBounds()); // Object { x: 0, y: 0, width: 32, height: 32, type: 22 }
What's wrong?
How can I get the correct bounds?

As far as I know, getBounds() will return the smallest possible rectangle that the object fits in and since Phaser.Rectangle doesn't have a rotation property, you will get the same rectangle both times.

It's being 6 years since this question, but just for the people who end up here after a Google search, the right answer is that the getBounds() is based on the object's worldTransform which is updated at the end of the render() cycle. So changing something in the object and in the next line trying to get its bounds will give you the old value. The solution is to wait a frame or call updateTransform():
const sprite = game.add.sprite(0, 0, "img");
console.log(sprite.getBounds());
// Phaser.Rectangle { x: 0, y: 0, width: 32, height: 32, type: 22 }
sprite.rotation = 0.52; // 30°
sprite.updateTransform();
console.log(sprite.getBounds());
// Phaser.Rectangle {x: -15.900164410999576, y: 0, width: 43.67037816068437, height: 43.67037816068437, type: 22}
https://photonstorm.github.io/phaser-ce/Phaser.Sprite.html#getBounds
Keep in mind that if the object is inside an hierarchy of objects, you should call updateTransform() in the highest object.

Related

why does this code add dummy DOM element for animating an three object along a path?

I'm trying to move objects along side a path in three.js.
I could find an example from gsap website and the code is doing something that I don't understand.
See the code below.
var path = [{x: 0, y: 0, z: -100}, {x: 100, y: 200, z: -200}, {x: 200, y: 200, z: -50}, {x: 240, y: 100, z: -250}];
var proxy = document.createElement("p");
console.log(proxy)
gsap.to(proxy, {
duration: 10,
repeat: -1,
motionPath: {
path, // equivalent to path: path
autoRotate: true,
useRadians: true
},
onUpdate: updateMesh
});
It created a dummy DOM element (I guess, which is called 'proxy' here).
and animates the three mesh object following the path as below.
var setX = gsap.quickSetter(cube.position, "x");
var setY = gsap.quickSetter(cube.position, "y");
var setZ = gsap.quickSetter(cube.position, "z");
var setRot = gsap.quickSetter(cube.rotation, "z");
function updateMesh() {
setX(gsap.getProperty(proxy, "x"));
setY(gsap.getProperty(proxy, "y"));
setZ(gsap.getProperty(proxy, "z"));
setRot(gsap.getProperty(proxy, "rotation"));
}
Why does this create a dummy DOM element? which seems quite weird to me.
Is there any better way to achieve this?
The original code is in the following link.
https://codepen.io/GreenSock/pen/ZEGxzvJ?editors=1111
As the original creator of that pen and the post it comes from, I believe that I used a proxy element because MotionPathPlugin doesn't work with straight WebGL objects (yet). So to make use of the plugin's super handy functionality, I created a "proxy" element that is not rendered to the page and applied it to that. Then transferred the values to the WebGL object.

Threebox Tooltip in 3D models

I´ve been trying to enable tooltips on some imported 3D models, but it isnt working.
I already enabled tooltips in threbox, and I enabled tooltips in the options for the 3d element, as shown below.
tb = new Threebox(
map,
mbxContext,
{
realSunlight: true,
enableSelectingFeatures: true, //change this to false to disable fill-extrusion features selection
enableTooltips: true // change this to false to disable default tooltips on fill-extrusion and 3D models
}
);
var proptions = {
obj: './models/er.glb',
type: 'gltf',
scale: 10,
units: 'meters',
rotation: { x: 90, y: 0, z: 0 }, //default rotation
anchor: 'center',
adjustment: { x: 0, y: 0, z: 0.4 },
enableToltips: true
}
When i load the object i did the following:
tb.loadObj(proptions, function (model) {
model.setCoords(place);
model.addTooltip("A radar in the middle of nowhere", true);
model.setRotation({ x: 0, y: 0, z: Math.floor(Math.random() * 100) })
tb.add(model);
});
Although the object appears in the render, when I put the mouse above or i click it nothing shows the tooltip.
What am I missing ?
EDIT:
Following #jscastro response i changed the import in the top of my html page to <link href="./threebox-plugin/examples/css/threebox.css" rel="stylesheet" /> (the path is the correct to where the file is)
I also removed the enableTooltip: true in proptions.
Despite that it still does not work, Below i will leave the code as it is:
var origin = [-8.4, 41.20, 1];
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: origin,
zoom: 11,
pitch: 30,
antialias: true
});
//Things related to dateTime ommited
window.tb = new Threebox(
map,
map.getCanvas().getContext('webgl'),
{
realSunlight: true,
enableSelectingFeatures: true, //change this to false to disable fill-extrusion features selection
enableTooltips: true // change this to false to disable default tooltips on fill-extrusion and 3D models
}
);
map.on('style.load', async function () {
await importarLinhas();
// stats
// stats = new Stats();
// map.getContainer().appendChild(stats.dom);
animate();
map.addLayer({
id: 'custom_layer',
type: 'custom',
renderingMode: '3d',
onAdd: function (map, mbxContext) {
var eroptions = {
obj: './models/stationBus.fbx',
type: 'fbx',
scale: 0.01,
units: 'meters',
rotation: { x: 90, y: 20, z: 0 }, //default rotation
anchor: 'center',
adjustment: { x: -0.1, y: -0.1, z: 0.4 }
}
var poptions = {
obj: './models/Busstop.fbx',
type: 'fbx',
scale: 0.03,
units: 'meters',
rotation: { x: 90, y: 20, z: 0 }, //default rotation
anchor: 'center',
adjustment: { x: -0.1, y: -0.1, z: 0.1 }
}
var proptions = {
obj: './models/er.glb',
type: 'gltf',
scale: 2.7,
units: 'meters',
rotation: { x: 90, y: 0, z: 0 }, //default rotation
anchor: 'center',
adjustment: { x: 0, y: 0, z: 0.4 }
}
allNos.forEach((element) => { //For each one of a list that i fill first
//center of where the objects are
var place = [element.lng, element.lat, 0];
//cylinder as "base" for each one of the 3d Models
**//in here i cant do the Tooltip for the object**
const geometry = new THREE.CylinderGeometry(0.6, 0.6, 0.15, 32);
const material = new THREE.MeshLambertMaterial({ color: 0x5B5B5B });
const cylinder = new THREE.Mesh(geometry, material);
var baseOptions = {
obj: cylinder,
anchor: 'center',
adjustment: { x: 0, y: 0, z: -0.4 }
}
let base = tb.Object3D(baseOptions);
base.setCoords(place);
base.setRotation({ x: 90, y: 0, z: 0 })
//The text is just for the test
base.addTooltip("A radar in the middle of nowhere", true);
// base.castShadow = true;
window.tb.add(base);
//next i check what type of element it is
//it can only be one at the same time, so i use different models for each type
if (element.tipo === "p") {
window.tb.loadObj(poptions, function (model) {
model.setCoords(place);
model.addTooltip("A radar in the middle of nowhere", true);
model.setRotation({ x: 0, y: 0, z: Math.floor(Math.random() * 100) })
// model.castShadow = true;
window.tb.add(model);
});
}
if (element.tipo === "er") {
window.tb.loadObj(eroptions, function (model) {
model.setCoords(place);
model.addTooltip("A radar in the middle of nowhere", true);
model.setRotation({ x: 0, y: 0, z: Math.floor(Math.random() * 100) })
// model.castShadow = true;
window.tb.add(model);
});
}
if (element.tipo === "pr") {
window.tb.loadObj(proptions, function (model) {
model.setCoords(place);
model.addTooltip("A radar in the middle of nowhere", true);
model.setRotation({ x: 0, y: 0, z: Math.floor(Math.random() * 100) })
// model.castShadow = true;
window.tb.add(model);
});
}
});
},
render: function (gl, matrix) {
window.tb.setSunlight(date, origin.center);
window.tb.update();
}
})
map.addLayer(createCompositeLayer());
map.on('SelectedFeatureChange', onSelectedFeatureChange);
});
EDIT
I downloaded the page you shared in the chat, and I found many different issues and mistakes in your code.
1. You're using the wrong property to enable the selection of 3D objects, you use enableSelectingFeatures: true, //change this to false to disable fill-extrusion features selection, that is for Mapbox fill-extrusions features as said in the comment, but not for 3D models and objects, you have to use enableSelectingObjects: true. Only adding this, your problem with the tooltips on mouse over will be solved.
tb = new Threebox(
map,
mbxContext,
{
realSunlight: true,
enableSelectingObjects: true, //enable 3D models over/selection
enableTooltips: true // enable default tooltips on fill-extrusion and 3D models
}
);
But I have found other issues...
2. Your models scale initialization is too small, so you are hiding them below the big shapes you have created. The scale of your bus stop is scale: 0.01 and you define a place which is on the ground var place = [element.lng, element.lat, 0];, so it's hidden inside this CylinderGeometry
If you use scale: 1 you will see how your bus stops raises from the cylinder.
3. Same with the bus, you initialize them with scale: 1, which make them be hidden below the tubes and cylinders you have created. If you initialize them with scale: 10, and you elevate them 5 meters from the floor let truck = model.setCoords([lngB, latB, 4]); then you will see them raising.
4. Your models have a wrong initialization params mixing anchor and adjustment. anchor: center will center the pivotal center of your object properly, but then you apply negative values to x and y (which means decenter the object), and a z value that elevates the pivotal center adjustment: { x: -0.1, y: -0.1, z: 0.4 }. If you want your model on altitude use the 3rd coord in setCoords.
5. Your Cylinders and Tubes for the bus stops and bus lines are huge, and also they have the wrong init params, as you set them below the ground level -0.4 units adjustment: { x: 0, y: 0, z: -0.4 } (something supported by Mapbox but very bad resolved and producing weird effects. My recommendation would be to make them almost flat and at the ground level with no adjustment param. const geometry = new THREE.CylinderGeometry(0.6, 0.6, 0.01, 32);.
Summarizing, check all of these changes and let me know if it works.

How to draw an inverted element on a layer in KonvaJS

is there any way to add a shape in KonvaJS which draws outside of it's boundries? Basically a "hole" in the layer, so that I can highlight a spot in the canvas by making everything around a circle darker (black with low opacity).
Any help is much appreciated!
Cheers
Edit:
Here is an image of what I mean (I'm not allowed to embed it yet):
https://i.imgur.com/gvTqgN0.jpg
I was hoping there might be something like this:
Konva.Circle({
x: 100,
y: 100,
radius: 50,
opacity: 0.3,
fill: 'black',
inverted: true
})
and this would then in turn "not draw" a circle, but everything around it would then take the given attributes. In this case it would all be darkend a bit besides the circle.
You can do this with a custom shape:
const shape = new Konva.Shape({
width: stage.width(),
height: stage.height(),
// what is color of background ?
fill: 'rgba(0,0,0,0.2)',
sceneFunc: (ctx, shape) => {
// draw background
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(shape.width(), 0);
ctx.lineTo(shape.width(), shape.height());
ctx.lineTo(0, shape.height());
ctx.lineTo(0, 0);
// now cut circle from the background
// we can do this by useing arc
const x = 200;
const y = 200;
const radius = 10;
// but it must be counter-clockwise
// so the last argument true is very important here
ctx.arc(200, 200, 100, 0, Math.PI * 2, true);
ctx.fillStrokeShape(shape);
},
// remove shape from hit graph, so it is not visible for events
listening: false
});
Demo: https://jsbin.com/tevejujafi/3/edit?html,js,output

Create offset for axis - X and Y should meet at 0, not Y-axis min value

I am using c3.js to show temperature values, as a range I expect values from -30 to +50 degrees.
This works fine so far, but I am unhappy with the graphical representation.
I would like to have my X axis meet the Y axis at 0 and not at -30. Is this possible with c3.js? I already had a look at the manual and the examples, but I didn't find anything regarding offsetting the axis in this way.
You can hide default axis (1) and add custom line at zero (2).
See in action (jsfiddle)
var chart = c3.generate({
data: {
columns: [
['sample', 30, 20, -10, 40, 15, -25]
]
},
axis: {
x: {
show: false // (1)
},
y: {
max: 50,
min: -30,
// center: 0,
}
},
grid: {
y: {
lines: [{ value: 0, text: 'zero' }] // (2)
},
},
});
Related docs:
http://c3js.org/reference.html#axis-x-show
http://c3js.org/reference.html#grid-y-lines

KineticJS - Crop fill image

I'm trying to use a tileset in my game. I want to crop the fill image but can't because
I can't fill a shape with a Kinetic.Image() object.
I can't crop a Image() object.
var rect = new Kinetic.Rect({
x: 0,
y: 0,
width: 64,
height: 64,
fill:{
image: imageObj,
crop:{
x: 128,
y: 128,
width: 64,
height: 64
},
},
strokeWidth: 1
});
This doesn't work, and I also can't replace image: imageObj with a Kinetic.Image() object that is precropped. Any ideas?
EDIT: Looks like it might be possible by drawing the Kinetic.Image to the scene, using toDataUrl to load the cropped Kinetic.Image into a image object useable by fill, then continue with the map script. This introduces a ton of performance issues/loading times so I'm going to go ahead and assume what I want to do just isn't feasible. If anyone has any ideas on how to do this properly please let me know.
You can get fill to accept an image, as shown in this example with the Vader/Yoda:
http://www.html5canvastutorials.com/kineticjs/html5-canvas-set-fill-with-kineticjs/
What i'd suggest is loading your images into an array (as he does in the example) then calling the images out as you create the tile.
I changed the code for the first Pentagon to a Rectangle on that example like so:
var colorPentagon = new Kinetic.Rect({
x: 40,
y: 50,
width: 100,
height: 100,
fill: {
image: images.darthVader,
offset: [-220, -70]
},
stroke: "black",
strokeWidth: 4,
draggable: true
});
And it worked, so no reason that can't give you what you want.

Resources