I am trying to create a game where you have to move a ball on a platform. At the start of the game, the ball is dropped on the platform and then you can move it around with the arrow keys. This is al working, no problems here.
The game starts with a ball dropped on a yellow tile as can be seen in my fiddle (click the 1 to start). The platform is build in javascript as follows (for level 1 and 2):
var levels = [
[
[1,1,1,1,1],
[1,1,1,1,1],
[1,2,1,1,1]
],
[
[1,1,1,2,1],
[1,1,1,1,1],
[1,1,1,1,1]
]
];
Where 1 = green tile, 0 = no tile and 2 is a yellow tile.
To let the ball drop on the yellow tile, I have the following code:
go: function() {
ball.reset((1*100+50),(2*100+50));
start();
}
Where (1*100+50) is the x-coordinate of the yellow tile and (2*100+50) the y. Better explained: 1 is 1 tile to the right * tile length + 50 ( +50 is to drop the ball in the middle of the div). All works as intended.
But if I load level 2 (see the fiddle, click the 2), we see that the yellow tile is moved, but the ball is still dropped at the fixed spot (see go: function). This is what I need to fix.
I want these yellow tile coordinates to be loaded when a level is loaded. In this case, the simplest thing to do is to add these coordinates with each level. I thought about something like this:
var levels = [
{
yellowTile : [1, 2],
tiles : [ [1,1,1,1,1],
[1,1,1,1,1],
[1,2,1,1,1] ]
},
{
yellowTile : [3, 0],
tiles : [ [1,1,1,2,1],
[1,1,1,1,1],
[1,1,1,1,1] ]
}
];
So the go: function will be like:
go: function() {
ball.reset((yellowTileX*100+50),(yellowTileY*100+50));
start();
}
But I have no luck in making this work. Hope someone can help me out here.
Many thanks
The easiest way to find the start position is to save it when looping all the tiles. I've modified your script so the start position is saved by adding the following to loadLevel:
if(levels[level][i][j] === 2) {
startPosition = {x: j, y: i};
}
I've added the function getStartPosition() to the plane class, this function can be used in the 'go' function to fetch the start x and y of the plane. This can be used to reset the ball to the correct x and y
go: function() {
ball.reset((plane.getStartPosition().x*100+50),(plane.getStartPosition().y*100+50));
start();
}
Check out my modified version: http://jsfiddle.net/BKEbL/7/
Related
i have got array of points (x,y) and i need to reduce points of polygons.
i would like use Simplify.js (It uses a combination of Douglas-Peucker).
But i have got problem:
let test =
[ { x: 33.56257055900005, y: 44.83995926300003 },
.....
..... more than 7k points
{ x: 33.56257055900005, y: 44.83995926300003 } ];
let simplified = simplify(test, 1, true);
always return 2 points (first, and last).
https://www.npmjs.com/package/simplify-js
http://mourner.github.io/simplify-js/
what it is not work?
At first remove last point of test to convert your polygon to polyline, then balance your tolerance. If your points are cordinate on the earth, 1 means at least 50 mi (80 km)!!!
Try 0.001 for tolerance
let simplified = simplify(test, 0.001, true);
Example JSfiddle
I can get my cone to point at each target sphere in turn (red,green,yellow,blue) using the THREE.js "lookAt" function.
// Initialisation
c_geometry = new THREE.CylinderGeometry(3, 40, 120, 40, 10, false);
c_geometry.applyMatrix( new THREE.Matrix4().makeRotationX( Math.PI / 2 ) );
c_material = new THREE.MeshNormalMaterial()
myCone = new THREE.Mesh(c_geometry, c_material);
scene.add(myCone);
// Application (within the Animation loop)
myCone.lookAt(target.position);
But now I want the cone to pan smoothly and slowly from the old target to the new target. I guess that I can do it by computing intermediate points on the circular arc which is centred at the cone centre Cxyz and which passes from the previous target position Pxyz to the new target position Nxyz.
Please can someone point me to suitable: (a) utilities or (b) trigonometry algorithms or (c) code examples for calculating the xyz coordinates of the intermediate points on such an arc? (I will supply the angular increment between points based on desired sweep rate and time interval between frames).
You want to smoothly transition from one orientation to another.
In your case, you would pre-calculate the target quaternions:
myCone.lookAt( s1.position );
q1 = new THREE.Quaternion().copy( myCone.quaternion );
myCone.lookAt( s2.position );
q2 = new THREE.Quaternion().copy( myCone.quaternion );
Then, in your render loop:
myCone.quaternion.slerpQuaternions( q1, q2, time ); // 0 < time < 1
three.js r.141
For those of you looking to lerp position and lookAt, you can create a initial lookAt target from the current look direction and lerp that towards the final target:
function MoveWhileLookingAt(object: Object3D, destination: Vector3, lookAt: Vector3){
const fromPosition = object.position.clone();
const fromLookAt = new Vector3(
0,
.1, // To avoid initial camera flip on certain starting points (like top down view)
-object.position.distanceTo(lookAt) // THREE.Camera looks down negative Z. Remove the minus if working with a regular object.
);
object.localToWorld(fromLookAt);
const tempTarget = fromLookAt.clone();
function LookAtLerp(alpha: number){
// This goes in your render loop
object.position.lerpVectors(fromPosition, destination, alpha);
tempTarget.lerpVectors(fromLookAt, lookAt, alpha);
object.lookAt(tempTarget);
}
}
I am using three.js framework and using physi.js for forces and gravity. My problem is that i has given some position to a dice on a plane and want to lob it or flip it from its position with some angle by clicking on it such that it rotate in air and fall on plane due to gravity force of plane.
i have idea about onclickevent method but i don't know how to set the dice to jump with some height in 90 degree and rotate it with some angle only one time for one click.
if you have some suggestion please give me method to set up the dice
thank you
i have no experience with physi.js, for physics i use cannon.js, so i do have some experience with physics. i can tell you how it's done, but i cant provide an example just yet. the first thing you need to do is cast a ray from the camera to the dice. This tells you if the object is clicked on. from there you apply a force to where the object is clicked. i hope this helps.
EDIT/Follow up:
I've been looking over physi.js, and it seems pretty similar to cannon.js. Also, there are many aspects to what you're asking, but i'll try to be as comprehensive as possible.
The first thing to do is set the gravity. In the examples it is done by:
var scene = new Physijs.Scene({ fixedTimeStep: 1 / 120 });
scene.setGravity(new THREE.Vector3( 0, -30, 0 ));
the next thing to do is define the plane the dice is sitting on as a rigid body, and the dice as a rigid body.
var dice = new Physijs.BoxMesh(
new THREE.CubeGeometry(5, 5, 5), //the collision geometry
new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture('images/dicetexture.jpg' )});, // material of the dice
5, // mass, for the plane use 0, meaning it doesnt move.
{ restitution: .2, friction: .8 } //contact material
);
and finally, you need to apply a force, i cant find an example of it, but going over the source real quick, i found:
// Physijs.Mesh.applyForce
Physijs.Mesh.prototype.applyForce = function ( force, offset ) {
if ( this.world ) {
this.world.execute( 'applyForce', { id: this._physijs.id, force_x: force.x, force_y : force.y, force_z : force.z, x: offset.x, y: offset.y, z: offset.z } );
}
};
both force and offset should be vectors. force being the direction and magnitude, offset being the point of origin.
i'll experiment a bit more with physi.js it seems to have solved some problems i've been pondering with. if this still doesnt solve the problem. i'll post an example.
as for letting it spin for a set number of times in a preset height, i think that's a lot of experimenting with the values...
EDIT 2:
In the fiddle you posted the problem you explained was an undefined variable, effect.
if (intersects.length > 0) {
intersects[ 0 ].applyImpulse(effect, offset);
}
change this to:
if (intersects.length > 0) {
var effect = new THREE.Vector3( 0, 100, 0 );
var offset = new THREE.Vector3( 0, 0, 0 );
intersects[ 0 ].object.applyImpulse(effect, offset);
}
the values ARE defined, but you define them in a different function.
function apply_force(){
var effect = new THREE.Vector3( 0, 100, 0 );
var offset = new THREE.Vector3( 0, 0, 0 );
object.applyImpulse( effect, offset );
}
this function will not be used anymore, so you might as well remove it.
CLICK TIMER:
if(canClick == true){
//process click
canClick = false;
setTimeout(function(){canClick = true}, 5000)//5 seconds before the user can click again.
}
Okay this is going to be hard to explain. So bear with me.
Im having less of a problem with the programming, and more a problem with the idea behind what Im trying to do.
I have a grid of triangles. Ref: http://i.imgur.com/08BPHiD.png [1]
Each triangle is it's own polygon on a canvas element that I have set as an object within the code. The only difference between the objects is the coordinates that I pass through as parameters of a function like so:
var triCoordX = [1, 2, 3, ...];
var triCoordY = [1, 2, 3, ...];
var triCoordFlipX = [1, 2, 3, ...];
var triCoordFlipY = [1, 2, 3, ...];
var createTri = function(x, y, z) {
return {
x: x,
y: y,
sides: 3,
radius: 15,
rotation: z,
fillRed: 17,
fillGreen: 17,
fillBlue: 17,
closed: true,
shadowColor: '#5febff',
shadowBlur: 5,
shadowOpacity: 0.18
}
};
for (i = 0; i < triCoordX.length; i++){
var tri = new Kinetic.RegularPolygon(createTri(triCoordX[i], triCoordY[i], 0));
}
for (i = 0; i < triCoordFlipX.length; i++){
var triFlip = new Kinetic.RegularPolygon(createTri(triCoordFlipX[i], triCoordFlipY[i], 180));
}
Now what Im trying to do exactly is have each object polygon be able to 'recognise' its neighbors for various graphical effects.
How I propose to do this is pass a 4th parameter into the function that I push from another array using the for loop that sets a kind of "index" for each polygon. Also in the for loop I will define a function that points to the index 'neighbors' of the object polygon.
So for instance, if I want to select a random triangle from the grid and make it glow, and on completion of a tween want to make one of it's neighbors glow I will have the original triangle use it's object function to identify a 'neighbor' index and pick at random one of its 3 'neighbors'.
The problem is with this model, Im not entirely sure how to do it without large amounts of bloat in my programming, or when I set the function for the loop, to set a way for the loop to intuitively pick the correct index numbers for what are actually the triangle's neighbors.
If all of that made sense, Im looking for any and all suggestions.
Think of your triangles as being laid out in a grid with the triangle in the top left corner being col==0, row==0.
Then you can find the row/col coordinates of the 3 neighbors of any triangle with the following function.
Ignore any neighbors with the following coordinates because the neighbors would be off the grid.
col<0
row<0
col>ColumnCount-1
row>RowCount-1
Example code (warning...untested code--you may have to tweak it):
function findNeighbors(t){
// determine if this triangle's row/col are even or odd
var evenRow=(t.col%2==0);
var evenCol=(t.row%2==0;
// left neighbor is always the same
n1={ col:t.col-1, row:t.row };
// right neighbor is always the same
n2={ col:t.col+1, row:t.row };
// third neighbor depends on row/col being even or odd
if(evenRow && evenCol){
n3={ col:t.col, row:t.row+1 };
}
if(evenRow && !evenCol){
n3={ col:t.col, row:t.row-1 };
}
if(!evenRow && evenCol){
n3={ col:t.col, row:t.row-1 };
}
if(!evenRow && !evenCol){
n3={ col:t.col, row:t.row+1 };
}
// return an array with the 3 neighbors
return([n1,n2,n3]);
}
I have been racking my brain on how to make this work. I can find no examples of this and actually no previous questions. Basically I have a 121 thumbnail images (with the exact same dimensions), arrange them in a grid with gutters and I want to take the first image and place it in the center. (this allows for an 11x11 image grid) Then I would like to take each next image and begin to arrange them around the center image using the next closest available vacant location to the center image until all used up. It is assumed the list of images will be gotten from an array object. What is the most efficient way of doing this?
Most likely not the most efficient way of solving this, but I wanted to play with it:
You could iterate over all the points in your grid, calculate their distances to the center point and then sort the points by this distance. The advantage over the algorithmic solutions is that you can use all sorts of distance functions:
// Setup constants
var arraySize = 11;
var centerPoint = {x:5, y:5};
// Calculate the Euclidean Distance between two points
function distance(point1, point2) {
return Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2));
}
// Create array containing points with distance values
var pointsWithDistances = [];
for (var i=0; i<arraySize; i++) {
for (var j=0; j<arraySize; j++) {
var point = {x:i, y:j};
point.distance = distance(centerPoint, point);
pointsWithDistances.push(point);
}
}
// Sort points by distance value
pointsWithDistances.sort(function(point1, point2) {
return point1.distance == point2.distance ? 0 : point1.distance < point2.distance ? -1 : 1;
});
The resulting pointsWithDistances array will look like this:
[
{x:5, y:5, distance:0},
{x:4, y:5, distance:1},
{x:5, y:4, distance:1},
...
{x:4, y:4, distance:1.4142135623730951},
{x:4, y:6, distance:1.4142135623730951},
...
{x:3, y:5, distance:2},
...
]
By iterating over the array in this order you are effectively filling the grid from the center outwards.
(Thanks for Andreas Carlbom's idea how to display this structure.)
Check out the difference to using Rectilinear Distances:
// Rectilinear Distance between two points
function distance(point1, point2) {
return Math.abs(point1.x - point2.x) + Math.abs(point1.y - point2.y);
}
For the shell-like structure of the algorithmic approaches you can use the Maximum Metric:
// 'Maximum Metric' Distance between two points
function distance(point1, point2) {
return Math.max(Math.abs(point1.x - point2.x), Math.abs(point1.y - point2.y));
}
You can play with the code here: http://jsfiddle.net/green/B3cF8/