I am a beginner with THREE.js and currently have a animation that spins a 3D model around its Y axis but for the website I am creating I need to rotate it back to origin during the timespan of 90 frames. I have tried using a various different code snippets but the problem is that it seems to work half the time and the other half it totally messes it up. I believe that it messes up more if I let it spin for a while.
Here is my current code for the rotation:
//angle
angle = ((room.rotation.y * 180) / Math.PI) % 360;
total_deg = room.rotation.y;
//for calculating the lap:
if(angle > 0) {
positiv = true;
} else {
positiv = false;
}
if(angle < last_angle) {
direction = "down";
} else {
direction = "up";
}
if(direction == "up" && positiv == true) {
lap = 1;
} else if(direction == "down" && positiv == true) {
lap = 2;
} else if(direction == "down" && positiv == false) {
lap = 3;
} else if(direction == "up" && positiv == false) {
lap = 4;
}
if(last_lap == 4 && lap == 1) {
room.rotation.y = 0;
}
last_angle = ((room.rotation.y * 180) / Math.PI) % 360;
//rotating it back depending on what lap it currently is on
if(lap == 4) {
room.rotation.y += -total_deg / 90;
}
if(lap == 3) {
room.rotation.y += -(Math.PI - Math.abs(total_deg)) / 90;
}
if(lap == 2) {
room.rotation.y += (Math.PI - Math.abs(total_deg)) / 90;
} else {
room.rotation.y -= total_deg / 90;
}
//reset the rotation when the room has spun a lap - don't know why this is works but seems to fix some of the rotation problems
if(last_lap == 4 && lap == 1) {
room.rotation.y = 0;
}
Have been stuck with this problem for days so any help would be appreciated
I hope I'm understanding your objective properly but to me it seems that there may be some confusion with degrees and radians as the units. Three.js uses radians, but I'm seeing 360 in your code which I'm unsure about.
Anyway this code seems like what you're trying to do, notice how it divides 2 pi (one rotation in radians) into 90 frames.
var i=0;
function update( event ) {
//angle
if(i++<90){
this.rotation.y += 2*Math.PI/90;
}
}
I figured it out using a Quaternion of the objects first rotation and rotating to that later. This example was very helpful: https://threejs.org/examples/#webgl_math_orientation_transform
OK, so I am making a Pacman game using HTML5 . the problem is whenever I hit one of the brick blocks I want the sprite to stop moving but it keeps going until it hits the left most brick object.
how do I fix this? please help... here is the code I'm using to make the sprite stop.
here is all my code, if you have time, please parse it, and tell me what I have done wrong.
function init(){
var canvas=document.getElementById("ctx");
var ctx = canvas.getContext("2d");
var player = {sx:6,sy:6,sw:15,sh:15,x:230,y:377,w:20,h:20}
var ss = new Image();
ss.src="SS.png";
var right=false,left= true,up = false,down = false
var b = [{x:0,y:0,w:25,h:((canvas.height/2)-25)},{x:0,y:((canvas.height/2)),w:25,h:((canvas.height/2))},{x:50,y:25,w:50,h:50},{x:125,y:25,w:75,h:50},{x:225,y:0,w:25,h:75},{x:275,y:25,w:75,h:50},{x:375,y:25,w:50,h:50},{x:50,y:100,w:50,h:25},{x:125,y:100,w:25,h:125},{x:125,y:150,w:75,h:25},{x:175,y:100,w:125,h:25},{x:225,y:125,w:25,h:50},{x:325,y:100,w:25,h:125},{x:275,y:150,w:75,h:25},{x:375,y:100,w:50,h:25},{x:25,y:150,w:75,h:75},{x:375,y:150,w:75,h:75},{x:375,y:250,w:75,h:75},{x:25,y:250,w:75,h:75},{x:125,y:250,w:25,h:75},{x:325,y:250,w:25,h:75},{x:175,y:300,w:125,h:25},{x:225,y:325,w:25,h:50},{x:50,y:350,w:50,h:25},{x:75,y:350,w:25,h:75},{x:125,y:350,w:75,h:25},{x:275,y:350,w:75,h:25},{x:375,y:350,w:50,h:25},{x:375,y:350,w:25,h:75},{x:25,y:400,w:25,h:25},{x:125,y:400,w:25,h:75},{x:50,y:450,w:150,h:25},{x:275,y:450,w:150,h:25},{x:325,y:400,w:25,h:50},{x:425,y:400,w:25,h:25},{x:175,y:400,w:125,h:25},{x:225,y:425,w:25,h:50},{x:450,y:0,w:50,h:((canvas.height/2)-25)},{x:450,y:(canvas.height/2),w:50,h:((canvas.height/2))}];
function gen(){
for(var i=0;i<b.length;i++){
ctx.fillStyle="blue"
ctx.fillRect(b[i].x,b[i].y,b[i].w,b[i].h)
}
ctx.drawImage(ss,player.sx,player.sy,player.sw,player.sh,player.x,player.y,player.w,player.h)
}
function move(){
for(var i=0;i<b.length;i++){
//((a.x + a.width) < b.x)
if(left &&
player.x > b[i].x && (player.x + player.w) < (b[i].x + b[i].w) &&
player.y > b[i].y && (player.y + player.h) < (b[i].y + b[i].h)) {
// here you can tell that the user is colliding an object
player.x-=1
}
else {
}
}
}
function animate(){
ctx.save()
ctx.clearRect(0,0,canvas.width,canvas.width);
gen()
move()
ctx.restore();
}
var ani = setInterval(animate, 30)
}
window.addEventListener("load",function(){
init()
})
First, I can see a problem with the first part of your if condition:
left = true && ...
Should be
left === true && ...
Or even better
left && ...
Now for the collision part it usually is top-left or in the middle of the object
I'd suggest this top-left origin collision check:
if(left &&
(player.x >= b[i].x && player.x + player.w <= b[i].x + b[i].w) &&
(player.y >= b[i].y && player.y + player.h <= b[i].y + b[i].h) {
// here you can tell that the user is colliding an object
}
It checks several cases, this part
(player.x >= b[i].x && player.x + player.w <= b[i].x + b[i].w)
Will meet requirements if the player's x (with its width component) inside the occupied x range of the current object
The second part
(player.y >= b[i].y && player.y + player.h <= b[i].y + b[i].h)
Will meet requirements if the player's y (with its height component) is inside the occupied y range of the current object.
It will only execute the if statement if the condition is satisfied for both of the above cases.
You can tell if you should reposition the player on the left or on the right, by substracting the players x component to the object's x component, same goes for top or bottom with y component. The previous sentence is only valid if you move in a grid cell by cell.
Essentially, what I'm doing is placing a bunch of random width/height rects onto a grid (near the center of it), then pushing them all away from each other until none of them overlap. I have another version where I check for collisions before I place them on the grid, but that's not what I'm going for in this build.
I'm wondering if someone can explain a better way to go about this?
What I've tried so far is something similar to:
let r1/r2 = rect1/rect2
do {
var ox = Math.max(0, Math.min(r1.x + r1.w, r2.x + r2.w) - Math.max(r1.x, r2.x)),
oy = Math.max(0, Math.min(r1.y + r1.h, r2.y + r2.h) - Math.max(r1.y, r2.y)),
dx = r2.x - r1.x,
dy = r2.y - r1.y;
if (ox > 0 && oy > 0) {
if (ox >= oy) {
if (r1.x >= r2.x && Math.random() > .1) {
r1.x += ox;
spaced = true;
continue;
} else {
r1.x -= ox;
spaced = true;
continue;
}
} else {
if (r1.y >= r2.y && Math.random() > .1) {
r1.y += oy;
spaced = true;
continue;
} else {
r1.y -= oy;
spaced = true;
continue;
}
}
}
} while ( /* stuff */ )
the random is only there because I will run into times when a certain rect gets pushed back and forth and never gets free and causes an infinite loop. This way is horribly inefficient however.
I believe what your trying to accomplish is known as a packing problem http://en.wikipedia.org/wiki/Packing_problem. If you just search stack overflow for "2d bin packing" you should be able to find all you need to roll a much more efficient algorithm.