I am using Don Mccurdy's physics engine and able to set the dynamic body and static body to bounce a sphere. I wish the ball to bounce along a path. What should be the approach I take in writing some animation code? And in case there is some reference code that will greatly help. Thanks
If you want to bounce the path in some direction, you can simply apply an impulse which will steer the ball.
let body // refers to the aframes entity.body
body.applyImpulse(
/* impulse vector*/ new CANNON.Vec3(x, y, z),
/* world position vector*/ new CANNON.Vec3(x, y, z)
);
Check it out here.
However if you want the ball to bounce with a complex path, then you should disable the physics engine (remove the dynamic-body) and use the animation-timeline component.
Related
I'm using aframe for a VR project I'm doing and I'm using checkpoint on the ground to lead the user around the 3D space. I received help before on how to create a checkpoint here
Here is the link to the most current iteration of my project -> https://museum-exhibit-demo.glitch.me/webVR.html
Is it possible to have the animation that takes you to the cylinder also change the view of the camera and height? Basically once I click the cylinder to take me to the position it will also snap my view to the text on the wall even if it is not eye height
Great Demo. I've prepared a candidate solution on glitch (app). This solution changes the height of the camera, and the horizontal direction/yaw of the camera. It does not change the pitch of the camera. Ideally any AR/VR app would minimise forcing a change of camera orientation. If you forcibly change the pitch of the camera that's like permanently tilting the floor of the user. If you just change the yaw then that just permanently changes the horizontal direction they are look. Changing the pitch can be done, but I think from a user perspective that might cause more problems than it is worth, changing the yaw is just about OK. Similar recommendations were previously mentioned in https://stackoverflow.com/a/47667912/10849562.
I'll break down the solution code by how it solves your two issues, to have the animation that takes you to the cylinder also change the height of the camera, and separately how it can change the view/direction? I'll add in line references to the solution were relevant.
Change the height to match the height of the text
First you need to know the height of the text associated with the checkpoint cylinder. One way to do this is to provide the id of the related a-text entity to the goto component. To do that I added a new component property textId to your goto component (L79). Then in each of the places where you have used the goto component the textId property was set. For example for the checkpoint cylinder associated with the Welcome! text, the goto component was changed to goto="textId: welcome" (L298).
The id of the associated a-text enitity can be accessed from methods of the goto component using this.data.textId which will be different for each goto component. Using this information within the component, the position of the a-text enitity can be found in a similar way to how you found the rig position, by finding the a-text element with document.querySelector L83 and then finding the position L93.
let text = document.querySelector(`#${this.data.textId}`);
text.object3D.getWorldPosition(textPos);
Note that instead of using text.getAttribute("position") the getWorldPosition method is used instead. That is because you have wrapped your a-text elements inside a-entity elements that also have positions set. getAttribute("position") only gives you the position relative to its parent entity, but this solution requires the absolute/world position of the text. Of course other solutions might do things different, and it's also possible to change the HTML structure of your demo so that you could use getAttribute("position"). getWorldPosition is a method from THREE.js (which A-Frame is based on) and stores the position in the textPos variable. You can use textPos in the same way as rigPos. Instead of rigPos.y you can now do textPos.y to get the height of the text as the end point of the position animation to change the height of the camera.
Note that 1.6 is taken away from the height in the solution. The default height of the camera in A-Frame is 1.6. You've handled this by reducing the position of the camera by -1.1 in the #pov entity.
Change the direction of the camera match the direction of the text
First we need to know the direction of the text with respect to its associated checkpoint cylinder. Because we now have access to the position of the cylinder the direction vector between from the cylinder to the text can be calculated (L111). From this the azimuthal angle or yaw angle of the direction from the checkpoint cylinder to the text can be calculated (L115). To do this calculation a function getYaw was created (L46) to calculate the yaw angle.
Because you have already applied a yaw rotation of 90 degrees on your #pov entity that wraps your a-camera entity, the yaw angle is calculated from the negative z-axis (0, 0, -1).
Now that you have the direction the text is from the checkpoint cylinder, you need to know the yaw direction the camera is currently pointing in. You can find this out from the rotation component of the a-camera entity. Just like finding the position of any entity, you can find the a-camera element with document.querySelector (L84) and the find its yaw angle camera.getAttribute("rotation").y (L116). You can then calculate the target yaw angle that you should set the rig to by calculating the relative angle from the camera entity to the text entity which is called targetRigYaw in the solution (L117).
Note that there are lots of applications of a mod function. This simply ensures that all yaw angles are always positive and between [0, 360] which helps simplify things when applying angles.
You could now use the targetRigYaw as the angle to set your rig to to change the view direction to look at the text. However depending on the yaw angles of the text direction and camera direction, this angle might be greater than 180 degrees. You can imagine that you could rotate left or right to end up looking in a particular direction. Unless the direction you would like to look in is directly behind you, one of the direction will be a shorted rotation than the other. L120-123 change the targetRigYaw angle so that you are always rotating in the shortest angular direction to end up looking at the text.
In order to animate the yaw in the same way as you animated the position you can add second component to the #pov entity. In the solution this is called animation__rotation (L144). The A-Frame docs describe how you can add multiple animation using the __ notation https://aframe.io/docs/1.0.0/components/animation.html#multiple-animations.
We can then set the animation__rotation component to perform an animation of the rotation of the #pov entity in a similar way to the position. The animation__rotation component is set using setAttribute to rotate from the current yaw angle of the rig to the targetRigYaw angle, and the duration of the animation is set to the same length as the position animation.
I hope this helps solve your two questions. Please let me know if you have any questions. I've added comment to the code, however there were quite a few snippets that I added that might not be obvious what they do.
I want to put water sprite inside the flask and when i drag it on top of the container it pour this water into the container.
Does anybody know how to do this in game maker?
And here is a picture of the flask and container
You could use a rectangle that is only visible through the sprites of the recipients and change it's scale when you pour it. For example, link it's image_yscale variable to the quantity of poured liquid.
If you are motivated, shaders could be the solution. Otherwise, you could simply design flat-bottomed recipients, make them transparent, and use the draw event to draw a liquid-colored rectangle inside of them before drawing them. The result won't be as astonishing, but far easier.
your draw event could look like ;
1 - draw the rectangle at the x & y coordinates (you may have to use an offset), with the correct scale using image_xscale & image_yscale, and the correct angle which is the flask's image_angle variable.
2 - draw the recipient after that.
We are developing a small game of dropping images. We need to find the image X and Y points without an Event like mouseClick() event etc.
Please Help me to find out Points of Moving Image. i.e Points of Transit Image.
We have applied pathtransition on image.
Read the docs.
"This Transition creates a path animation that spans its duration. The
translation along the path is done by updating the translateX and
translateY variables of the node"
Just register a listener with the translateX and translateY properties of the Node you are animating. You can use the boundsInParent property to find its coordinates, including translations, relative to the parent.
I need to draw a sprite in Game Maker, where the opacity (alpha) of the sprite being drawn is a gradient, and not a fixed value.
In simpler terms, I need the sprite to look like it's fading from one of its edges.
The easy to do this is to apply a gradient to the sprite in the editor under image -> gradient. If you want to do it in code the only way I can think of is:
for (_t = 0;_t < sprite_get_width(sprite);_t ++){
draw_sprite_part_ext(sprite,0,_t,0,_t+1,sprite_get_height(sprite),x+_t,y,1,1,c_white,_t/(sprite_get_width(sprite)))
}
(put this code in the draw event and change "sprite" to your sprite)
update:
The above code only works in game maker studio, for game maker version 8.0 or lower change the code to:
for (_t = 0;_t < sprite_get_width(sprite);_t +=1 ){
draw_sprite_part_ext(sprite,0,_t,0,1,sprite_get_height(sprite),x+_t,y,1,1,c_white,_t/(sprite_get_width(sprite)))
}
I'm working on a full screen image viewer, I'll temporarily open a dev URL here:
http://www.jungledragon.org/apps/jd3/image/704/great_grey_owl.html/zoom
This viewer is responsive and scales to your browser width/height. One of its key features is being able to zoom in and out of the image using your mouse wheel. Rather than a center-based zoom, the idea is to zoom based on origin, meaning the coordinates of your mouse, allowing you to zoom into specific areas of the image.
How to reproduce the issue
If you open the above URL and have a quick play with your mouse wheel, it may appear to be working correctly. However, the math I am using is slightly off. Here is how you can reproduce the issue:
Open the above URL
Hover your mouse over the left eye of the Owl
Zoom one step using your mouse wheel, it should zoom exactly into the eye
Position your mouse on the owl's beak
Zoom one more step using your mouse wheel
You should now notice that the second zoom step did not go into the Owl's beak exactly, it seems to be slightly off, both horizontally and vertically. I'm thinking this is a result of bad math.
How it works
Here is the javascript that handles it all:
http://www.jungledragon.org/apps/jd3/js/jd3-slideshow.js
I am capturing the mousewheel event. Based upon its direction, I am increasing or decreasing the zoom level. The actual zooming is nothing more than applying a CSS class that scales the image using a CSS3 transform:
&.grow1 { #include jd-scale(1); }
&.grow2 { #include jd-scale(1.5); }
&.grow3 { #include jd-scale(2.0); }
&.grow4 { #include jd-scale(2.5); }
&.grow5 { #include jd-scale(3.0); }
Note: the above is a call to a SASS mixin that translates into the right vendor prefixes for transform:scale.
The above accomplishes the basic zooming without issues. To make origin-based zooming possible, however, a few more steps are needed. Upon doing the actual zooming, I first set the origin of the zoom in javascript, using transform-origin. Here is my helper function for setting it:
function zoomOrigin(selector, originStr) {
selector.css({'-webkit-transform-origin': originStr});
selector.css({'-moz-transform-origin': originStr});
selector.css({'-ms-transform-origin': originStr});
selector.css({'-o-transform-origin': originStr});
selector.css({'transform-origin': originStr});
}
The heart of this question is about calculating the correct origin. There are two things worthy to mention in calculating this value:
The absolute coordinates (meaning the X and Y) are relative to the image, not relative to the page
The calculation of the origin should take into account that the image has grown/shrunk based on the current zoom state
The origin calculation happens in realtime, based on the mousemove event. Here is the method that does so, with irrelevant parts removed:
$("#image-container img").mousemove(function(e) {
// user has moved their mouse. in case of zooming or panning, this means that the
// origin (center point) of those interactions need to be recalculated
// calculate the mouse offset within the zoomable object (which is different than the page-level offset)
// this relies on the parent of the element having position:relative set
var parentOffset = $(this).offset();
zoomOriginX = e.pageX - parentOffset.left;
zoomOriginY = e.pageY - parentOffset.top;
// recalculate the width and height of the image given the current zoom level
width = $(this).outerWidth() + (1 + ((zoomLevelCurrent - 1)*0.5) * $(this).outerWidth());
height = $(this).outerHeight() + (1 + ((zoomLevelCurrent - 1)*0.5) * $(this).outerHeight());
// calculate origin percentages based on zoomed width and height
// the zoom methods rely on these variables to be set
zoomOriginPercX = (zoomOriginX / width * 100);
zoomOriginPercY = (zoomOriginY / height * 100);
});
The main purpose of this method is to correctly set the global variables zoomOriginPercX and zoomOriginPercY, which are used to set the origin (percentage) prior to zooming.
From a math perspective, my idea was to simply calculate the zoomed width of the image, and to use the offset X and Y to come to a reliable origin percentage. As the problem statement shows, I am quite close to a correct calculation, yet something is off.
Although the zooming currently works well, I want it to be perfect. It would make for quite a powerful image viewer that is really easy to implement, also for others.
Desired Effect
To start answering your question I think it's worth first clarifying the desired effect. Essentially you're looking for the same effect you'd get if you pinched to zoom on an iPhone - the 'origin' of the pinch stays exactly the same, and everything around it stretches. You can imagine pinning some stretchy fabric at the origin, and pulling the corners.
Problem
This is working fine for you if you don't move the mouse between zooms, but if you do, the origin appears to move. The cause of the problem is exactly that - you are changing the origin of the transform every time you move the mouse. Of course you do need to do this, but you are calculating the origin based on the original (100% zoomed) position of the image. The actual origin needs to be somewhere between the origin of the first zoom and the new mouse position.
In other words, CSS is just doing one transform. If you set the origin to x,y then zoom to zoom level 2, this will give the same result as if you set the origin to x2,y2, zoom to level 1, then move to x,y, and go to level 2.
Solutions
I presume you could solve the issue in several ways:
Calculate a scaling factor for the 'new' origin on each zoom
this is likely a function of zoom level, mouse position and previous origin
Calculate and apply a translation each time the origin is moved
again will depend on the current origin, zoom level and mouse position
Find another way to 'stack' transforms on top of one another.
One way to do this may be to dynamically generate a new containing div each time you and apply a scale transform to that similar to the accepted solution in this question.
Unfortunately I don't have the time to go further than this, but hopefully it points you in the right direction?