p5.js creating a new Vector error - javascript

So i'm trying to rewrite some of main proccessing sketches to p5.js, but (there is always a but..) i have a problem with creating Vecotrs. I think i'm lacking some simple java script uderstanding here.
So i use the example provided with p5.js, and my code looks like that:
var location ;
function setup() {
createCanvas(1000, 1000);
background(0);
location = new Vector(0, 0);
//location = createVector(0, 0);
//location = new p5.Vector(0, 0);
}
function draw() {
ellipse(location.x, location.y, 80, 80);
}
function Vector (x,y) {
this.x = x;
this.y = x;
}
I tryied 3 ways of creating vectors, the one right now, with creating custom "class" Vector, and those 2 commented out. And if i try it out, i have page not found and address bar is changed to "address to my index.html/p5.Vector%20Object%20:%20[0,%200,%200]".
I really have now idea what is wrong.

The variable name was the culprit. I was actualy accessing window.location . Simple name change did the trick.

Related

How to enable collisions in matter.js?

I'm trying out matter.js on p5.js.
I'm trying to make a simple Top Down simulation where bodies collide with each other when trying to move.
Here's my code:
let engine,world;
function setup() {
createCanvas(400, 400);
engine = Matter.Engine.create();
world = engine.world;
m1 = Matter.Bodies.rectangle(50,50,50,50);
m2 = Matter.Bodies.rectangle(100,50,50,50);
Matter.World.add(world,m1);
Matter.World.add(world,m2);
}
function draw() {
background(220);
Matter.Body.translate(m1,{x: 1,y: 0});
pos1 = m1.position;
pos2 = m2.position;
rectMode(CENTER);
rect(pos1.x,pos1.y,50,50);
rect(pos2.x,pos2.y,50,50);
}
My intention was to make body m1 push body m2 when trying to move in his direction. Unfortunately m1 is just going through m2. How do I make them collide?
I've seen that I can add stiffness to the body's options but I don't think that will help me if they are not colliding in the first place.
I just found the problem: the translate function won't ever check collisions. Instead I used the setVelocity function and updated the engine every frame.
Matter.Engine.update(engine);
Matter.Body.setVelocity(m1,v1);
I also had to turn off the gravity in the setup.
engine.world.gravity.y = 0;

How to pass object to animation function in JavaScript?

I have been trying to make a JavaScript animation of moving circle in HTML Canvas without using global variables. I am using requestAnimationFrame function. Since JavaScript does not support passing variable by reference, I tried creating a Circle class:
class Circle{
constructor(x, y, dx, dy) //set initial position and velocity of circle
{
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
}
}
function moveCircle(circle, other variables)
{
//clear canvas
//calculate new position and velocity using circle.x, etc.
//save new values to the object
//draw new circle into the canvas
requestAnimationFrame(moveCircle);
}
function button()//function called after click on button
{
//initial settings of canvas, intial condition
circle = new Circle(x, y, dx, dy);
moveCircle(circle, other vars);
}
This makes one frame and then throws error "Cannot read property 'x' of undefined". What am I doing wrong? Is there any other way of doing this, while avoiding global variables?
First of all, you don't need to create a class you can just pass the coordinates in an object or as separate arguments.
Secondly you should use Function#bind on requestAnimationFrame to pass the same arguments to next call.
Example using object:
function moveCircle(circle) {
console.log(circle.x);
if (circle.x) {
circle.x -= circle.dx;
requestAnimationFrame(moveCircle.bind(null, circle));
}
}
function button() {
moveCircle({
x: 500,
y: 0,
dx: 20,
dy: 0
});
}
button();
Example without object:
function moveCircle(x, dx) {
console.log(x);
if (x) {
requestAnimationFrame(moveCircle.bind(null, x - dx, dx));
}
}
function button() {
moveCircle(500, 20);
}
button();
To keep things simple you could use a closure to create a handler that internally knows what your circle looks like and how it should move. A closure is simply a function that defines its own variables locally, then returns a function that can access those.
We want to return a function that only accepts one argument: time, since that is the argument passed into every handler in the AnimationFrame by the browser. Then we want the closure function to draw into the globally defined canvas. Have a look here:
const canvas = document.body.appendChild( document.createElement( 'canvas' ) );
function makeMovingCircle( canvas, x, y, radius, distance, duration ){
// Lets get the context to draw here so we only need to fetch it once and store it, saving some computing time in favour of storing into memory.
const ctx = canvas.getContext( '2d' );
// We need to return a named function here so it can interally call itself again in requestAnimationFrame
return function AnimationHandler( time ){
// Lets just calculate an offset here based on the distance and duration we passed in above.
const progress = (time % duration / duration) * distance;
ctx.clearRect( 0, 0, canvas.width, canvas.height );
ctx.beginPath();
ctx.arc( x + progress, y, radius, 0, Math.PI*2, true );
ctx.stroke();
// Now call the named handler for the next animationFrame
window.requestAnimationFrame( AnimationHandler );
}
}
// Now lets make an animation handler and add it to the animationFrame. If you ever want to cancel it, you might want to store it in a global variable though so you can call cancelAnimationFrame on it.
window.requestAnimationFrame(
makeMovingCircle( canvas, 15, 15, 10, 100, 2000 )
);
I did a quick example from my memory:
const circle = $('#circle');
class Main {
constructor() {
}
start() {
requestAnimationFrame(this.loop.bind(this))
}
loop() {
const pos = circle.position();
// speed is a constant 1,1. But you could replace it by a variable
circle.css({top: pos.top+1, left: pos.left+1, position:'absolute'});
requestAnimationFrame(this.loop.bind(this))
}
}
const main = new Main();
main.start();
<div>
<img id="circle" src="https://playcode.io/static/img/logo.png"
alt="PlayCode logo">
<h1 id="msg"></h1>
</div>
#circle {
position: absolute;
top: 0;
left: 0;
}
In js, object are passed by reference, and primitive types by value.
I think you should avoid having other variables in moveCircle function. That kind of function is usually called "loop" or "gameLoop" or "update". When your button is clicked, add a speed to the circle, without creating a new circle, something like myCircle.speed = {x:2, y:2}. In the gameloop, add the speed to the position each frame.
Think also about delta time, as requestAnimationFrame will be faster depending on the PC/Mobile that run it.
You can wrap your application into on Main class if you like. (like I did above)
Finnaly, if you insist passing parameters to moveCircle, you can use bind.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
function c(a,b,c) {
console.log(a); console.log(b); console.log(c);
}
c.bind(window, 4,3)
// function c() // bind will return a function ! In a class usually the context that you want to pass is `this`. If you are playing directly in the console, the context is window by default (not that it matter in this example)
c.bind(window, 4,3)()
// 4
// 3
// undefined
The first call to moveCircle (from what I understand, it is in button function), should also be a requestAnimationFrame like requestAnimationFrame(moveCircle.bind(window, other vars)), you could re-use that in moveCircle as well, to avoid any global variable. Still, I recommend making a class to wrap your application, so that you can use local variables to your class to save the current state of your game instead of having that same state living inside the function arguments only.

Tween.js | My tween isn't updating even when I loop it

So, I'm creating a game in which I have a ship with a gun that shoots bullets.
I want the gun of the ship to bounce back when I shoot so it looks like the gun actually shot the bullet. Everything is fine so far, the gun is only moving relative to the body, and nothing's been stuck in infinite loops so far.
My ship is made from a constructor I coded that works perfectly, so to create the tweens, instead of making variables inside the constructor that I can't reuse, I made the tweens actual attributes of the object.
This is what the code looks like:
this.gunTweenPosition = {y : unit / -1.52 + (gunLength * unit / -4)};
this.gunTweenTarget = {y : av.gunTweenPosition.y + unit / 6};
this.gunTween1 = new TWEEN.Tween(av.gunTweenPosition.y).to(av.gunTweenTarget.y, 1000);
this.gunTween2 = new TWEEN.Tween(av.gunTweenTarget.y).to(av.gunTweenPosition.y, 1000);
this.gunTween1.easing(TWEEN.Easing.Cubic.In);
this.gunTween2.easing(TWEEN.Easing.Cubic.Out);
this.gunTween1.onUpdate(function() {
this.gun.position.y = av.gunTweenPosition.y;
});
this.gunTween2.onUpdate(function() {
this.gun.position.y = av.gunTweenTarget.y;
});
'this' being the object we're constructing,
and to start the function that will push and pull the gun, I have this function that I just call:
car avatar = this;
var number = 0;
function loopTweenUpdating() {
number++;
if (number < 20) {
avatar.gunTween1.update();
avatar.gunTween1.onComplete(function() {
avatar.gunTween2.update();
});
setTimeout(loopTweenUpdating, 20);
}
}
I can't see what the problem is here.
Click THIS link to see the full code.
Any ideas?
It looks like you are missing to start the tween.
this.gunTween1.start();

Simple ball animation HTML5 using requestAnimationFrame

I am just starting trying to make some animation using HTML5 and JavaScript.
Currently I have created a JavaScript class for the ball. It has an update function which should update the position of the ball and a draw function which should draw it:
/*global Vector*/
var Ball = (function () {
function Ball(pPostion) {
this.setPosition(pPostion);
}
Ball.prototype.getPosition = function () {
return this.mPosition;
};
Ball.prototype.setPosition = function (pPosition) {
this.mPosition = pPosition;
};
Ball.prototype.draw = function (pContext) {
pContext.save();
pContext.beginPath();
pContext.arc(100, 100, 20, 0, Math.PI * 2, true);
pContext.closePath();
pContext.fillStyle = '#ff0000';
pContext.stroke();
pContext.restore();
};
Ball.prototype.update = function () {
this.getPosition().add(new Vector(10, 0));
};
return Ball;
}());
In the my main section I have created the following method:
function ballGameLoop() {
ball.draw(mainContext);
ball.update();
requestAnimationFrame(ballGameLoop);
}
And when called, it does draw the ball but it doesn't seem to move at all. I don't have a specific type of way I want the ball to be animated, just any kind of movement would be good. Can anyone give any advice on where I may be going wrong?
From the looks of it, it seems you are just drawing an arc at the same coordinates over and over again (center at (100,100)).
Incorporating your Ball's position into this would be the way to make the render location dependent on the object's position. From what it seems, something along the lines of the following would give movement:
Ball.prototype.draw = function (pContext) {
var coordinates = this.getPosition();
pContext.save();
pContext.beginPath();
pContext.arc(coordinates.X, coordinates.Y, 20, 0, Math.PI * 2, true);
pContext.closePath();
pContext.fillStyle = '#ff0000';
pContext.stroke();
pContext.restore();
};
I'm of course assuming on how you setup the Vector object, so I'm guessing x and y can be accessed by (Vector).X and (Vector).Y respectively.
anyway just my approach at it.

simple requestAnimationFrame not working JavaScript

I am currently trying to understand animation using JavaScript and HTML5.
From what I have gathered after researching on the internet, requestAnimationFrame repeatedly calls a method.
I have created a plane, and created a method which will move the plane in a diagonal line. However, it there seems to be no animation.
I'm fairly new to this so it could be just me not quite getting the concept. I don't think it is to do with my browser as I have tried it on both chrome and internet explorer, and they should be up to date as I only installed them a few months ago as this is a new laptop.
Here is my main class, it should include all relevent code:
/*global window, document, alert, Vector, Moth, Matrix, Plane, SceneGraphNode*/
function onLoad() {
var mainCanvas, mainContext, planePosition, plane;
// this function will initialise our variables
function initialiseCanvasContext() {
// Find the canvas element using its id attribute.
mainCanvas = document.getElementById('mainCanvas');
// if it couldn't be found
if (!mainCanvas) {
// make a message box pop up with the error.
alert('Error: I cannot find the canvas element!');
return;
}
// Get the 2D canvas context.
mainContext = mainCanvas.getContext('2d');
if (!mainContext) {
alert('Error: failed to get context!');
return;
}
planePosition = new Vector(0, 0, 0);
plane = new Plane(planePosition);
}
function translate(pPosition) {
var matrix = Matrix.createTranslation(pPosition);
matrix.transform(mainContext);
}
function scale(pPosition) {
var matrix = Matrix.createScale(pPosition);
matrix.transform(mainContext);
}
function rotate(pPosition) {
var matrix = Matrix.createRotation(pPosition);
matrix.transform(mainContext);
}
function drawPlane() {
scaleVector = new Vector(0.25, 0.25, 0);
scale(scaleVector);
translate(new Vector(0, 0));
rotate(0);
plane.draw(mainContext);
}
function drawMoth() {
var moth, mothPosition;
mothPosition = new Vector(mainCanvas.width / 2, mainCanvas.height / 2, 0);
moth = new Moth(mothPosition);
moth.draw(mainContext);
}
function drawPlane() {
plane = new Plane(planePosition);
scale(new Vector(0.25, 0.25, 0));
plane.draw(mainContext);
}
function animatePlane() {
translate(planePosition.add(new Vector(100, 100, 0)));
drawPlane();
window.requestAnimationFrame(animatePlane);
}
initialiseCanvasContext();
drawMoth();
animatePlane();
}
window.addEventListener('load', onLoad, false);
Please let me know if you think it would help to see any associated methods. I have also attached the result.
A lot of things are undefined here (the Matrix and Vector objects and their methods). Please include the code if you have it, otherwise keep reading.
It seems you've got a bit of a gap in your Object-Oriented JS knowledge. I'm guessing you know a good chunk of this, but it will be worth your time to solidify your knowledge of the following:
Know how to make a new object. Understand what an object is.
Understand how to make a constructor function.
Understand that using the new keyword simply calls an object's constructor function.
Understand inheritance. The this keyword vs. prototypical inheritance.
Understand encapsulation.
Understand the Canvas API
Add comments to your code. If other people are going to read you're code, please add comments. It helps. All you really need is a single comment per function explaining what it does. Explaining what the input parameters are is useful to.
Here are some resources to get you started (and perhaps finished):
Read this (and it's two prerequisites): http://javascriptissexy.com/oop-in-javascript-what-you-need-to-know/
Check out the built-in Canvas methods: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API
Here are the code structures that were missing
function Vector(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
var Matrix = {
createTranslation: function() {
},
createRotation: function() {
},
createScale: function() {
},
transform: function() {
}
};
function Plane(position) {
this.add = function() {
this.draw = function() {
};
};
}
function Moth(position) {
this.draw = function() {
};
}
I know this doesn't answer your question and I'm likely about to be downvoted to hell, but I can't really help you until you understand what you're doing a bit better. Good luck!

Categories

Resources