I'm currently writting a 3D implementation of the boids algorithm in P5.js but I'm having trouble orienting my boids according to their direction (velocity). Rotations are limited to RotateX(), RotateY() and RotateZ(). The simplest solution that I feel should work goes along these lines :
push();
translate(this.pos);
rotateZ(createVector(this.vel.x, this.vel.y).heading());
rotateY(createVector(this.vel.x, this.vel.z).heading());
beginShape();
// Draw Boid Vertices..
endShape();
pop();
But it doesn't.
I've written a much smaller version of the program which contains only the orientation for randomly generated particles that go in a single direction. It is available here directly on the p5js website : https://editor.p5js.org/itsKaspar/sketches/JvypSPGGh
There is a default orbit control so you can zoom and drag the mouse to check the orientation of the particles.
Thanks so much, I've been stuck on this for half a day now
From your demo, the z component is flipped, and you can test this from only trying one of the rotations at a time. Second, chaining rotations in 3D this way will usually not do what you want, as rotating will change the "up" or "right" vector of the coordinate system attached to a certain object. For example, rotating about the up (-y for p5) vector, or the yaw angle, will rotate the right vector. The second rotation then needs to be about the rotated right vector (now pitch), so you can't just use rotateX/Y/Z as they are still in world space instead of object space. Note that I'm completely ignoring roll in this solution, but if you look at the boids from the front and top angles, it should be aligned with the velocities
var right = p5.Vector(this.vel.x, 0, this.vel.z);
rotate(atan(this.vel.y/ this.vel.x), right);
rotateY(atan2(-this.vel.z, this.vel.x));
I am using create.js's tween.js. I am trying to make a bounce animation, more complex than the one given. More specifically, I am trying to tween an objects's y by an offset rather than a given coordinate. It seems like there is a simple way of doing this like:
createjs.Tween.get(circle, {loop:false}).to({offset-x: 100}, 1000, createjs.Ease.linea);
Ultimate Question: How do I tween the coordinates of an object based off of its current position?
When you make a Tween instance, you are creating a deterministic animation, meaning that you can set the position of the tween to any value (between 0 and 1), and it will be where you expect it.
If I understand what you are asking, you want to make a tween up-front, but have it use the object's current position instead of the value it was at when the tween was made. If this is the case, then you will need a different approach. Perhaps you should generate the tween on-demand when it is needed, rather than initially. That way, it could use your current position.
Here is a quick sample: http://jsfiddle.net/x4xxwjuv/
The ball moves at a constant rate, but when you click the buttons, it will:
Tween back a bit, based on its current position
OR Tween to a specific Y position (fall to the floor)
Then it resumes moving normally. The tweened ball is filled, the animated one is not.
Here is sample code from the spike.
createjs.Tween.get(ball)
.to({x: ball.x+(ball.xSpeed*-4), y:ball.y+(ball.ySpeed*-4)}, 1000, createjs.Ease.bounceOut);
I'm making a canvas game where you travel in a spaceship over an endless repreating background. Right now I'm drawing four instances of the background at different positions based off of the player's x/y position, so they will move with the player.
ctx.translate(ax,ay);
ctx.drawImage(Ibg,Math.round(x/1080)*1080,Math.round(y/720)*720,1080,720);
ctx.drawImage(Ibg,(Math.round(x/1080)*1080)-1080,Math.round(y/720)*720,1080,720);
ctx.drawImage(Ibg,Math.round(x/1080)*1080,(Math.round(y/720)*720)-720,1080,720);
ctx.drawImage(Ibg,(Math.round(x/1080)*1080)-1080,(Math.round(y/720)*720)-720,1080,720);
Translating to ax and ay basically allows objects to scroll with the cameras the player moves, since ax and ay are relative to the player's position. I can create a parallax effect by doing this instead:
ctx.translate(ax*.5,ay*.5);
This makes the background scroll slower than other game objects, like I'd like it to. But I still haven't figured out how to adjust the rest of the code to compensate. As the player moves farther from (0,0) he sees less and less of the background, because it seems to go beyond him at a faster rate. How can I fix this?
As an option to markE's answer you don't need to use a second canvas at all (which is a good option to this).
You can simply use CSS for background image and adjust background position with the amount you need.
Demo here
The essential part is simply these lines:
Background X position where -1 can be replaced with the value you want to move it at.
bgx -= 1;
Then for each loop the background position is updated (Y position is fixed in this example):
canvas.style.backgroundPosition = bgx + 'px -30px'; // set X and Y position
When bgx somehow equals the max width of the image you just reset it to the beginning.
Use 2 canvases -- one placed directly on top of the other
A "background" canvas is on the bottom and animates more slowly.
A "game objects" canvas is on the top and animates more quickly.
That way you can create a parallax effect using different animation speeds for each canvas.
The basis for the code is from John E. Graham's blog http://johnegraham2.com/blog/2010/09/25/project-javascript-2d-tile-engine-with-html5-canvas-part-4-using-zones-for-further-optimization/
It works perfectly for drawing a screen's worth of tiles, but I cannot for the life of me figure out how to adjust it 1 row/column at a time based on pressing up, down, left, or right keys.
Here is an example with the transparency to help visualize the zones http://simplehotkey.com/Javascript/canvas.html (loading positions of 1,188 tiles but only draws a couple hundred to fill the screen) I had it loading an array with 70,000 entries and it was still quick because it's only drawing whats on the screen, but cannot figure out how to slide everything based on input...
I've come up with a couple ideas and am not sure what's the best way.
One screen worth of tiles is shown here:
tilesArray = [
0,0,0,0,0,0,0,1,2,9,6,0,0,7,0,0,1,0,
0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,
0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,9,0,
0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,9,0,
0,9,9,9,9,9,9,0,7,2,0,0,0,0,0,1,2,0,
0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,
0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,
0,9,0,7,2,9,9,9,9,9,9,9,9,9,9,9,9,0,
0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,
0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
];
Where 0 is a wall tile (around perimeter), 9 a floor tile, 7 a door and a couple other random tiles.
That is exactly what is loaded to the screen, but I cannot figure out how to shift everything 1 tile in either direction based on input, up, down, left, right.
The one idea I'm leaning towards now, is just to use that array above as the basis for rendering, and somehow feeding the new values into it based on keyboard input, from another array. Maybe slicing from another, much larger array (holding all the tiles for the entire level) and using that slice to populate the array that's actually rendered???
That's replacing every tile every frame though...
for getting player input I was using:
//Key listener
document.onkeydown = function(e){
e = e?e:window.event;
console.log(e.keyCode + "Down");
switch (e.keyCode){
case 38:
//UP KEY
Game.inputReaction('up');
//Game.moveDir('up');
break;
case 40:
//DOWN KEY
//Game.inputReaction(40);
//Game.moveDir('down');
break;
case 37:
//Left Key
//Game.inputReaction(37);
break;
}
}
The other alternative is to try to adjust the tiles already on the screen and add new tiles but this engine isn't using global variables so I'm not sure how to affect the tile engine programatically based on input....like I can add another method (inputReaction(num)) and trigger some actions from my keyboard input (console.log()) but I can't access the other methods actually drawing the tiles. Or maybe I have to make a copy of the object, change it and return it? but it's pretty complex.
I think it might be easier to adjust the array values that are being fed into the "engine" (array above) rather than changing around how the engine is calculating what's being drawn. Can you confirm this?
Add a camera abstraction that you can move around on the map, then shift the drawing positions according to the camera position. When the camera moves south 10px, all tiles move north 10px, same with east and west. Since you only draw the tiles that are visible, there won't be much of a performance loss.
The renderer looks at the camera to figure out what needs to be drawn and you can expose the camera object to the outside to manipulate it. That way you only need to change the camera position to change what is shown on the screen.
I did this in a proof of concept tiling engine a year ago and I was able to smoothly scroll and scale huge tilemaps.
If you start changing the array itself, your performance will suffer and you won't be able to scroll smoothly since you can only go in steps of one tile and not one pixel.
I'm using canvas for a project and I have a number of elements that I'm skewing. I'm only skewing on the y value and just want to know what the new width of the image is after skewing (so I can align it with another canvas element). Check out the code below to see what I mean
ctx.save();
//skew the context
ctx.transform(1,0,1.3,0,0,0);
//draw two images with different heights/widths
ctx.drawImage(image,0,0,42,60);
ctx.drawImage(image,0,0,32,25);
The goal would be to know that the 42 by 60 image was now a X by 60 image so I could do some translating before drawing it at 0,0. It's easy enough to measure each image individually, but I have different skew values and heights/widths throughout the project that need to be align. Currently I use this code (works decently for images between 25 and 42 widths):
var skewModifier = imageWidth*(8/6)+(19/3);
var skewAmount = 1.3; //this is dynamic in my app
var width = (skewModifier*skewAmount)+imageWidth;
As images get wider though this formula quickly falls apart (I think it's a sloping formula not a straight value like this one). Any ideas on what canvas does for skews?
You should be able to derive it mathematically. I believe:
Math.atan(skewAmount) is the angle, in radians, that something is skewed with respect to the origin.
So 1.3 would skew the object by 0.915 radians or 52 degrees.
So here's a red unskewed object next to the same object skewed (painted green). So you have a right triangle:
We know the origin angle (0.915 rads) and we know the adjacent side length, which is 60 and 25 for your two images. (red's height).
The hypotenuse is the long side thats being skewed.
And the opposite side is the triangle bottom - how much its been skewed!
Tangent gets us opposite / adjacent if I recall, so for the first one:
tan(0.915) = opposite / 60, solving for the opposite in JavaScript code we have:
opposite = Math.tan(0.915)*60
So the bottom side of the skewed object starts about 77 pixels away from the origin. Lets check our work in the canvas:
http://jsfiddle.net/LBzUt/
Looks good to me!
The triangle in question of course is the canvas origin, that black dot I painted, and the bottom-left of the red rectangle, which is the original position that we're searching for before skewing.
That was a bit of a haphazard explanation. Any questions?
Taking Simon's fiddle example one step further, so you can simply enter the degrees:
Here's the fiddle
http://jsfiddle.net/LBzUt/33/