I am following the 2D breakout game tutorial on the Mozilla website. There is a bit of code that I do not understand.
var brickRowCount = 3;
var brickColumnCount = 5;
var brickWidth = 75;
var brickHeight = 20;
var brickPadding = 10;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;
var bricks = [];
for(c = 0; c < brickColumnCount; c++) {
bricks[c] = []; // <-- here
for(r = 0; r < brickRowCount; r++) {
bricks[c][r] = { x: 0, y: 0 }; // <-- here
}
}
I understand in general what the code does, however, there are a few lines that are unclear exactly what they do. According to the website, "We will hold all our bricks in a two-dimensional array. It will contain the brick columns (c), which in turn will contain the brick rows (r), which in turn will each contain an object containing the x and y position to paint each brick on the screen."
I have put comments next to the lines of code that I specifically do not understand. Can someone please clarify exactly what these statements mean?
Thank you
it is creating a multidimensional array, or another way to call it, an array of array.
Each element of the array is another array, so to access them you need to use multiple [] for each dimension.. And just like any other array, they need to be initialized.
So here
bricks[c] = [];
it is initializing for each element of array bricks an array
bricks[c][r] = { x: 0, y: 0 };
here is storing an object in the position r in the array bricks[c] (which means the element in the position c in array bricks is an array too)
Some comments that might help
// create a new empty array, `[]`, in `bricks` at position `c`
bricks[c] = []
// create a new brick, {x:0,y:0}, in `bricks[c]` at position `r`
bricks[c][r] = { x: 0, y: 0 };
bricks[c] is an array within the bricks array.
bricks[c][r] contains the coordinates of the brick.
It's creating the array bricks, then within it, it is creating an array of c and adding values using r.
Could write it like this for you to visualize: bricks[bricks[c][r]]
It says that at position (c,r) in the array a literal object is placed containing two fields: x and y. Both these fields have the value 0
The syntax {x: 0 ,y: 0} is a shorthand for creating an object containing two fields and assigning a value to these fields at the same time.
bricks[c] = [] sets array element number c to be an empty array.
E.g. if you run the for loop without the second part:
var bricks = [];
for(c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
}
bricks will be [ [ ], [ ], [ ], [ ], [ ] ]
If you run the full code, bricks will be
[
[ { x: 0, y: 0 }, { x: 0, y: 0 }, { x: 0, y: 0 } ],
[ { x: 0, y: 0 }, { x: 0, y: 0 }, { x: 0, y: 0 } ],
...
]
Think of that as a matrix, where c is columns, r is rows, and x is the cell at intersection cr
c\r r0 r1 r2 .. rn
c0 x00 x01 x02 .. x0n
c1 x10 x11 x12 .. x1n
.. .. .. .. .. ..
cn xn0 xn1 xn2 .. xnn
The array has to be initialized (that is what presented in your code), that every cell of the array (matrix) will be assigned with a value and probably (just my guess) the value will be changed trough the events happening during the game, or they will be checked or both.
Related
so I'm working on this snake game, and I'm basically trying to prevent the food from spawning on top of the snake tail. My setup variables:
let headX = 10; //snake starting position
let headY = 10;
let appleX = 5; //food starting position
let appleY = 5;
This is the function that checks head/food collision
function checkAppleCollision() {
if (appleX === headX && appleY === headY) {
generateApplePosition();
tailLength++;
score++;
}
}
And this is the function that randomizes the apple position after collision, and also returns the "too much recursion" error, after a couple of collisions:
function generateApplePosition() {
let collisionDetect = false;
let newAppleX = Math.floor(Math.random() * tileCount);
let newAppleY = Math.floor(Math.random() * tileCount);
for (let i = 0; i < snakeTail.length; i++) {
let segment = snakeTail[i];
if (newAppleX === segment.x && newAppleY === segment.y) {
collisionDetect = true;
}
}
while (collisionDetect === true) {
generateApplePosition();
}
appleX = newAppleX;
appleY = newAppleY;
}
Please help, I have no idea what to do here. Everything else works as intended.
Using recursions or do while is a bad idea (I'll explain later)
meanwhile, you could simplify your logic by creating:
reusable samePos() and collides() functions
a recursive createApple() function, which will return itself if the randomly generated x,y positions are occupied by the snake body
const world = {w:6, h:1}; // height set to 1 for this demo only
const snake = [{x:0, y:0}, {x:1, y:0}, {x:2, y:0}, {x:3, y:0}];
const apple = {pos: {x:0, y:0}};
// Check if two object's x,y match
const samePos = (a, b) => a.x === b.x && a.y === b.y;
// Check if object x,y is inside an array of objects
const collides = (ob, arr) => arr.some(o => samePos(ob, o));
const createApple = () => {
const randPos = {
x: ~~(Math.random() * world.w),
y: ~~(Math.random() * world.h),
};
if (collides(randPos, snake)) {
console.log(`position ${randPos.x} ${randPos.y} is occupied by snake`);
return createApple(); // Try another position.
}
// Finally a free spot!
apple.pos = randPos;
console.log(`Apple to free position: ${apple.pos.x} ${apple.pos.y}`);
}
createApple();
Run this demo multiple times
The problem
Useless random guesswork!
As you can see from the example above, if you run it multiple times, very often the randomly generated number is the same as the previously generated one:
...
position 2 0 is occupied by snake <<<
position 1 0 is occupied by snake
position 2 0 is occupied by snake <<<
position 2 0 is occupied by snake <<<
position 1 0 is occupied by snake
position 2 0 is occupied by snake <<<
...
therefore, as your snake grows in size, the recursion might go wild — ad absurdum, iterating way too many times, repeating and failing on the same xy positions, until finally hitting a rare free spot...
This is a really bad design.
Solutions
One solution would be to keep track of the already used randomized positions inside an Array - but that implies unnecessarily to go trough such an Array.
A best solution would be to actually treat the game not as a 2D game, but as a 1D game:
Consider this 2D map of size 4x3 as indexes:
0 1 2 3
4 5 6 7
8 9 10 11
now, let's place a snake into this map:
0 ⬛ 2 3
4 ⬛ ⬛ 7
8 9 ⬛ 11
here's the linear map with the Snake as a 1D list:
[ 0 ⬛ 2 3 4 ⬛ ⬛ 7 8 9 ⬛ 11 ]
therefore, instead of using an array of objects {x:n, y:n} for the snake body positions, all you need is:
[1, 5, 6, 10] // Snake body as indexes
Now that you know all the indexes where you're not allowed to place an Apple, all you need to do when creating the new apple is:
Create an Array of 0-N indexes of length: world.w * world.h
Loop the snake body indexes and delete those indexes from the array of indexes to get an Array of free spots indexes
Simply get only once a random key from that array of free spots!
const indexToXY = (index, width) => ({ x: index%width, y: Math.trunc(index/width) });
const world = {w:4, h:3};
const snakeBody = [1, 5, 6, 10];
const createApple = () => {
const arr = [...Array(world.w * world.h).keys()]; // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
snakeBody.forEach(i => delete arr[i]);
const freeIndexes = arr.filter(k => k !== undefined); // [0, 2, 3, 4, 7, 8, 9, 11]
const appleIndex = freeIndexes[~~(Math.random() * freeIndexes.length)];
const applePos = indexToXY(appleIndex, world.w);
console.log("New apple position: %o", applePos);
};
createApple();
Run this demo multiple times
Having that free spot index simply draw your apple at the XY coordinates using this simple formula
X = index % mapWidth
Y = floor(index / mapWidth)
As others have said, this doesn't need to be recursive, and you should also take into account the (however unlikely) possibility where there are no more tiles to spawn on which would result in an infinite loop.
function generateApplePosition() {
// Count how many tiles are left for spawning in
const tilesLeft = (tileCount * tileCount) - snakeTail.length;
let collisionDetect;
if (tilesLeft > 0) {
do {
const newAppleX = Math.floor(Math.random() * tileCount);
const newAppleY = Math.floor(Math.random() * tileCount);
collisionDetect = false;
for (let i = 0; i < snakeTail.length; i++) {
const { x, y } = snakeTail[i];
if (newAppleX === x && newAppleY === y) {
collisionDetect = true; // Collision
break;
}
}
if (!collisionDetect) {
// Found spawn point
appleX = newAppleX;
appleY = newAppleY;
}
} while (collisionDetect);
}
}
I have an variable obj that has the element count that needs a cartesian coordinate.
So I want to generate the following matrix.
obj = 9, Square root of obj = 3, 3x3 matrix
(-1,1)
(0,1)
(1,1)
(-1,0)
(0,0)
(1,0)
(-1,-1)
(0,-1)
(1,-1)
obj = 25, Square root of obj = 5, 5x5 matrix
(-2,2)
(-1,2)
(0,2)
(1,2)
(2,2)
(-2,1)
(-1,1)
(0,1)
(1,1)
(2,1)
(-2,0)
(-1,0)
(0,0)
(1,0)
(2,0)
(-2,-1)
(-1,-1)
(0,-1)
(1,-1)
(2,-1)
(-2,-2)
(-1,-2)
(0,-2)
(1,-2)
(2,-2)
obj = 49, Square root of obj = 7, 7x7 matrix
(-3,3)
(-2,3)
(-1,3)
(0,3)
(1,3)
(2,3)
(3,3)
(-3,2)
(-2,2)
(-1,2)
(0,2)
(1,2)
(2,2)
(3,2)
(-3,1)
(-2,1)
(-1,1)
(0,1)
(1,1)
(2,1)
(3,1)
(-3,0)
(-2,0)
(-1,0)
(0,0)
(1,0)
(2,0)
(3,0)
(-3,-1)
(-2,-1)
(-1,-1)
(0,-1)
(1,-1)
(2,-1)
(3,-1)
(-3,-2)
(-2,-2)
(-1,-2)
(0,-2)
(1,-2)
(2,-2)
(3,-2)
(-3,-3)
(-2,-3)
(-1,-3)
(0,-3)
(1,-3)
(2,-3)
(3,-3)
What I did was hardcoded the first set that is when the obj value is 9 to be created inside a loop, and pushed those in a list called coordinates.
All I then did was call the loop by passing the Math.sqrt(obj).
Problem:
There are missing coordinates, when the obj value is greater than 9.
For eg: when the obj value is 49. It would create the adjacent previous element, but it won't create the previous element of the previous element (coordinates like (-1, 3), (1, 3), (-3, 1), (3, 1), (-3, -1), (3, -1), (-1, -3), (1, -3)).
This is happening because I hardcoded the logic to create the previous coordinate by subtracting with 1. As the obj value increases the current number of missing coordinates is twice the previous number of missing elements (not sure).
I can't seem to figure out a way to create the logic to create the missing elements.
Another problem is repeating coordinates. Which happened because I used the logic to create the missing elements wrong.
Hard to check if all coordinates are correct when the count (obj) value increases.
Note:
I would like to know different approaches to create the cartesian coordinates around (0, 0). Apparently all my efforts in building the logic ends up with missing elements or repeating elements. And it is hard to actually check if all the coordinates are correct when the obj values increases.
I want to create a cartesian coordinate matrix with any value. Currently I'm stuck with using the squares of odd numbers (I plan to substitute the 0 axis for when the number is less than or greater than squares of odd numbers).
Approach ideas/concepts to test:
As I'm a beginner in graphics programming, I would like to know better approaches to do this. Also here are some approaches I just came up with. I am not sure if this works yet, but I'll add an update.
I could maybe create a cross for just the 0's (x,y) axis. And then try to create the rest of the elements by subtracting or adding to each coordinate in the axis.
As there are 4 quadrants, I could create 4 individual loops that creates just that particular quadrant's missing coordinates.
(0,1)
(-1,0)
(0,0)
(1,0)
(0,-1)
Another approach could be like to sort the coordinates and then check to see the distance between 2 adjacent coordinates if it is greater than 1 create a new element, else continue checking.
Current Code:
My demo code at JSFiddle
const speak = 'these are the COORDINATES you are looking for!'
// 9, 25, 49, 81, 121 => substitutable values for variable 'obj'
const obj = 49 // loop using this variable
const coordinates = []
// hardcodes
const start = [0,0]
const points = []
/* points.push(start) */
/**
* FIX!.
*
* needs to also create coordinates from initial coordinate substracted
* by more than 1, currently it gets the previous element by substracting 1,
* we need to get previous elements of the previous elements based on number
* of elements.
*/
// creating array from coordinates in all quadrants
function demo (n) {
// pushing initial coordinates
for (let i = 1; i <= Math.sqrt(n); i++) {
coordinates.push([-i, i], [i-1, i], [i, i], [-i, i-1], [i-1, i-1], [i, i-1], [-i, -i], [i-1, -i], [i, -i])
for (let j = 3; j < Math.sqrt(n); j++) {
coordinates.push([-i, i-j], [i-j, i-j], [i, i-j], [i-j, -i])
}
}
// pushing missing coordinates
/* for (let i = 1; i <= Math.sqrt(n); i++) {
coordinates.push([i-2, i], [-i, i-2], [i-2, i-2], [i, i-2])
} */
for (let i = 0; i < obj; i++) {
points.push(coordinates[i])
}
}
demo(obj)
// sorting multidimensional array
points.sort(function (a, b) {
return a[1] - b[1]
})
/* // print array as row and column of coordinates
for (let x = 0; x < Math.sqrt(obj); x++) {
let el = []
for (let i = 0; i < Math.sqrt(obj); i++){
el.push(points[i + Math.sqrt(obj) * x])
}
console.log(el)
*/
}
If I understand you correctly you want to have the coordinates in an order so that the left upper corner is first and right lower corner is last, right?
You can try it this way
let
size = 81, //ie a 7x7 grid,
rc = Math.floor(Math.sqrt(size)) //number of rows/columns
max = Math.floor(rc / 2), //maximum x and y coordinates
min = -1 * max; //minimim x and y coordinates
coords = [] //the array of coordinates
//as the positive y coordinates should be first, iterate from max down to min
for (let y = max; y >= min; y--)
//for each row, iterate the x cooridinates from min up to max
for (let x = min; x <= max; x++)
coords.push([x,y]);
for (let i = 0; i < rc; i++) {
let row = coords.slice(i*rc, (i+1)*rc); //get one full row of coordinates
console.log(row.map(x => formatCoordinate(x)).join("")); //and display it
}
function formatCoordinate(x) {
return "|" + `${x[0]}`.padStart(3, " ") + "/" + `${x[1]}`.padStart(3, " ") + "|"
}
Another way, is, just put your coordinates in the array in any order, and sort the values afterwards. But you have to sort by x and y coordinate,
let
size = 81, //ie a 7x7 grid,
rc = Math.floor(Math.sqrt(size)) //number of rows/columns
max = Math.floor(rc / 2), //maximum x and y coordinates
min = -1 * max; //minimim x and y coordinates
coords = [] //the array of coordinates
//coords will be [[-3, -3], [-3, -2], [-3, -1] ..., [3, 3]]
for (let i = min; i <= max; i++)
for (let j = min; j <= max; j++)
coords.push([i,j]);
//sort coords to be [[-3, 3], [-2, 3], [-1, 3], ... [3, -3]]
coords.sort((a, b) => {
if (a[1] != b[1]) //if y coordinates are different
return b[1] - a[1]; //higher y coordinates come first
return a[0] - b[0]; //lower x coordinates come firs
})
for (let i = 0; i < rc; i++) {
let row = coords.slice(i*rc, (i+1)*rc); //get one full row of coordinates
console.log(row.map(x => formatCoordinate(x)).join("")); //and display it
}
function formatCoordinate(x) {
return "|" + `${x[0]}`.padStart(3, " ") + "/" + `${x[1]}`.padStart(3, " ") + "|"
}
Both approaches assume that size is the square of an odd number, but you can of course adapt them any way you want, ie in principle you just need to set min and max to any values you want, and both approaches will create a square of coordinates from [[min/max] ... [max/min]].
So I have a 2D array created like this:
//Fill screen as blank
for(var x = 0; x<500; x++ ){
screen[x] = [];
for(var y = 0; y<500; y++ ){
screen[x][y] = '#ffffff';
}
}
And was wondering if there's an easy way to convert it to an ImageData object so I can display it on a canvas?
Flattening arrays
The first thing you'll have to learn is how to flatten a 2d array. You can use a nested loop and push to a new 1d array, but I prefer to use reduce and concat:
const concat = (xs, ys) => xs.concat(ys);
console.log(
[[1,2,3],[4,5,6]].reduce(concat)
)
Now you'll notice quickly enough that your matrix will be flipped. ImageData concatenates row by row, but your matrix is grouped by column (i.e. [x][y] instead of [y][x]). My advice is to flip your nested loop around :)
From "#ffffff" to [255, 255, 255, 255]
You now have the tool to create a 1d-array of hex codes (screen.reduce(concat)), but ImageData takes an Uint8ClampedArray of 0-255 values! Let's fix this:
const hexToRGBA = hexStr => [
parseInt(hexStr.substr(1, 2), 16),
parseInt(hexStr.substr(3, 2), 16),
parseInt(hexStr.substr(5, 2), 16),
255
];
console.log(
hexToRGBA("#ffffff")
);
Notice that I skip the first "#" char and hard-code the alpha value to 255.
Converting from hex to RGBA
We'll use map to convert the newly created 1d array at once:
screen.reduce(concat).map(hexToRGBA);
2d again?!
Back to square one... We're again stuck with an array of arrays:
[ [255, 255, 255, 255], [255, 255, 255, 255], /* ... */ ]
But wait... we already know how to fix this:
const flattenedRGBAValues = screen
.reduce(concat) // 1d list of hex codes
.map(hexToRGBA) // 1d list of [R, G, B, A] byte arrays
.reduce(concat); // 1d list of bytes
Putting the data to the canva
This is the part that was linked to in the comments, but I'll include it so you can have a working example!
const hexPixels = [
["#ffffff", "#000000"],
["#000000", "#ffffff"]
];
const concat = (xs, ys) => xs.concat(ys);
const hexToRGBA = hexStr => [
parseInt(hexStr.substr(1, 2), 16),
parseInt(hexStr.substr(3, 2), 16),
parseInt(hexStr.substr(5, 2), 16),
255
];
const flattenedRGBAValues = hexPixels
.reduce(concat) // 1d list of hex codes
.map(hexToRGBA) // 1d list of [R, G, B, A] byte arrays
.reduce(concat); // 1d list of bytes
// Render on screen for demo
const cvs = document.createElement("canvas");
cvs.width = cvs.height = 2;
const ctx = cvs.getContext("2d");
const imgData = new ImageData(Uint8ClampedArray.from(flattenedRGBAValues), 2, 2);
ctx.putImageData(imgData, 0, 0);
document.body.appendChild(cvs);
canvas { width: 128px; height: 128px; image-rendering: pixelated; }
I suspect your example code is just that, an example, but just in case it isn't there are easier way to fill an area with a single color:
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, 500, 500);
But back to flattening the array. If performance is a factor you can do it in for example the following way:
(side note: if possible - store the color information directly in the same type and byte-order you want to use as converting from string to number can be relatively costly when you deal with tens of thousands of pixels - binary/numeric storage is also cheaper).
Simply unwind/flatten the 2D array directly to a typed array:
var width = 500, height = 500;
var data32 = new Uint32Array(width * height); // create Uint32 view + underlying ArrayBuffer
for(var x, y = 0, p = 0; y < height; y++) { // outer loop represents rows
for(x = 0; x < width; x++) { // inner loop represents columns
data32[p++] = str2uint32(array[x][y]); // p = position in the 1D typed array
}
}
We also need to convert the string notation of the color to a number in little-endian order (format used by most consumer CPUs these days). Shift, AND and OR operations are multiple times faster than working on string parts, but if you can avoid strings at all that would be the ideal approach:
// str must be "#RRGGBB" with no alpha.
function str2uint32(str) {
var n = ("0x" + str.substr(1))|0; // to integer number
return 0xff000000 | // alpha (first byte)
(n << 16) | // blue (from last to second byte)
(n & 0xff00) | // green (keep position but mask)
(n >>> 16) // red (from first to last byte)
}
Here we first convert the string to a number - we shift it right away to a Uint32 value to optimize for the compiler now knowing we intend to use the number in the following conversion as a integer number.
Since we're most likely on a little endian plaform we have to shift, mask and OR around bytes to get the resulting number in the correct byte order (i.e. 0xAABBGGRR) and OR in a alpha channel as opaque (on a big-endian platform you would simply left-shift the entire value over 8 bits and OR in an alpha channel at the end).
Then finally create an ImageData object using the underlying ArrayBuffer we just filled and give it a Uint8ClampedArray view which ImageData require (this has almost no overhead since the underlying ArrayBuffer is shared):
var idata = new ImageData(new Uint8ClampedArray(data32.buffer), width, height);
From here you can use context.putImageData(idata, x, y).
Example
Here filling with a orange color to make the conversion visible (if you get a different color than orange then you're on a big-endian platform :) ):
var width = 500, height = 500;
var data32 = new Uint32Array(width * height);
var screen = [];
// Fill with orange color
for(var x = 0; x < width; x++ ){
screen[x] = [];
for(var y = 0; y < height; y++ ){
screen[x][y] = "#ff7700"; // orange to check final byte-order
}
}
// Flatten array
for(var x, y = 0, p = 0; y < height; y++){
for(x = 0; x < width; x++) {
data32[p++] = str2uint32(screen[x][y]);
}
}
function str2uint32(str) {
var n = ("0x" + str.substr(1))|0;
return 0xff000000 | (n << 16) | (n & 0xff00) | (n >>> 16)
}
var idata = new ImageData(new Uint8ClampedArray(data32.buffer), width, height);
c.getContext("2d").putImageData(idata, 0, 0);
<canvas id=c width=500 height=500></canvas>
How can i create something like this in QML using javascript?
Actually I know how to create rectangles in QML but want to do something like this. QML canvas can be of any size but whenever QML section is loaded multiple squares are generated with random sizes and colors without overlapping. When I'm trying to do this rectangles are generated in a list form.
I'm a web developer(ruby on rails oriented) but new to such javascript stuff. Any help will be appreciated.
As #ddriver already noticed, the simpliest decision is to loop through all children to find a room to a new rectangle.
Rectangle {
id: container
anchors.fill: parent
property var items: [];
Component {
id: rect
Rectangle {
color: Qt.rgba(Math.random(),Math.random(),Math.random(),1);
border.width: 1
border.color: "#999"
width: 50
height: 50
}
}
Component.onCompleted: {
var cnt = 50;
for(var i = 0;i < cnt;i ++) {
for(var t = 0;t < 10;t ++) {
var _x = Math.round(Math.random() * (mainWindow.width - 200));
var _y = Math.round(Math.random() * (mainWindow.height - 200));
var _width = Math.round(50 + Math.random() * 150);
var _height = Math.round(50 + Math.random() * 150);
if(checkCoord(_x,_y,_width,_height)) {
var item = rect.createObject(container,{ x: _x, y: _y, width: _width, height: _height });
container.items.push(item);
break;
}
}
}
}
function checkCoord(_x,_y,_width,_height) {
if(container.items.length === 0)
return true;
for(var j = 0;j < container.items.length;j ++) {
var item = container.children[j];
if(!(_x > (item.x+item.width) || (_x+_width) < item.x || _y > (item.y+item.height) || (_y+_height) < item.y))
return false;
}
return true;
}
}
Yes, this is not so wise solution but it still can be improved.
If you want efficiency, it will come at the cost of complexity - you will have to use some space partition algorithm. Otherwise, you could just generate random values until you get enough that are not overlapping.
Checking whether two rectangles overlap is simple - if none of the corners of rectangle B is inside rectangle A, then they don't overlap. A corner/point is inside a rectangle if its x and y values are in the range of the rectangle's x and width and y and height respectively.
In JS Math.random() will give you a number between 0 and 1, so if you want to make a random value for example between 50 and 200, you can do that via Math.random() * 150 + 50.
Have an array, add the initial rectangle value to it, then generate new rectangle values, check if they overlap with those already in the array, if not - add them to the array as well. Once you get enough rectangle values, go ahead and create the actual rectangles. Since all your rectangles are squares, you can only go away with 3 values per square - x, y and size.
I hope someone can guide me on how to convert long data points into arrays as i have a long list to plot and i hope of an easier way to loop instead of typing x 50 times.
Currently, i have data points where x increment of +.25 and y is calculated from a formula below.
Example:
dataPoints: [
{ x: 0, y: 1000*(0.5/(50*0.6))* (Math.exp(-((6)/(50*0.6)*0))) }
];
Link to demo: http://jsfiddle.net/QwZuf/95/
Thank you!
You just need a simple for loop:
var dataPoints = [];
for (var x = 0; x <= 12.5; x += 0.25) {
dataPoints.push({
x: x,
y: 1000*(0.5/(50*0.6))* (Math.exp(-((6)/(50*0.6)*x)))
});
}
and then pass that array as the dataPoints parameter to the plotting function.
See http://jsfiddle.net/alnitak/xQpv7/