Sliding values of an array inside intervals - javascript

I ve created a array with eleven values . I am trying to slide the values of my array during intervals. What i am trying, every n ms to slide a value to the next position of the array that i ve created. Every inteval i initialize the first value, so i want the slide effect.
var barArray = [0,0,0,0,0,0,0,0,0,0,0];
var interval = 0;
setInterval(function() {
temporal = getNewValue; //getting with a function new value
barArray[0] = temporal;
if(interval == barArray.length)
{
interval = 0;
}
for (var i = 0; barArray.length; i++){
// code missing
}
}, 1000);
I am tried many things without finding a solution.
Output:
1st interval: [76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2nd interval: [55, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0]
3rd interval: [32,55, 76, 0, 0, 0, 0, 0, 0, 0, 0]
11th interval: [..., 32, 55, 76]
12th [..., 32,55] ect. `

What you have described here is a queue. You input elements at one end and silently drop them at the other end. JavaScript arrays have functions to add and extract elements at both ends of the array (push/pop and shift/unshift).
In the end, a complete solution would be:
var barArray = [0,0,0,0,0,0,0,0,0,0,0];
setInterval(function() {
barArray.unshift(getNewValue());
barArray.pop();
}, 1000);

Related

Merging Audio files with Javascript

I have an issue that I have spent forever trying to figure out and I can't get it. I want to take two audio files, and merge them into one blob so that they play at the exact same time. I don't know much about how audio works, so i'm kinda shooting in the dark. But my first idea (which I will leave the code below) was to create arrays of the decimal values of the two audio files, then add the values of a certain position together and divide by two, then push all of these new values into an array that would be turned into a blob and then played. This failed however, it played a really horrible squeaking sound.
function mergeAudio(){
var length;
const mergedAudio = []
//audioArray1 and audioArray2 are just arrays of the decimal values of the two audio files
// setting the length of the merged audio
if(audioArray1.length < audioArray2.length){
length = audioArray1.length
}else{
length = audioArray2.length
}
//merging bytes and pushing them to a new array
for(var i = 0; i < length; i++){
var byte = audioArray2[i] + audioArray1[i]
byte = byte / 2
if(byte <= 0){
byte = 0
}
mergedAudio.push(byte)
}
//create Audio and play it
const arrayBuffer = new Uint8Array(mergedAudio)
const audioBlob = new Blob(arrayBuffer);
const audioUrl = URL.createObjectURL(audioBlob);
const audio = new Audio(audioUrl);
audio.play().then(function(){}).catch(function(error){
console.log(error)
})
})
Like i said, this did not work, and i tried subtracting values from each byte and trying other methods to see what the outcome would be so I could figure out what I was doing wrong, but for some reason every other method I try (besides the one in the code above) leaves an error message:
"DOMException: Failed to load because no supported source was found."
If anyone is savvy with audio or knows why I am getting this error, or if anyone knows another method to merge audio, it would be greatly appreciated!!!
Edit: I am getting my data 5 second .mp3 files and am using the code below to create an array of the data
var audioArray1;
input.addEventListener('change', () =>{
const fileReader = new FileReader()
fileReader.onload = function(event) {
const arrayBuffer = event.target.result
const buffer = new Uint8Array(arrayBuffer)
const array = []
for(var i = 0; i < buffer.length; i++){
array.push(buffer[i])
}
audioArray1 = array
}
//uses audio file that user uploaded and assigns to file reader
fileReader.readAsArrayBuffer(input.files[0]);
})
If I log the array, it shows something like this:
(74925) [73, 68, 51, 4, 0, 0, 0, 0, 0, 35, 84, 83, 83, 69, 0, 0, 0, 15, 0, 0, 3, 76, 97, 118, 102, 53, 55, 46, 53, 54, 46, 49, 48, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 251, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 110, 102, 111, 0, 0, 0, 15, 0, 0, 0, 129, 0, 1, 36, 128, 0, 5, 7, …]
A few things to be aware of:
(1) you need to deal with PCM values, not bytes. The PCM is created by appending bytes. For example, if the format is 16-bit, one of the two bytes will be shifted 8-bits over and the two bytes are then OR'd together to form a single 16-byte value. The order of the two bytes depends on whether the format is little-endian or big-endian.
(2) Once you have the PCM, mixing the tracks together is accomplished via addition.
IDK what playback format you are using. There may be another formatting step. The only time I've played raw PCM was when using the Web-Audio API.

Convert uint8array to double in javascript

I have an arraybuffer and I want to get double values.For example from [64, -124, 12, 0, 0, 0, 0, 0] I would get 641.5
Any ideas?
You could adapt the excellent answer of T.J. Crowder and use DataView#setUint8 for the given bytes.
var data = [64, -124, 12, 0, 0, 0, 0, 0];
// Create a buffer
var buf = new ArrayBuffer(8);
// Create a data view of it
var view = new DataView(buf);
// set bytes
data.forEach(function (b, i) {
view.setUint8(i, b);
});
// Read the bits as a float/native 64-bit double
var num = view.getFloat64(0);
// Done
console.log(num);
For multiple numbers, you could take chunks of 8.
function getFloat(array) {
var view = new DataView(new ArrayBuffer(8));
array.forEach(function (b, i) {
view.setUint8(i, b);
});
return view.getFloat64(0);
}
var data = [64, -124, 12, 0, 0, 0, 0, 0, 64, -124, 12, 0, 0, 0, 0, 0],
i = 0,
result = [];
while (i < data.length) {
result.push(getFloat(data.slice(i, i + 8)));
i += 8;
}
console.log(result);
Based on the answer from Nina Scholz I came up with a shorter:
function getFloat(data /* Uint8Array */) {
return new DataView(data.buffer).getFloat64(0);
}
Or if you have a large array and know the offset:
function getFloat(data, offset = 0) {
return new DataView(data.buffer, offset, 8).getFloat64(0);
}

Uncaught TypeError: cannot set property 'backgroundColor' of undefined javascript

I am creating a HTML music production program. I am currently working on the note system for when you click on a note, it switches color to black. But, when I use my Javascript function, it shows the error Uncaught TypeError: cannot set property 'backgroundColor' of undefined
Here is my Javascript. it is incomplete, but if anyone can help, that would be great.
var pattern = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
function switchNote(num, note) {
var trId = document.getElementsByTagName("tr")[note + 8].id;
pattern[num] = note;
document.getElementById(trId).lastChild.style.backgroundColor = "#000";
return "switched";
}
It indicates that the .lastChild is not a DOM element (a node with .nodeType of 1). The lastChild is either a textNode or a commentNode and it doesn't have style property.
You can use the lastElementChild property for getting the last element child.
Another option is using the .children property:
var children = [].slice.call(element.children);
var last = children[children.length - 1];
// for getting the last 2 children of the element:
// var last2 = children.slice(-2);
Note that if the document.getElementsByTagName("tr")[note + 8] returns the target element, then there is no need to re-query DOM by using document.getElementById method. IDs must be unique and reading the .id property of an element for getting it again by .getElementById doesn't make a lot of sense.
Try this:
var pattern = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
function switchNote(num, note) {
var trId = document.getElementsByTagName("tr")[note + 8].id;
pattern[num] = note;
document.getElementById(trId).children[document.getElementById(trId).children.length].style.backgroundColor = "#000";
return "switched";
}

javascript board game piece placement

I'm writing a board game in java script, and what i'm trying to accomplish is: layout the board(chess/checkers format) Then add pieces to the board based on position. So for example i want to be able to write code for piece a to be moved onto tile 10.
So far in my code i have a loop to create the board but don't a method to properly name the tiles, so that the piece can correctly be placed on the tile.
for (i=0; i<64; i++){
var tile = cc.Sprite.create(res.myTile_png);
this.addChild(tile,0);
x = centerpos.x + ((i % 8) - 3.5) * tile.getBoundingBox().width;
y = centerpos.y + (Math.floor(i / 8) - 3.5) * tile.getBoundingBox().height;
tile.setPosition(x,y);
}
One way to go about doing this would be to assign a unique integer identifier to every distinct piece in the game, and then maintain a matrix of dimensions equal to the # of rows x # of columns on the board, with values of the piece identifiers in the correct address in the matrix that would correspond to their position on the board.
For instance, the starting arrangement of pieces in checkers can be represented by:
[
[ 0, -1, 0, -1, 0, -1, 0, -1 ],
[ -1, 0, -1, 0, -1, 0, -1, 0 ],
[ 0, -1, 0, -1, 0, -1, 0, -1 ],
[ 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 1, 0, 1, 0, 1, 0, 1, 0 ],
[ 0, 1, 0, 1, 0, 1, 0, 1 ],
[ 1, 0, 1, 0, 1, 0, 1, 0 ]
]
with, say, -1 representing white, and 1 representing red pieces on the board.
The tile elements of the board can also be kept in a matrix, so that the two matrices can be iterated over together to place the pieces in corresponding locations.
The unique ids can also then be used as CSS class names, or image file names to be attached to the element representing the piece.

Connect Four Game Checking for Wins JS

I am working on my first full program with two weeks of programming under my belt, and have run into a road block I can't seem to figure out. I am making a connect 4 game, and have started by building the logic in JavaScript before pushing to the DOM. I have started to make it with cell objects made by a constructor, that are then pushed into a game object in the form of a 2D array. I have managed to create a function that makes the play each time, and changes the value of the cell at the lowest point of that column with a 2 day array. However, I am not sure how to get my check for wins function to operate.
So far my logic is that, for each point in the 2D array, you can check by row, by column, and by diagonals. I understand the logic of how to check for win, but I don't understand how to traverse through the arrays by row and column. In the example below, this.cellsArray is an array of cell objects in the Board Constructor. The array has 7 column arrays, with 6 rows each, as I flipped the typical row column logic to account for Connect Four's column based nature. However I can't access the array like this.cellsArray[col][row], as col and row aren't defined, and I'm not sure how to define an index value? Any help would be appreciated!
Connect 4
Example:
//array location is equal to an instance of this.cellsArray[col][row]
Board.prototype.checkRowRight = function (arrayLocation) {
if ((arrayLocation[i+1][i].value === arrayLocation.value) && (arrayLocation[i+2][i]=== arrayLocation.value) && (arrayLocation[i+3][i].value === arraylocation.value)){
this.winner = this.currentPlayer;
this.winnerFound = true;
console.log('Winner has been found!')
}
};
Referencing back to my logic found here and refactoring out the winning line detection code, this can easily be converted into Javascript as follows:
function chkLine(a,b,c,d) {
// Check first cell non-zero and all cells match
return ((a != 0) && (a ==b) && (a == c) && (a == d));
}
function chkWinner(bd) {
// Check down
for (r = 0; r < 3; r++)
for (c = 0; c < 7; c++)
if (chkLine(bd[r][c], bd[r+1][c], bd[r+2][c], bd[r+3][c]))
return bd[r][c];
// Check right
for (r = 0; r < 6; r++)
for (c = 0; c < 4; c++)
if (chkLine(bd[r][c], bd[r][c+1], bd[r][c+2], bd[r][c+3]))
return bd[r][c];
// Check down-right
for (r = 0; r < 3; r++)
for (c = 0; c < 4; c++)
if (chkLine(bd[r][c], bd[r+1][c+1], bd[r+2][c+2], bd[r+3][c+3]))
return bd[r][c];
// Check down-left
for (r = 3; r < 6; r++)
for (c = 0; c < 4; c++)
if (chkLine(bd[r][c], bd[r-1][c+1], bd[r-2][c+2], bd[r-3][c+3]))
return bd[r][c];
return 0;
}
And a test call:
x =[ [0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 0, 0],
[0, 0, 1, 2, 2, 2, 0],
[0, 1, 2, 2, 1, 2, 0] ];
alert(chkWinner(x));
The chkWinner function will, when called with the board, return the first (and only, assuming each move changes only one cell and you're checking after every move) winning player.
The idea is to basically limit the checks to those that make sense. For example, when checking cells to the right (see the second loop), you only need to check each row 0-6 starting in each of the leftmost four columns 0-3.
That's because starting anywhere else would run off the right hand side of the board before finding a possible win. In other words, column sets {0,1,2,3}, {1,2,3,4}, {2,3,4,5} and {3,4,5,6} would be valid but {4,5,6,7} would not (the seven valid columns are 0-6).
This is an old thread but i'll throw my solution into the mix since this shows up as a top search result for "how to calculate connect4 win javascript"
I tackled this problem by using matrix addition.
Assume your game board is stored in memory as a 2D array like this:
[ [0, 0, 0, 0, 0, 0, 0],
[0, 0, Y, 0, 0, 0, 0],
[0, 0, Y, 0, 0, 0, 0],
[0, 0, R, 0, 0, 0, 0],
[0, 0, Y, 0, 0, 0, 0],
[0, 0, R, R, R, 0, 0] ];
On each "Coin Drop" you should call a function passing the x/y position of the coin.
THIS is where you calculate weather the user has won the game
let directionsMatrix = {
vertical: { south: [1, 0], north: [-1, 0] },
horizontal: { east: [0, 1], west: [0, -1] },
backward: { southEast: [1, 1], northWest: [-1, -1] },
forward: { southWest: [1, -1], northEast: [-1, 1] },
};
NOTE: "South" in matrix notation is [1,0], meaning "Down 1 cell, Right 0 cells"
Now we can loop through each Axis/Direction to check if there is 4 in a row.
const playerHasWon = (colnum, rowNum, playerColor, newGrid) => {
//For each [North/South, East/West, NorthEast/Northwest, SouthEast/Southwest]
for (let axis in directionsMatrix) {
// We difine this variable here so that "East" and "West" share the same count,
// This allows a coin to be dropped in a middle cell
let numMatches = 1;
// For each [North, South]
for (let direction in directionsMatrix[axis]) {
// Get X/Y co-ordinates of our dropped coin
let cellReference = [rowNum, colnum];
// Add co-ordinates of 1 cell in test direction (eg "North")
let testCell = newGrid[cellReference[0]][cellReference[1]];
// Count how many matching color cells are in that direction
while (testCell == playerColor) {
try {
// Add co-ordinates of 1 cell in test direction (eg "North")
cellReference[0] += directionsMatrix[axis][direction][0];
cellReference[1] += directionsMatrix[axis][direction][1];
testCell = newGrid[cellReference[0]][cellReference[1]];
// Test if cell is matching color
if (testCell == playerColor) {
numMatches += 1;
// If our count reaches 4, the player has won the game
if (numMatches >= 4) {
return true;
}
}
} catch (error) {
// Exceptions are to be expected here.
// We wrap this in a try/catch to ignore the array overflow exceptions
// console.error(error);
break;
}
}
// console.log(`direction: ${direction}, numMatches: ${numMatches}`);
// If our count reaches 4, the player has won the game
if (numMatches >= 4) {
return true;
}
}
}
// If we reach this statement: they have NOT won the game
return false;
};
Here's a link to the github repo if you wish to see the full code.
Here's a link to a live demo

Categories