P5JS sound only plays when I leave the active tab - javascript

I'm trying to write a code so that when a rect() reaches a certain point, a song will start playing. I was having trouble with my actual code so I started a new test file to mess around with it and try to get it to work (my actual js file is very long & I wanted something short and simple) but I just ran into the problem again.
The code is supposed to work so if the mouse is pressed, the left square will slide over to the right square, and when it hits the right square, the song will play. If the mouse is clicked again, the song will stop.
I've gotten most of that to work, but the trouble comes in when I add in
if ( backtoblack.isPlaying() ) {
backtoblack.stop();
} else {
backtoblack.play();
}
Here's the complete code for the sketch:
var backtoblack;
var rect1X = 20;
var speed = 1;
var mouseWasPressed;
function preload(){
backtoblack = loadSound('assets/backtoblack.mp3');
}
function setup() {
createCanvas(590,630);
background("#704e34");
}
function draw(){
fill("#fff");
rect(rect1X, 20, 120, 120);
rect(450, 20, 120, 120);
if (mouseWasPressed == true ) {
if(rect1X <= 390){
rect1X += speed;
}
}
if ( backtoblack.isPlaying() ) {
backtoblack.stop();
} else {
backtoblack.play();
}
}
function mousePressed(){
mouseWasPressed = true;
}

The problem is that your if else block that toggles whether the song is playing is inside the draw() function. That means that 60 times per second, you toggle the song! It's like you're constantly hitting the play and stop buttons. Then when you switch tabs, the draw() function is paused, which is why it stops toggling.
To fix your problem, you need to not toggle the song every frame. Perhaps put it inside the mousePressed() function to test things out.
Taking a step back, I'd also encourage you to debug your code (that guide is for Processing, but here is a guide on JavaScript). It's really great that you put together a smaller example program to test things out, but you should also try to step through the code line by line, or add print statements, to figure out what's going on. Stepping through or adding print statements would have helped you realize what was going on.
Anyway, good luck!

Related

Set videoElement.currentTime in Hulu video player doesn't work, and breaks the player

I have a Chrome extension in which I'm trying to jump forward or backward (based on a user command) to a specific time in the video by setting the currentTime property of the video object. Before trying to set currentTime, a variety of operations work just fine. For example:
document.getElementsByTagName("video")[1].play(); // works fine
document.getElementsByTagName("video")[1].pause(); // works fine
document.getElementsByTagName("video")[1].muted = true; // works fine
document.getElementsByTagName("video")[1].muted = false; // works fine
BUT as soon as I try to jump to a specific point in the video by doing something like this:
document.getElementsByTagName("video")[1].currentTime = 500; // doesn't work
No errors are thrown, the video pauses, and any attempted actions after this point do nothing. So the items shown above (play/pause/mute/unmute) no longer work after attempting to set currentTime. If I read the value of currentTime after setting it, it correctly displays the new time that I just set it to. Yet nothing I do will make it play, and in fact even trying to make the video play by clicking the built-in toolbar no longer works. So, apparently setting currentTime wreaks all kinds of havoc in the video player. Yet if I reload the video, all works as before as long as I don't try to set currentTime.
I can easily jump to various times (backward or forward) by sliding the slider on the toolbar, so there must be some way internally to do that. Is there some way I can discover what code does a successful time jump? Because it's a Chrome extension I can inject custom js into the executing Hulu js, but I don't know what command I would send.
Any ideas?
Okay I fiddled around with it for a little while to see how I could reproduce the click event on the player and came up with the following solution:
handleViewer = function(){
var thumbnailMarker = $('.thumbnail-marker'),
progressBarTotal = thumbnailMarker.parent(),
controlsBar = $('.controls-bar'),
videoPlayer = $('#content-video-player');
var init = function(){
thumbnailMarker = $('.thumbnail-marker');
progressBarTotal = thumbnailMarker.parent();
controlsBar = $('.controls-bar');
videoPlayer = $('#content-video-player');
},
check = function(){
if(!thumbnailMarker || !thumbnailMarker.length){
init();
}
},
show = function(){
thumbnailMarker.show();
progressBarTotal.show();
controlsBar.show();
},
hide = function(){
controlsBar.hide();
},
getProgressBarWidth = function(){
return progressBarTotal[0].offsetWidth;
};
return {
goToTime: function(time){
var seekPercentage,
duration;
check();
duration = videoPlayer[0].duration;
if(time > 0 && time < duration){
seekPercentage = time/duration;
this.jumpToPercentage(seekPercentage);
}
},
jumpToPercentage: function(percentage){
check();
if(percentage >= 1 && percentage <= 100){
percentage = percentage/100;
}
if(percentage >= 0 && percentage < 1){
show();
thumbnailMarker[0].style.left = (getProgressBarWidth()*percentage)+"px";
thumbnailMarker[0].click();
hide();
}
}
}
}();
Once that code is initialized you can do the following:
handleViewer.goToTime(500);
Alternatively
handleViewer.jumpToPercentage(50);
I've tested this in chrome on a MacBook pro. Let me know if you run into any issues.
Rather than try to find the javascript responsible for changing the time, why not try to simulate the user events that cause the time to change?
Figure out the exact sequence of mouse events that trigger the time change.
This is probably some combination of mouseover, mousedown, mouseup, and click.
Then recreate those events synthetically and dispatch them to the appropriate elements.
This is the approach taken by extensions like Stream Keys and Vimium.
The video should be ready to play before setting the currentTime.
Try adding this line before setting currentTime?
document.getElementsByTagName("video")[1].play();
document.getElementsByTagName("video")[1].currentTime = 500;
Looks like it works if you first pause, then set currentTime, then play again.
document.getElementsByTagName("video")[1].pause()
document.getElementsByTagName("video")[1].currentTime = 800.000000
document.getElementsByTagName("video")[1].play()
Probably would need to hook into some event like onseeked to put in the play command to make it more robust.

Game slows down on click

I'm currently working on a game in node using socket.io and drawing onto canvas. I'm noticing that when I click during the game, character movement slows to a crawl. I would ideally like to maintain the draw rate that the game begins at and determine what's causing these memory issues. I'm looking to find out how I can debug this in a deterministic way
For context: I'm updating x,y coordinates in the game loop according to which keys are active (dictated by keyup and keydown events). I'm sending player information to the server via sockets about ~60 times a second.
To get more specific, here's a recording of the page's memory timeline:
The steep increase happens right around the time of the click event. The original jump (before the 6 extra listeners are added) is happening once the game starts. As you can see it's going a little wild on that click.
I have no handlers bound to the click event but the JS Heap grows rapidly and listeners seem to be added which confuses me. Here's a link to my repo, below is a chunk from game.js that has to do with keypresses and may be somehow involved:
var sendKey = function (activeK) {
player.xSpeed = 0;
player.ySpeed = 0;
if (activeK[KEY_W]) {
player.ySpeed = -SPEED;
}
if (activeK[KEY_A]) {
player.xSpeed = -SPEED;
}
if (activeK[KEY_S]) {
player.ySpeed = SPEED;
}
if (activeK[KEY_D]) {
player.xSpeed = SPEED;
}
if (activeK[SPACE]) {
activate(player)
}
}
document.onkeydown = function(e) {
if (activeKeys.hasOwnProperty(e.keyCode)) {
activeKeys[e.keyCode] = true;
sendKey(activeKeys)
}
}
document.onkeyup = function(e) {
if (activeKeys.hasOwnProperty(e.keyCode)) {
activeKeys[e.keyCode] = false;
sendKey(activeKeys)
}
}
Thanks!
Note: I originally started from scratch to try to learn a bunch but will likely switch to a game making framework.

Javascript audio not playing

I get a headache trying to understand why my script is not playing the sounds like i want to.
I have a quite simple HTML/Javascript animation with several sounds into it, executed on user's interaction (swipe, click, validate...).
Here is the url if you want to test and see the complete source :
http://artcode.fr/apps/bioprojet/simulation/index.html
The issues are at step 4 & 5 :
Step 4, clicking on the red button makes it disappear, execute an "injection sound", plays "validate sound" and then goes to step 5 where there should be a clock sound executed each second during the countdown to 10.
This regular behavior is ok in desktop browser (Safari/Chrome), but when launched in Safari mobile ou Chrome mobile, the sounds on step 4 are not always played (sometimes even inverted), and the clock sound on step 5 is never played.
I tried a lot of things to make it work, with no success, as :
"currenTime" and "pause()"
"onended" event, but doesn't seem to work on mobile
different sounds, to see if the issue came from this (answer is no)
inverted places
Here is the part of the code where the mess is :
if(e==4){
$("#voir_etape_3").addClass("voir_etape_on");
$("#bouchon_rouge").click(function(){
clic.play();
$("#anim_clic").animate({ top: "110px" }, { duration:50, complete: function(){
var pauseclic = setInterval(function(){
clearInterval(pauseclic);
valide.play();
$(".etape").hide();
$("#etape_5").show();
actions(5);
},2000);
}});
});
}
if(e==5){
$("#voir_etape_4").addClass("voir_etape_on");
var t=0;
var decompte = setInterval(function(){
t++;
if (t<=10){
tic.play();
$("#decompte").text(t);
if (t==10){ $("#decompte").addClass("decompte_on"); }
} else{
$("#decompte").addClass("decompte_on");
if (t==11){
clearInterval(decompte);
tictactic.pause();
//tictactic.currentTime = 0;
valide.play();
$(".etape").hide();
$("#etape_6").show();
actions(6);
}
}
}, 1000);
}
Sounds are defined at the beginning of my javascript script :
var valide = new Audio('./graph/valide.mp3');
var tic = new Audio('./graph/tictac.mp3');
var tictactic = new Audio('./graph/tictactic.mp3');
var clic = new Audio('./graph/clic.mp3');

consecutives calls to requestAnimationFrame

I played a bit with the javascript function called requestAnimationFrame(), and made this stroke by stroke kanji painter. It works well... the code is clean enough, considered my newbie-ness. I followed a nice tutorial here and landed on a structure like this :
function here_a_closure() {
var some_state = 0;
var last_frame = false;
function machinery() {
// do mysterious stuff
return last_frame;
}
function frame_display() {
handle = window.requestAnimationFrame(frame_display);
if (machinery()) {
window.cancelAnimationFrame(handle);
}
// do the display
}
frame_display();
}
However, I would like to extend this, and paint some more kanjis next to the first one. Should I wait for the end of the first animation to launch the next one ? I would prefer (more modularity and re-use), but how ? Or should I make the machinery more complex to animate more than one character in the same animation ?
Use a single requestAnimationFrame to drive all your animations.
If you have multiple animations that run with different timings then you can make use of the elapsed time that's automatically fed into each call.
function animate(time){
requestAnimationFrame(animate);
}
This way you have the flexibility of running each of your animations either consecutively or serially without increasing the complexity of your 'machinery'.
if(time>doSomethingOnAnimation1whenThisTimeElapses){ ... }
if(time>doSomethingOnAnimation2whenThisTimeElapses){ ... }
if(time>doSomethingOnAnimation3whenThisTimeElapses){ ... }
Here's a more detailed code about using requestAnimationFrame's timer on a previous post:
How to control animation speed (requestAnimationFrame)?

Lengthening MIDI.js piano note duration

I'm using MIDI.js to build a music app that allows users to play piano through their keyboard.
Everything is working, but the problem I'm having is that the notes (called with MIDI.noteOn) only last 3 seconds, then just cut off. I'm trying to find a way to:
1- Make the note last for longer.
2- Make the note fade to nothing as opposed to just cutting off.
Could anyone point me in the right direction with there? There is so little documentation & discussion on MIDI.js.
Thanks in advance!
EDIT: The instrument name is acoustic_grand_piano
In theory, you need to call noteOff at the proper time.
In practice, MIDI.Plugin.js has this:
// FIX: needs some way to fade out smoothly..
root.noteOff = function (channel, note, delay) {
// var source = sources[channel+""+note];
// if (!source) return;
// source.noteOff(delay || 0);
// return source;
};

Categories