three.js editor will not execute position change script - javascript

Disclaimer: I am utilizing the three.js editor (https://threejs.org/editor/) as an ide to create an animated 3d scene with 6 objects and 6 directional lights. The scene itself will export and display without any animation/position changes.
When I attempted to add this script below to edit the xy positions of the objects the scene will not display when I press play.
var box = this.getObjectByName ('box');
var filledTube =this.getObjectByName('filledTube');
var ball =this.getObjectByName('ball');
var dice =this.getObjectByName('dice');
var tube =this.getObjectByName('tube');
var knot=this.getObjectByName('knot');
var blue1=this.getObjectByName('blue');
var blue2=this.getObjectByName('blue2');
var red1=this.getObjectByName('red');
var red2=this.getObjectByName('red2');
var green1=this.getObjectByName('green');
var green2=this.getObjectByName('green2');
function update( event ) {
var time = (event.time*.01);
box.position.x=-time;
box.position.y=-time;
filledTube.position.x=-time;
filledTube.position.y=-time;
ball.position.x=-time;
ball.position.y=-time;
dice.position.x=-time;
dice.position.y=-time;
tube.position.x=-time;
tube.position.y=-time;
knot.position.x=-time;
knot.position.y=-time;
blue1.position.x=+time;
blue1.position.y=+time;
blue2.position.x=+time;
blue2.position.y=+time;
red1.position.x=+time;
red1.position.y=+time;
red2.position.x=+time;
red2.position.y=+time;
green1.position.x=+time;
green1.position.y=+time;
green2.position.x=+time;
green2.position.y=+time;
}
I cannot find any information on google on the editor so here I am... any help or direction to documentation would be appreciated.

Try event.delta instead of event.time in the update function. My guess is that all objects are moving to fast.
So in update function:
var time = (event.delta*.01);
Good luck!

The script works and probably "kicks" everything far away, out of the view.
The reason is that the event.time values are very big, even if they are divided.
To see those objects, and move them in the scene try this:
var speed = 0.02;
box.position.x += speed; // adds 0.02 to the current box x position value
box.position.y -= speed; // subtracts 0.02 to the current box y position value
A nice tool, the browser console, can help you track values (for example: event.time) and solve problems.
For example: Add the following line inside the update function and see for yourself the huge time values.
console.log(event.time); // outputs time values
You can learn more for console here and here

Related

how to use the 'map' function using Brackets and p5.js?

I'm currently taking a course on intro to computer programming. It's an online course and doesn't have much help when you're stuck.
I'm using Brackets and p5.js.
I unfortunately don't know how to use the map function, I've tried different possibilities, but so far I haven't been able to solve the question below:
When the mouse button is pressed:
- Use the 'random' function to produce random values ranging from 2 to 14.
- Assign the output to Secure_vault_key0
When the mouse button is released:
- Use the 'random' function to produce random values ranging from 2 to 8.
- Assign the output to Secure_vault_key1
When any key is pressed:
- Make Secure_vault_key2 equal to the value of 'key'
When the mouse button is pressed:
- Use the 'map' function to scale mouseX to values ranging from 14 to 77.
- Assign the output to Secure_vault_key3
When the mouse button is pressed:
- Use the 'map' function to scale mouseY to values ranging from 22 to 76.
- Assign the output to Secure_vault_key4
Whilst the mouse is being dragged:
- Use the 'map' function to scale mouseX to values ranging from 14 to 80.
- Assign the output to Secure_vault_key5
This time you'll need to create the relevant event handlers yourself.
There are many possible ways of investigating this case, but you
should use ONLY the following commands:
- The assignment operator aka. the equals sign !
- mouseX, mouseY
- key, keyCode
- random
- map
*/
//declare the variables
var Secure_vault_key0;
var Secure_vault_key1;
var Secure_vault_key2;
var Secure_vault_key3;
var Secure_vault_key4;
var Secure_vault_key5;
function preload()
{
//IMAGES WILL BE LOADED HERE
}
function setup()
{
createCanvas(512,512);
//initialise the variables
Secure_vault_key0 = 0;
Secure_vault_key1 = "";
Secure_vault_key2 = "";
Secure_vault_key3 = 0;
Secure_vault_key4 = 0;
Secure_vault_key5 = 0;
}
///////////////////EVENT HANDLERS///////////////////
//Create event handlers here to open the safe ...
function mouseDragged()
{
console.log("mouseDragged", mouseX, mouseY);
Secure_vault_key5 = map(mouseX, 14, 80);
}
function mousePressed()
{
console.log("mousePressed");
Secure_vault_key0 = random(2,14);
Secure_vault_key3 = map(mouseX, 14, 76);
}
function keyPressed()
{
console.log("keyPressed");
Secure_vault_key2 = key;
}
function mouseRealesed()
{
console.log("mouseReleased");
Secure_vault_key1 = random(2,8);
}
///////////////DO NOT CHANGE CODE BELOW THIS POINT///////////////////
Check out the p5.js reference page for map() : https://p5js.org/reference/#/p5/map
It looks like you're only using three parameters in your map functions, and it requires five (with an optional sixth parameter). The five necessary parameters are as follows (in this order):
variable you want to map the value of (in your case mouseX)
the current minimum of that value (if you're working with mouseX, you most likely want to use zero)
the current maximum of that value (again, if you're working with mouseX, you probably want to use the width of your canvas here, which you can do using the built in width variable or hardcoding in the value)
the new minimum value you want to be stored in one of your Secure_vault variables
the new maximum value you want
It might seem silly or redundant that you need to specify the current maximum and minimum of a built-in variable like mouseX, but it's just one of those programming things where the computer demands as much explicit instruction as possible in order to properly execute your instructions.
Look at the second example on the reference page linked above for a good example of using the map() function with mouseX. And if you're going to be working in p5.js beyond this project these reference pages are a really great place to look for answers to all kinds of questions!
update!! I just corrected in below code. use height and width
/*oh I also met such issues, I know I have to define five arguments, I just can't understand what the second and third arguments should be, I wrote 0,mouseY/X, but it's not correct.
only SecretStoreCombination0 is correct, I've used up the chances today, I will try tomorrow!*/
function keyReleased(){
SecretStoreCombination0 = random()*10+1;
SecretStoreCombination2 = key;
}
function mouseReleased(){
SecretStoreCombination1 = map(mouseY,0,height,3,13);
SecretStoreCombination4 = map(mouseY,0,height,20,79);
}
function mousePressed(){
SecretStoreCombination3= map(mouseX,0,width,6,69);
SecretStoreCombination5= map(mouseY,0,height,16,73);
}

Three.js - Spawn an object every x seconds and move each object forward (along Z)

I am making an endless runner style game using Three.js. The basic set up of the scene and idea for the game is a long moving road with cars coming towards you that you have to dodge out of the way of. I am still at the early stages of creating this game, and so my first problem is that I need the hero character (who is dodging the cars) to seem like he is moving forwards, and at the same time have the cars seem like they are moving (faster) towards the hero character.
My thinking was to create road strip objects (the white lines in the middle of a road), and have them move towards the hero character, who is at (0, 0), at a certain speed.
I have successfully created a road strip object and positioned it at the very back of the road (RoadStrip.mesh.position.z = -5000;). Here is my code for that:
var objectRoadStrip = function() {
this.mesh = new THREE.Object3D();
this.mesh.name = "roadStrip";
geomRoadStrip = new THREE.BoxGeometry(20, 11, 300);
matRoadStrip = new THREE.MeshPhongMaterial({color: Colors.white});
RoadStrip = new THREE.Mesh(geomRoadStrip, matRoadStrip);
RoadStrip.name = 'roadStripName';
this.mesh.add(RoadStrip);
}
function createRoadStrip() {
new objectRoadStrip();
RoadStrip.position.y = -72.5;
RoadStrip.position.z = -5000;
scene.add(RoadStrip);
}
In the render() function, which is the function that loops over every frame and is called last to make sure the camera and scene update every frame, I am able to successfully move this strip forwards along the z axis by 10 every time render() is called. I also added some code so that when the RoadStrip touches (0,0), it is removed from the scene. See this below:
function render(){
// moves RoadStrip towards (0,0). When it reaches z = -150, remove that strip from the scene
if (RoadStrip.position.z <= -150) {
RoadStrip.position.z += 10;
} else {
scene.remove(RoadStrip);
}
renderer.render(scene, camera);
requestAnimationFrame(render);
}
I have also added the following code to the init() function which creates a RoadStrip when the scene is created, and the continues to create a RoadStrip every 10 seconds (roughly every time the RoadStrip reaches (0,0).
createRoadStrip();
setInterval( function() {
createRoadStrip();
}, 10000);
This is similar to the effect I'm going for, but read The Problem section below where I explain what I truly need.
The Problem
I need to spawn a RoadStrip every x amount of seconds (still to be decided once I get it working, but lets say 3 seconds for now) continuously. Each RoadStrip needs to move towards (0,0) with z += 10 independently. When a RoadStrip instance reaches (0,0), it should be removed from the scene, but other RoadStrips should continue to spawn regardless every 3 seconds at the original position (z = -5000).
My Attempts / Solution Ideas
I've done a lot of reading on this, trawling through code from other people's endless runner games and reading through SO answers but nothing seems to have worked. Below are some of the things I have tried, or some things that I feel would work but I am not doing right/don't have a good understanding of:
Idea: Instead of calling the createRoadStrip() function inside a setInterval, push a RoadStrip object to an array every 3 seconds, and then call that array and move the array along the z axis by += 10.
Possible solution help: I tried changing the setInterval to less than 2 seconds instead of 10 seconds. This caused the RoadStrip to move along the Z axis for 2 seconds as expected, but of course, after 2 seconds another RoadStrip was spawned, and so the first RoadStrip stopped moving along the Z axis, and the new one did instead (for 2 seconds as well) and this process repeated infinitely. This is so close to what I need, but I need each RoadStrip to continue moving, and be remove from the scene when it reaches (0,0)
Thanks for taking the time to read my Question, I look forward to your solutions!
Examples of similar style games: First, Second.
Thanks to #prisoner849 and his link to this thread, I managed to find the solution to the problem, and so I am writing an answer here for anyone who comes across this with the same problem in the future!
I read through the thread and found a link to this JSFiddle, that includes a successful animation similar to the one I was trying to achieve, and I would highly suggest studying the code of that JSFiddle to fully understand how to create an endless runner effect.
Here is a detailed explanation of how to do this:
Instead of infinitely creating objects and have them animate forwards until they reach the end point and disappear (like I originally thought was the right solution), you have to create an array of objects and animate that instead.
Here is my code for doing this:
var roadStripArray = []
function objectRoadStrip() {
for (var i = 0; i < 100; i++) {
geomRoadStrip = new THREE.BoxGeometry(20, 11, 500);
matRoadStrip = new THREE.MeshPhongMaterial({color: Colors.white});
RoadStrip = new THREE.Mesh(geomRoadStrip, matRoadStrip);
RoadStrip.position.set(0, -72.5, -150 - i * 1250);
RoadStrip.receiveShadow = true;
scene.add(RoadStrip);
roadStripArray.push(RoadStrip);
}
}
The for loop has the code i < 100 as my road is quite long and therefore needs a lot of strips
This code:
RoadStrip.position.set(0, -72.5, 0 - i * 1250);
sets the position of each strip to be different from each other, and the number 1250 is the distance between each strip
After creating the objects, you must animate them in the render() function. You have to set them to move along the Z axis, and then create an if statement that says "if any strip reaches the end point (where you want it to disappear), reset it's position back to the start (i.e. the start of the road for me). This means you are constantly looping through your array of objects, and therefore don't infinitely create them.
Here is the code that animates the strips:
// loop that runs every frame to render scene and camera
var clock = new THREE.Clock();
var time = 0;
var delta = 0;
var direction = new THREE.Vector3(0, 0, 1);
var speed = 2000; // units a second - 2 seconds
function render(){
requestAnimationFrame(render);
delta = clock.getDelta();
time += delta;
roadStripArray.forEach(function(RoadStrip){
RoadStrip.position.addScaledVector(direction, speed * delta);
if (RoadStrip.position.z >= 10000) {
RoadStrip.position.z = -10000;
} else {
}
});
renderer.render(scene, camera);
}
The code that moves each strip is:
RoadStrip.position.addScaledVector(direction, speed * delta);
You can read more about .addScaledVector here, but essentially this is the code that animates the strip.
The if statement then checks if the strip touches 10000 (i.e. the end of the road), and if it does, sets the position of that strip to -10000. That strip then moves back towards the end point along the Z axis.
We wrap this all in a forEach function to loop through each RoadStrip in the array and animate them all in the same way. We need to animate them individually so that we can detect when one of them reaches the end of the road.
Thanks, hope this helps!
Usually this kind of scenario is best handled with some kind of particle-system like approach: you don't insert/remove objects continuously to the scene but create a set of objects during initialization, let's say the player can only see 10 road stripes at a time, and your game logic is always moving those 10 stripes, updating positions as needed, once one strip goes out of the field of view, it is recycled at the begining and so on. I don't think you will find a canned solution that does exactly what you are looking for, you would need to come up with the update logic that suits best your game.
I have an example of custom particle system there. Once a particle is getting out of scope, it is made available for the system when it needs to emit a new particle. The number of particle in the pool is always constant and can be defined by the user here just for testing purpose. A similar approach can be used to manipulate your infinite stripes. The repo for that code is available at https://github.com/leefsmp/Particle-System but you can find many other particle system implementations out there, this one is a bit specific to my needs.
Hope that helps.

THREE JS how to detect if one object is facing a selected point

So I'm very new to THREE JS and I've been trying to figure this out for a few hours now, but how do I determine whether or not a mesh is facing a selected point? Essentially what I have is an RTS style game, where you can select a character and select where he moves to. Currently you can select the character and you can select and where you want it to move to on the map and it will start walking, however I can't figure out how to determine if it is facing the right direction. I don't want to use lookAt because I want the mesh to turn while it walks forward, and not do anything instantaneously.
Ideas?
a simple solution is to select arbitrary look vector
var lookVector = new THREE.Vector3(0,0,1);
and when you need to do some check transform a copy of this vector with mesh matrix (make sure matrix is updated and count in the geometry transformations if you did any)
var direction = lookVector.clone().applyMatrix4(mesh.matrix);
var origin = mesh.boundingSphere.center;
var lookVectorAtThisTime = direction.sub(origin);
then calculate the angle to your point of interest
var vectorToPOI = POI.sub(origin);
var angle = lookVectorAtThisTime.angleTo(vectorToPOI);
if(angle < minAngle)
{
//looking at the point
}
you can also calculate your look vector directly from geometry or some other way origin vector can be something else than the center of the object, but this should get you on the right path..

Three.js: orbitcontrols plus camera tweens = offset headaches

I'm being driven mildly insane looking for a working combination of interactions. I basically need to make something like a google earth style setup, where you can:
orbit round an object, highlighting the centre-most location,
click a menu link and animate rotation of the object to a particular 'location' (highlighting the new location).
I'm using orbitcontrols for the first bit, and was hoping to tween the orbitcontrols directly for the menu link bit, but couldn't get the camera to move in the right path. SO I put the camera inside an object, and whilst orbitcontrols handles the camera, the tweening is done on the object ('camHolder') instead.
So there are two moving parts (cam controlled by user's mouse, camHolder tweened into position by link clicks), and when either one moves, the rotational difference between them changes. In order to highlight the right 'point' between these two rotation values, I need to keep track of the offset between the two. Basically (simplified version of the codepen):
// ------- MOUSE/CAMERA INTERACTION ---------
// location of points (in radians):
var pointLongs=[-3,-2,-2.5,-2,-1.5,-1,-0.5,0,1,2,2.5,3];
// most recent point highlighted (by menu click):
var currentPoint = 5;
// get diff (in radians) between camera and current point
var pointDistance = pointLongs[currentPoint] - camera.rotation.y;
// the offset rotation of cam (i.e. whats closest to the front):
var offset = camera.rotation.y + pointDistance;
// find the closest value to offset in pointLongs array:
var closest = pointLongs.reduce(function (prev, curr) {
return (Math.abs(curr - offset) < Math.abs(prev - offset ) ? curr : prev);
});
closestPointIndex = pointLongs.indexOf(closest);
// highlight that point (raise it up):
scene.getObjectByName(pointNames[closestPointIndex]).position.y = 20;
This seems to work as long as pointDistance is above 0, but if not, the tracking of the current 'point' only works on part of the mouse orbiting circle, when it should work all the way round.
Codepen here: http://codepen.io/anon/pen/BNPWya (the Sole tween code is embedded in there so skip the first chunk...). Try rotating the shape with the mouse, and notice that the points aren't raised all the way around. Click the random / next menu buttons, and the 'gap' changes... Sometimes it does go all the way round!
I've tried changing just about all the values (pointLongs all positive values; initial rotation of camera, etc) but my maths is generally terrible, and I've lost the ability to see straight - anyone have any ideas? Please ask if something doesn't make sense!
I'd add the tag 'HelpMeWestLangleyYoureMyOnlyHope' but I don't have enough reputation :D
TLDR; rotation of object and camera won't 'sync', need to either correct the difference, or maybe find a way to tween position/rotation of orbitcontrols?

Acceleration on Keypress

I'd like to add acceleration in javascript. For instance, if I press and hold a button, then the object moves accelerated in the chosen direction.
Could someone suggest please, how to start this one? Should I log the time of the keypress? If yes, how can I do this?
Thank you
You should do dome research on Kinematics.
You can do this with a simple loop that models the correspondence between position, velocity and acceleration.
I've made a simple example (using jQuery for accessing DOM/CSS):
var position = 0;
var velocity = 0;
var acceleration = 0.1;
var $thing = $("#thing");
var loop = function () {
$thing.css("left", position + "px");
position = position + velocity;
velocity = velocity + acceleration;
}
window.setInterval(loop, 100);
You can run it here: http://jsfiddle.net/QAn3Z/
Now you just need to add keypress detection.
This should get you started. Come back with more specific questions or problems, they will be less downvoted than "how should I begin" ;-)

Categories

Resources