Phaser and Web Audio API - orientate sprite - javascript

I'm trying to use phaser with the web audio API but I can't figure out how to go from the sprites x, y, z and rotation values to a directional vector and up vector. How would I do this?
ctx.setPosition(sprite.x, sprite.y, sprite.z);
ctx.setOrientation(0,0,0,0,0,0);
ctx.setVelocity(0, 0, 0);

I'm pretty sure I worked it out, here's the code:
function updateWithSprite(sprite)
if (sprite.body) {
var rot = sprite.body.rotation + Math.PI / 2;
this.setPosition(sprite.body.x, body.y, 0);
this.setOrientation(Math.cos(rot), Math.sin(rot), 0);
this.setVelocity(sprite.body.velocity.x, sprite.body.velocity.y, sprite.body.velocity.z);
} else {
var rot = sprite.rotation + Math.PI / 2;
this.setPosition(sprite.x, sprite.y, 0);
this.setOrientation(Math.cos(rot), Math.sin(rot), 0);
this.setVelocity(0, 0, 0);
}
}

Related

Flickering horizontal lines on the animation made with canvas only on iOS 16

I have webview application where on the splash screen there is an animation with 2 gradients 'waves' made using canvas. When I opened it with iOS 16 I noticed that there are some scrange horizontal lines flickering during the animation.
It happens only when the app is opened on the device with iOS 16.
I draw these animation with the code below:
public drawWaveAnimation = (
windowHeight: number,
windowWidth: number,
{
canvas,
context,
heightRatio,
frameRatio,
trygonometricalFunction,
gradientColors,
faster,
frames,
frequency,
phi,
startingHeightPosition,
}: WaveAnimationOptions
) => {
this[canvas].nativeElement.height = windowHeight;
this[canvas].nativeElement.width = windowWidth;
const cw = this[canvas].nativeElement.width;
const ch = this[canvas].nativeElement.height;
if (faster) {
frames += this.changeAnimationSpeed(frames);
} else {
frames += 0.6;
}
phi = frames / frameRatio;
this[context].clearRect(0, startingHeightPosition, cw, ch);
this[context].beginPath();
this[context].translate(0, startingHeightPosition);
const reachHalfHeight = startingHeightPosition > windowHeight / 2;
startingHeightPosition += this.changeGoingDownAnimationSpeed(
faster,
reachHalfHeight
);
this[context].moveTo(0, ch);
const amplitude = windowHeight / parseFloat(heightRatio.toFixed(1));
for (let x = 0; x < windowWidth; x += 1) {
const y =
(trygonometricalFunction(x * frequency + phi) * amplitude) / 2 +
amplitude / 2;
this[context].lineTo(x, y);
}
this[context].lineTo(windowWidth, ch);
this[context].lineTo(0, ch);
const gradient = this[context].createLinearGradient(
0,
0,
window.innerWidth,
0
);
gradient.addColorStop(0, gradientColors[0]);
gradient.addColorStop(1, gradientColors[1]);
this[context].fillStyle = gradient;
this[context].fill();
requestAnimationFrame(() => {
this.drawWaveAnimation(windowHeight, windowWidth, {
canvas,
context,
heightRatio,
frameRatio,
trygonometricalFunction,
gradientColors,
faster,
frames,
frequency,
phi,
startingHeightPosition,
});
});
};
When I was testing it, I noticed that when I remove gradient from the animation waves these flickering lines also disappear. I have the gradient injected like below:
const gradient = this[context].createLinearGradient(
0,
0,
window.innerWidth,
0
);
gradient.addColorStop(0, gradientColors[0]);
gradient.addColorStop(1, gradientColors[1]);
this[context].fillStyle = gradient;
this[context].fill();
I cannot reproduce it on the browser(safari, chrome), on XCODE simulator or android simulator. It happens only on the real device with iOS 16.
Had the same issue, looks like they fixed it in IOS 16.3

How to overlay a shape on a video in p5js?

In P5js I want to overlay a shape to a video, but they don't share the same dom element.
Is there any way to do it?
Code test here: The video should be visible through the triangular contour that cuts the shape.
The code:
let video;
function preload() {
video = createVideo("video.mp4");
}
function setup() {
createCanvas(400, 300);
background("gray");
video.size(400,400);
video.loop();
var w = width * 0.7;
var h = height * 0.7;
translate((width/2) - (w/2), (height/2) - (h/2));
fill("lightgray");
noStroke();
beginShape();
vertex(0, 0);
vertex(w, 0);
vertex(w, h);
vertex(0, h);
beginContour();
vertex(w * 0.2, h * 0.4);
vertex(w * 0.5, h * 0.8);
vertex(w * 0.8, h * 0.4);
endContour();
endShape();
noLoop();
}
I see here that hiding the video and using image (i.e. image(video, 10, 10)) it is possible to draw a single frame. Alas I use noLoop() and in my case there would be no automatic refresh of the video in draw().
"The video should be visible through the triangular contour that cuts the shape."
Below is a result I got from a quick play-around with your code. Maybe it will be useful to you in some way (eg: gives new ideas on how to proceed).
The code's logic is to simply create 2 layers.
Bottom layer 1 is video and top layer 2 is triangle (the canvas).
Other ideas include maybe using BlendModes like Screen or Multiply:
example: canv.blendMode(SCREEN);
Where SCREEN makes whites transparent, and MULTIPLY makes blacks transparent).
The example testing code (makes two layers and also removed background("gray");)
let video; let canv;
function preload()
{ video = createVideo("video.mp4"); }
function setup()
{
translate(0, 0);
video.size(400,300);
video.style("z-index: 1"); //# is default in P5.JS
video.position(0, (width * 0.7) );
video.loop();
canv = createCanvas(400, 400);
canv.style("z-index: 2");
canv.position(0, 0); //# important to have a setting
//# Not needed ....
//background("gray");
var w = width * 1;
var h = height * 1;
translate((width/2) - (w/2), (height/2) - (h/2));
fill("lightgray");
noStroke();
beginShape();
vertex(0, 0);
vertex(w, 0);
vertex(w, h);
vertex(0, h);
beginContour();
vertex(w * 0.2, h * 0.4);
vertex(w * 0.5, h * 0.8);
vertex(w * 0.8, h * 0.4);
endContour();
endShape();
noLoop();
}

How to improve javascript canvas pattern performance

I'm creating a 2D html5 game using canvas. I'm currently making the map who is very large (25000px x 25000px). I'm now trying to add textures to map shapes
Here is the code :
let snowPattern;
let sandPattern;
let junglePattern;
const jungleTexture = new Image();
jungleTexture.src = "./assets/game/map/jungleTexture.png";
jungleTexture.onload = function() {
junglePattern = ctx.createPattern(jungleTexture, "repeat");
};
const snowTexture = new Image();
snowTexture.src = "./assets/game/map/snowTexture.png";
snowTexture.onload = function() {
snowPattern = ctx.createPattern(snowTexture, "repeat");
};
const sandTexture = new Image();
sandTexture.src = "./assets/game/map/sandTexture.png";
sandTexture.onload = function() {
sandPattern = ctx.createPattern(sandTexture, "repeat");
};
//Function to draw map shapes
function animate() {
mapX = document.documentElement.clientWidth / 2 - camera.x * zoom;
mapY = document.documentElement.clientHeight / 2 - camera.y * zoom;
ctx.setTransform(1, 0, 0, 1, mapX, mapY);
//Arctic
if (document.getElementById("3").checked === true) {
ctx.fillStyle = snowPattern;
}
else {
ctx.fillStyle = "#EFF4F6";
}
ctx.fillRect(0, 0, 12500 * zoom, 12500 * zoom);
//Desert
if (document.getElementById("3").checked === true) {
ctx.fillStyle = sandPattern;
}
else {
ctx.fillStyle = "#E5C068";
}
ctx.fillRect(12499 * zoom, 0 * zoom, 12500 * zoom, 12500 * zoom);
//Jungle
if (document.getElementById("3").checked === true) {
ctx.fillStyle = junglePattern;
}
else {
ctx.fillStyle = "#0F7F2A";
}
ctx.fillRect(0, 12500 * zoom, 25000 * zoom, 12500 * zoom);
window.requestAnimationFrame(animate);
}
animate();
So when I only put colors on the background of the shapes, it's working perfectly (constent 144fps), but with patterns, my fps decrease to 20.
Does anyone have an idea about how can I improve the performances ?
You are trying to draw a massive rectangle and it creates an overhead which is expected. It depends on the browser but canvas has some limits. When you reach those limits, you will suffer performance or crash. You can see the limits here Also drawing a huge rectangle will always end with poor performance.
My suggestion would be: draw a smaller rectangle (probably a bit bigger than your game screen) and move it till end of the rectangle and just before pattern ends, move it back again.
Finally, the problem wasnt coming from the size, even with a 50px x 50px pixel rect, the performance was terrible. You need to use ctx.beginPath(), ctx.rect, ctx.closePath() and ctx.fill() to get normal performances.

How to pan on scroll in d3 v4/v5 with Canvas

Background
I'm rendering many elements, so I'm using d3 with canvas instead of SVG.
This lovely block from #mbostock describes how to zoom the canvas on mouse scroll in d3v4. However, I'd like to pan on mouse scroll instead of zooming (like regular webpages and this block).
There are a couple folks who have figured out how to pan on scroll using d3 with SVGs. Unfortunately, those answers don't work out of the box for canvas.
Code
canvas.call(d3.zoom()
.scaleExtent([1 / 2, 4])
.on("zoom", zoomed));
... later on ...
function zoomed() {
context.save();
context.clearRect(0, 0, w, h);
// this gives the default zooming and panning behavior in canvas:
context.translate(d3.event.transform.x, d3.event.transform.y);
context.scale(d3.event.transform.k, d3.event.transform.k);
// Instead, something like this might work?:
current_translate = d3....?
new_translate = {'x': current_translate.x + d3.event.sourceEvent.wheelDeltaX,
'y': current_translate.y + d3.event.sourceEvent.wheelDeltaY};
context.translate(new_translate.x, new_translate.y);
drawCanvas();
context.restore();
}
Alternately, it might be the case I shouldn't use using d3.zoom at all. Should it be instead something like:
canvas.call(d3.pan() // ??
.on("zoom", pan));
A final alternative I can think of is that I should set no javascript handler for the scroll behavior, but just have a canvas element which is larger than window.innerHeight. Then maybe the browser would just take care of it for me? (trying this the naive way hasn't worked for me, so would love some help if this is the best option).
Here's some code which combines your two linked examples:
<!DOCTYPE html>
<meta charset="utf-8">
<canvas width="960" height="500"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var canvas = d3.select("canvas"),
context = canvas.node().getContext("2d"),
width = canvas.property("width"),
height = canvas.property("height"),
radius = 2.5;
var points = d3.range(2000).map(phyllotaxis(10));
canvas.call(d3.zoom()
.scaleExtent([1 / 2, 4])
.on("zoom", zoomed))
.on("wheel.zoom", pan);
drawPoints();
var currentTransform = d3.zoomIdentity;
function zoomed() {
context.save();
context.clearRect(0, 0, width, height);
currentTransform = d3.event.transform;
context.translate(currentTransform.x, currentTransform.y);
context.scale(currentTransform.k, currentTransform.k);
drawPoints();
context.restore();
}
function pan() {
context.save();
context.clearRect(0, 0, width, height);
currentTransform.x += d3.event.wheelDeltaX;
currentTransform.y += d3.event.wheelDeltaY;
context.translate(currentTransform.x, currentTransform.y);
drawPoints();
context.restore();
}
function drawPoints() {
context.beginPath();
points.forEach(drawPoint);
context.fill();
}
function drawPoint(point) {
context.moveTo(point[0] + radius, point[1]);
context.arc(point[0], point[1], radius, 0, 2 * Math.PI);
}
function phyllotaxis(radius) {
var theta = Math.PI * (3 - Math.sqrt(5));
return function(i) {
var r = radius * Math.sqrt(i), a = theta * i;
return [
width / 2 + r * Math.cos(a),
height / 2 + r * Math.sin(a)
];
};
}
</script>

javascript dissapearing object on canvas

I am writing a script to draw an image of the sun, and have an image of the earth orbit around it.
I have defined a planet class as so:
function planet(name, size, rotateRate, startx, starty, colour, scale, oRad, oAng, oSpd){//container class for planets
this.name = name;
this.rotateRate = rotateRate;
this.x = startx;
this.y = starty;
this.colour = colour;
this.scale = scale;
this.size = size;
this.orbitRadius= oRad;
this.orbitAngle = oAng;
this.orbitSpeed = oSpd;
this.drawByArc =
function drawArcCircle(){//draws circles using the arc method
context.save();
context.strokeStyle = '#000000';
context.fillStyle = this.colour;
context.lineWidth=3;
context.beginPath();
context.arc(this.x,this.y,this.size*this.scale,0,Math.PI * 2,false)
context.stroke();
context.fill();
context.closePath();
context.restore();
}
}
Now I have created two instances of the class in the program and drawn them fine using the following functions:
function gameLoop(){//The Game Loop
var thisTime = Date.now();//current time
var deltaTime = thisTime - lastTime;//find difference, not yet used
update();
draw();
lastTime = thisTime;
setTimeout(gameLoop, 1000/60);
}
function draw(){// Draws all the objects
drawBackground();
Sun.drawByArc();
Earth.drawByArc();
}
function update(){// Updates for animation
//var newRotation = this.getCurrantRotation() + (this.getRotationRate()*deltaTime);
var gSegments;
gScale = 4;
simSpeed = 10;
Sun.scale = gScale;
Earth.scale = gScale;
Earth.orbitSpeed = 360/simSpeed;
//Earth.x = Sun.x + Earth.orbitRadius * Math.cos(Earth.orbitAngle * Math.pi / 180);
//Earth.y = Sun.y - Earth.orbitRadius * Math.sin(Earth.orbitAngle * Math.pi / 180);
}
When i have the last two lines of the update method commented out, both circles draw fine, however when i add the final two lines in to attempt to update the earths position in orbit, when i attempt to run the code in chrome the Earth sphere vanishes!
Chrome debugger shows no errors so i'm at a loss as to why it occurs.
EDITED::
Well, I found that thanks to a small typing error (math.pi instead of Math.PI) my planet x and y values were becoming NaN.
however now my earth is stuck at at 90 degree point in its orbit and simply doesnt move, at least it draws, any ideas?
Solved it.
Most of the issues came from using math.pi instead of Math.PI
on top of that, i had not set a value to change the angle of orbit, meaning the orbit always remained at 90, making there be no orbit.
Chrome debug very much helped me in figuring all this out, so thanks a lot user1816548

Categories

Resources