I'm attempting to make a Red Alert style game, just to sharpen my JS skills , and get a basic understanding of game development. I'm attempting to move a block mesh from one part of the ground to another. However, it moves the block instantly, instead of animating it.
Here's my babylonjs-playground...
http://www.babylonjs-playground.com/#OYE6Q
I think the issue's with this block of code...
var moveUnit = function (position, item) {
if (position.x > 0) {
while (item.position.x < position.x) {
item.position.x += 0.001;
}
} else {
while (item.position.x > position.x) {
item.position.x -= 0.001;
}
}
if (position.z > 0) {
while (item.position.z < position.z) {
item.position.z += 0.001;
}
} else {
while (item.position.z > position.z) {
item.position.z -= 0.001;
}
}
}
while (item.position.x < position.x) {
item.position.x += 0.001;
}
By using the while loop, your are updating position to the final position in increments within the same frame of the game. It is equivalent to saying:
item.position.x = position.x;
Because of this, you see it jump from its initial position to its final position from one frame to the next; regardless of how you update the position.
If you want to simulate movement over time, you need to move the object in increments toward it's goal over multiple frames. If the increments are chosen correctly, and the frames are fast enough, it will look like smooth movement.
To accomplish this, objects need to have some idea of where they are moving across frames, and you need to introduce the concept of time into your game.
Take a look at this tutorial for an example of the concept.
BABYLON.js has a built in animate function, which handles time constraints for meshes automatically. Here's a link to a working example!
http://www.babylonjs-playground.com/#OYE6Q#4
Related
I am creating a project in which a body is picked up and thrown by the user (with a mouse constraint). The body is set so that it can pivot about the constrain point. I need to find out, from the moment that it is let go, how many times it fully rotates (+-360 degrees) before landing. Reading the documentation, the only thing that I could find regarding the rotation was Matter.Body.rotate() which actually just sets the rotation of a body instead of recording it. How should I go about this?
Basically: How can I count an objects rotations?
This worked for me tbh:
var rad = 6.28;
var nrad = -6.28;
Events.on(engine, "tick", function () {
if(boxA.angle > rad){
rad+=6.28;
nrad+=6.28;
hrt +=1;
//hrt is the rotation c0unter
}
if (boxA.angle < nrad){
nrad-=6.28;
rad-=6.28;
hrt +=1;
}
rnum.innerHTML = "Spins: " + hrt;
fnum.innerHTML = fcounter; });
New to p5.js and trying to learn more every day. Basically, I am currently learning about particle systems and objects, and getting confused by the amount of code. Anyways, I'd like that on function mousePressed(), an array of particles (particle system) that I've created appears. It'd also be awesome if the particle system could trail the position of the mouse. So, basically, if you click your mouse on the screen particles appear in that position, and also trail your mouse.
I can't figure out what I'm missing in the code. I feel kind of lost about what half of it is even doing (my professor wrote a lot of it). When I add in the mousePressed function, everything goes to pot. I feel like I'm too overwhelmed to even know what's missing. Any help, plus detailed insight into what I need to do and why that solution works would be super appreciated. Thank you!
var particles = [];
var now = null;
function setup() {
createCanvas(windowWidth, windowHeight);
}
function draw() {
background(255, 25, 25);
function mousePressed() {
particles.push(new Particle(new p5.Vector(mouseX, mouseY)));
//particles.push(new Particle(new p5.Vector(width / 2, height / 1.5)));
for (var i = 0; i < particles.length; i++) {
// if our particle is dead, remove it
if (particles[i].lifespan <= 0) {
//splice is a way of removing a specific
//element from an array
particles.splice(i, 2);
} else {
particles[i].update();
particles[i].display();
}
//this.particle = new ParticleSystem(createVector(mouseX, mouseY));
// patricles.push(p);
}
}
}
function Particle(loc) {
this.loc = loc;
this.acc = new p5.Vector();
this.vel = new p5.Vector(random(-100, 100), random(-2, 0));
this.lifespan = 555;
}
Particle.prototype = {
constructor: Particle,
update: function() {
this.vel.add(this.acc);
this.loc.add(this.vel);
this.lifespan -= 4.0;
},
display: function() {
stroke(random(0), this.lifespan);
fill(random(255), random(255), random(255))
ellipse(this.loc.x, this.loc.y, 20, 20);
}
}
First of all, your mousePressed() function is inside your draw() function. That doesn't make a ton of sense. You want your mousePressed() function to be at the same level as your draw() function.
function draw(){
//draw code here
}
function mousePressed(){
//mousePressed code here
}
If I were you, I would start smaller. Can you create a program that draws a single ellipse? Can you then make it so that single ellipse appears when you click the mouse? Then can you have that ellipse follow the mouse? Only if you can get that working perfectly by itself, then you should start thinking about adding multiple ellipses.
You're trying to go from your end goal and work backwards, which is just going to confuse you. Instead, start from the simplest sketch possible and take one small step at a time. Then if you get stuck you can post an MCVE along with a specific question, and it'll be easier to help you.
I'm encountering a collision issue that I can't quite figure out. The point of my program is to generate a random number of circles (between 2 and 15) with random velocities in a bounding box that is 1920x900. If they touch each other, they're supposed to fly off in opposite directions (not great physics, I know, but that'll come later.)
To do this, I've got four arrays: two for the coordinates of the circles (xcords[] and ycords[], and two for the momentum of each circle (xdirs[] and ydirs[]).
Here's my collision function
function collides(x, y)
{
if(Math.hypot(xcords[y]-xcords[x], ycords[y]-ycords[x]) < 50)
{
return true;
}
else return false;
}
When I hardcode certain values, such as
if(collides(xcords[1],xcords[0])
{
xdirs[0] *= -1;
xdirs[1] *= -1;
ydirs[0] *= -1;
ydirs[1] *= -1;
}
then it works fine. The two circles I hardcode will collide correctly. But when I try to apply this to every circle:
for(i=0; i<circles; i++)
{
for(j=0; j<circles; j++)
{
if(collides(xcords[i], xcords[j]))
{
xdirs[i] *= -1;
xdirs[j] *= -1;
ydirs[i] *= -1;
ydirs[j] *= -1;
}
}
}
Then the circles just ignore each other, and I have no idea why. This is the only time I use a double for loop in this code, but I do the first for loop multiple times, and it handles it correctly for every other function.
Here's a jsfiddle for it. https://jsfiddle.net/sekbr0pg/
The bounding box is a little off, but it's enough to see that the collision is wonky.
Let's take circle 1 and circle 2. You want to check whether they collide or not only once. Is the following loop good for that?
for(i=0; i<circles; i++) {
for(j=0; j<circles; j++){
// if collides ...
}
}
Answer is no, and the reason is that they will run twice, for i=1 and j=2 and i=2 and j=1. So basically it won't change anything since -1*-1 = 1. In your loop change j=0 to j=i+1.
Also your collides function accept circles, so I think collides(i,j) will do the job.
I am making a little game using HTML5 Canvas and javascript. I am so far that I have a kite moving some sort of power up on collision and an obstacle on collision.
Now I'm at the point I want to add lives and when you hit an obstacle your life will decrease 1.
I tried some stuff and when you hit an obstacle the life decreases but it decreases constantly and the player image gets removed instead of the obstacle image.
here is the life thing you can check all the code there.
http://nickzijlstra.com/kite
Here the code I think is the most important for the problem.
function hitObject(player, obj){
var a = (obj.x - player.x),
b = (obj.y - player.y),
c = Math.sqrt(a*a + b*b),
r0 = player.image.width/2,
r1 = obj.image.width/2;
if (c < r0+r1) {
player.drawable = false;
lifes -=1;
window.location.reload(true);
}
}
If someone sees the problem or knows the solution I would really appreciate it!
The reason the player disappears is because of this line in the hitObject function:
player.drawable = false;
This will cause the player to not be drawn because of this condition in your drawing function:
if (player.drawable == true) {
context.drawImage(player.image, player.x, player.y, player.image.width, player.image.height);
}
I presume you actually want to move the obj back to a random spot on the top of the screen if the player gets hit. It doesn't do this at the moment, which is why the lives go down rapidly: the object hits the player, it removes a life, and then the next frame it hits the player again (even though the player isn't visible).
What you might want is something like:
...
if (c < r0+r1) {
lifes -=1;
// Respawn the object.
obj.y = -50;
obj.x = Math.random() * canvas.width;
...
At a guess, I'd say that you should replace the
player.drawable = false;
with
obj.drawable = false;
and wrap the whole collision detection inside of an if obj.drawable=true so that removed obstacles won't collide with the kite.
I have an Array of 16 billiard balls in JS and want to move each ball smoothly with its direction and speed.
For that I set up a timer, calling UpdateThis() every 42ms (for 24 fps).
The problem is that UpdateThis() takes 53ms as firebug states.
Now UpdateThis iterates over every ball and calls UpdateBall(ball).
I assume that the problem lies there.UpdateBall looks like this:
function UpdateBall(ball)
{
if(ball.direction.x != 0 && ball.direction.y != 0) {
//ball moving!
for(var i = 0; i < balls.length; i++) {
//CheckCollision(ball, balls[i]); //even without this it takes 53 ms!
}
var ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Multiply Direction with speed and add to position!
if(ps.x < Bx || ps.y < By || ps.x > Bw || ps.y > Bh) { //Bounce off the wall!
ball.direction = VMul(ball.direction, -1); //Invert direction
ball.speed *= 1;
ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Calc new position!
}
ball.position = ps;
ball.MoveTo(); //See explanation at the bottom.
ball.speed *= GRK; //Gravity
if(ball.speed < 0.05) {
ball.speed = 0;
}
}
}
it seems that the most time is spent in ball.MoveTo() which looks like this:
function()
{
this.image.style.left = this.position.x + "px";
this.image.style.top = this.position.y + "px";
}
-- UPDATE --
function UpdateThis() {
for(var i = 0; i < balls.length; i++) {
var cur = balls[i];
UpdateBall(cur);
balls[i] = cur;
}
}
and onload looks like
nx = setInterval(function() { UpdateThis(); }, 42);
Does somebody have any ideas on how to speed this up?
-- UPDATE 2 --
You can download the folder with the HTML file here (the password is password)
What about separating the position updates from the drawing? So have something like this (untested code):
function DrawBall(ball)
{
ball.MoveTo(); //Take this line out of UpdateBall
}
-
function UpdateThis() {
for(var i = 0; i < balls.length; i++) {
var cur = balls[i];
UpdateBall(cur);
balls[i] = cur;
}
}
-
function DrawThis() {
for(var i = 0; i < balls.length; i++) {
DrawBall(balls[i]);
}
setTimeout(function() { DrawThis(); }, 42);
}
-
nx = setInterval(function() { UpdateThis(); }, 42);
setTimeout(function() { DrawThis(); }, 42);
If indeed it's the moving of the position that's slow, this way the logic update still happens at 42ms, and the framerate is no faster than 42ms but it can skip frames. (I haven't actually tried this, so this is all theoretical and you may need to tweak some stuff)
Why moving may be (and most probably is) slow?
Move functionality could be slow, because it has more things to do than simple variable assignment. It has to actually render some element to some other place. You could test this if you run this on IE9. I anticipate it should run faster since it uses hardware video acceleration.
As for the other routine I hope others will dissect it. :)
Questions for you
Can you please describe how do balls move? Sporadically? How do you call UpdateBall() for each ball? Do you queue those calls?
Provide VMul and VAdd functionality
Have you played with styling? Maybe relative positioning of balls' immediate parent may speed up rendering. And setting overflow:hidden on it as well. I don't know. Depends on how you've done it. Hence a JSFiddle would be very helpful.
A suggestion
Instead of using setInterval to call your function you should maybe just queue them and let them execute as fast as it gets. And just for the sake of it, provide a central setInterval with some watcher that they don't run too fast.
But I guess that it still utilizes your processor to 100% which isn't good anyway.
Very important note: Don't run you app while Firebug's enabled because it's a well known fact that Javascript executes much slower when Firebug is running.
That's tough, if MoveTo() is in fact your bottleneck, since there is not a whole lot going on there. About the only things I can think of, right off hand, are
1) Cache the style property of the image and position for faster lookups. Everytime you see a dot in the object chain it's requires stepping through the scope chain. Ideally you can cache this property at the time the parent of MoveTo() is constructed.
2) Are the 'px' strings required? It may result in an invalid CSS specification, but it may still work. I have a hard time believing 2 string concats would really change all that much though.
The main problem here is likely the fact that anytime you change the DOM, the browsers re-flows the entire page. Your only other option may be to refactor such that instead of changing the styles, you actually remove the previous contents, and replace it with the a document fragment describing the new state. This would result in only 2 re-flows for the entire step (1 for removal, 1 for addition), instead of 2 for each ball.
EDIT: Regarding #1 above, when I say cache, I don't mean just locally in the function call. But perhaps as a closure in the parent object. For example:
var Ball = function(img){
var style = img.style;
var posX;
var posY;
function MoveTo(){
style.left = posX + "px";
style.right = posY + "px";
}
};