Im making a game with javascript, css and html only, it's a simple game, where the character must hit the cakes so you get more points. Im having an issue, on the cakes movement and positioning. I could set them on the screen randomly and going horizontally to the right, but I can't that my function repeats itself nor limit the cakes to a certain zone of the screen.
This is my HTML:
<script language ="javascript">
function createNewCake() {
var myDiv = document.createElement('div');
myDiv.id = "cake0";
myDiv.className = "cake-div";
return myDiv;
}
function rotateElement(elem, degrees) {
var rad=degrees*(Math.PI / 180.0);
var text = "rotate(" + degrees + "rad)";
elem.style.transform = text;
elem.style.webkitTransform = text;
elem.style.mozTransform = text;
elem.style.oTransform = text;
elem.style.msTransform = text;
}
var cakes = new Array();
var colors = new Array();
colors[0] = "images/bolo1.png";
colors[1] = "images/bolo2.png";
colors[2] = "images/bolo3.png";
colors[3] = "images/maca.png";
for (var i=0; i<20; i++) {
var aCake = createNewCake();
aCake.id = "cake" + i;
var index = Math.floor(Math.random() * (colors.length + 1));
aCake.style.backgroundImage = "url('" + colors[index]+ "')";
aCake.style.left = Math.floor(Math.random() * window.innerWidth);
aCake.style.top = Math.floor(Math.random() * window.innerHeight);
document.body.appendChild(aCake);
cakes.push(aCake);
}
animate();
function animate() {
requestAnimationFrame(animate);
for (var i=0; i < cakes.length; i++) {
var pixel = Number(cakes[i].style.left.replace("px",""));
cakes[i].style.left = pixel + 2 + "px";
}
}
</script>
</body>
I got it done, thanks all!
It was just if checking if the image pixel is hitting the max width! :D
Related
Here is the current index (HTML and JavaScript):
var maxZ = 1000;
window.onload = function() {
var add = document.getElementById("add");
add.onclick = addSquare;
var colors = document.getElementById("colors");
colors.onclick = changeColors;
var squareCount = parseInt(Math.random() * 21) + 30;
for (var i = 0; i < squareCount; i++) {
addSquare();
}
}
//Generates color
function getRandomColor() {
var letters = "0123456789abcdef";
var result = "#";
for (var i = 0; i < 6; i++) {
result += letters.charAt(parseInt(Math.random() * letters.length));
}
return result;
}
function addSquare() {
var square = document.createElement("div");
var squareArea = document.getElementById("squareArea");
square.className = "square";
square.style.left = parseInt(Math.random() * 650) + "px";
square.style.top = parseInt(Math.random() * 250) + "px";
square.style.backgroundColor = getRandomColor();
square.onclick = squareClick;
squareArea.appendChild(square);
}
function changeColors() {
var squares = document.querySelectorAll("#squareArea div");
for (i = 0; i < squares.length; i++) {
squares[i].style.backgroundColor = getRandomColor();
}
}
function squareClick() {
var oldZ = parseInt(this.style.zIndex);
if (oldZ == maxZ) {
this.parentNode.removeChild(this);
} else {
maxZ++;
this.style.zIndex = maxZ;
}
}
<html>
<head>
<title>Colored Squares</title>
<script src="Squares.js" type="text/javascript"></script>
<link href="Squares.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="squareArea"></div>
<div>
<button id="add">Add Square</button>
<button id="colors">Change Color</button>
</div>
<p>Click a square to move it to the front.</p>
</body>
</html>
Here is the goal:
Edit Colored squares to add the following functionality.
Users will be able to click a square and drag it to any position on the screen. - When the user lets go of the click it will stay in that position.
In order to accomplish this you will need to add Prototype and Scriptaculous to the scripts loaded in the html and use their functionality.
You will also need to create 3 functions in the JavaScript file:
function squareMouseMove(event)
function squareMouseDown(event)
function squareMouseUp(event)
Add appropriate global variables
Change the creation of the squares to added observers for the mouse events that execute the functions.
The issue that you have with your code is that the squares are empty, so they collapse to nothing and you will not see them. Add a width and height to them so you can see them.
Another issue is that you're specifying the left and right, but these properties will have no effect unless you make them absolutely positioned.
Here is your code working with the width, height, and position properties added:
var maxZ = 1000;
window.onload = function() {
var add = document.getElementById("add");
add.onclick = addSquare;
var colors = document.getElementById("colors");
colors.onclick = changeColors;
var squareCount = parseInt(Math.random() * 21) + 30;
for (var i = 0; i < squareCount; i++) {
addSquare();
}
}
//Generates color
function getRandomColor() {
var letters = "0123456789abcdef";
var result = "#";
for (var i = 0; i < 6; i++) {
result += letters.charAt(parseInt(Math.random() * letters.length));
}
return result;
}
function addSquare() {
var square = document.createElement("div");
var squareArea = document.getElementById("squareArea");
square.className = "square";
square.style.left = parseInt(Math.random() * 650) + "px";
square.style.top = parseInt(Math.random() * 250) + "px";
square.style.width = "100px";
square.style.height = "100px";
square.style.position = "absolute";
square.style.backgroundColor = getRandomColor();
square.onclick = squareClick;
squareArea.appendChild(square);
}
function changeColors() {
var squares = document.querySelectorAll("#squareArea div");
for (i = 0; i < squares.length; i++) {
squares[i].style.backgroundColor = getRandomColor();
}
}
function squareClick() {
var oldZ = parseInt(this.style.zIndex);
if (oldZ == maxZ) {
this.parentNode.removeChild(this);
} else {
maxZ++;
this.style.zIndex = maxZ;
}
}
<html>
<head>
<title>Colored Squares</title>
<script src="Squares.js" type="text/javascript"></script>
<link href="Squares.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="squareArea"></div>
<div>
<button id="add">Add Square</button>
<button id="colors">Change Color</button>
</div>
<p>Click a square to move it to the front.</p>
</body>
</html>
I am trying to solve a problem for an assignment, where the objective is to build a game. The game loads with smiley faces shown across two columns(divs) laid out side by side. There is one extra smiley on the left div, and if the user clicks on that extra smiley, the next run of the game should:
Increase the number of smileys by 5, for the next run
Generate a whole new set of smileys for the second run(by removing existing smileys from the current run).
The code I have so far has a bug. If I include the code for removing child nodes from the current run of the game, in the next run 5 more smileys are not added. If I remove this code, then in the next run, 5 more smileys are added but the previous smileys are at the same position (meaning they are not removed).
Here's the JS code:
var numberOfFaces = 5;
var theLeftSide = document.getElementById("leftSide");
var theRightSide = document.getElementById("rightSide");
var theBody = document.getElementsByTagName("body")[0];
function generateFaces() {
//remove current children
while(theLeftSide.firstChild){
theLeftSide.removeChild(theLeftSide.firstChild);
}
while(theRightSide.firstChild){
theRightSide.removeChild(theRightSide.firstChild);
}
while(numberOfFaces > 0) {
var face = document.createElement("img");
face.src = "http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png";
var topValue = generateRandomNumber(0,400);
face.style.top = topValue+"px";
var leftValue = generateRandomNumber(0,400);
face.style.left = leftValue+"px";
theLeftSide.appendChild(face);
//changes
var leftSideImages = theLeftSide.cloneNode(true);
var leftSideLastImage = leftSideImages.lastChild;
leftSideImages.removeChild(leftSideLastImage);
theRightSide.appendChild(leftSideImages);
//4th - generate 5 more faces for correct click in left side
theLeftSide.lastChild.onclick = function nextLevel(event){
event.stopPropagation();
numberOfFaces += 5;
generateFaces();
};
theBody.onclick = function gameOver() {
alert("Game Over!");
theBody.onclick = null;
theLeftSide.lastChild.onclick = null;
};
numberOfFaces--;
}
}
function generateRandomNumber(min, max) {
return Math.floor(Math.random() * (max-min + 1));
}
And this is the link to the Fiddle.
I also made a Codepen pen that has the same code.
Would appreciate any help.
Update -
My function structure was somewhat different in earlier attempts. I revised it based on some forum comments. Here's the earlier structure-
function generateFaces() {
//remove current children
while(theLeftSide.firstChild){
theLeftSide.removeChild(theLeftSide.firstChild);
}
while(theRightSide.firstChild){
theRightSide.removeChild(theRightSide.firstChild);
}
while(numberOfFaces > 0) {
var face = document.createElement("img");
face.src = "http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png";
var topValue = generateRandomNumber(0,400);
face.style.top = topValue+"px";
var leftValue = generateRandomNumber(0,400);
face.style.left = leftValue+"px";
theLeftSide.appendChild(face);
numberOfFaces--;
}
//changes
var leftSideImages = theLeftSide.cloneNode(true);
var leftSideLastImage = leftSideImages.lastChild;
leftSideImages.removeChild(leftSideLastImage);
theRightSide.appendChild(leftSideImages);
//4th - generate 5 more faces for correct click in left side
theLeftSide.lastChild.onclick = function nextLevel(event){
event.stopPropagation();
numberOfFaces += 5;
generateFaces();
};
theBody.onclick = function gameOver() {
alert("Game Over!");
theBody.onclick = null;
theLeftSide.lastChild.onclick = null;
};
//numberOfFaces--;
}
You are decrementing numberOfFaces to zero in the while loop and add 5 again, so the value is always 5.
Change the while loop to
for(var n = 0; n < numberOfFaces; n++) {
var face = document.createElement("img");
face.src = "http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png";
var topValue = generateRandomNumber(0,400);
face.style.top = topValue+"px";
var leftValue = generateRandomNumber(0,400);
face.style.left = leftValue+"px";
theLeftSide.appendChild(face);
...
}
and each run adds an extra 5 smiley set. Altered fiddle here
Append your right child after while loop:
var numberOfFaces = 5;
var theLeftSide = document.getElementById("leftSide");
var theRightSide = document.getElementById("rightSide");
var theBody = document.getElementsByTagName("body")[0];
function generateFaces() {
//remove current children
while(theLeftSide.firstChild){
theLeftSide.removeChild(theLeftSide.firstChild);
}
while(theRightSide.firstChild){
theRightSide.removeChild(theRightSide.firstChild);
}
while(numberOfFaces > 0) {
var face = document.createElement("img");
face.setAttribute("src", "http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png");
//face.src = "http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png";
var topValue = generateRandomNumber(0,400);
face.style.top = topValue+"px";
var leftValue = generateRandomNumber(0,400);
face.style.left = leftValue+"px";
theLeftSide.appendChild(face);
//changes
var leftSideImages = theLeftSide.cloneNode(true);
var leftSideLastImage = leftSideImages.lastChild;
leftSideImages.removeChild(leftSideLastImage);
//4th - generate 5 more faces for correct click in left side
theLeftSide.lastChild.onclick = function nextLevel(event){
event.stopPropagation();
numberOfFaces += 5;
generateFaces();
};
theBody.onclick = function gameOver() {
alert("Game Over!");
theBody.onclick = null;
theLeftSide.lastChild.onclick = null;
};
numberOfFaces--;
}
theRightSide.appendChild(leftSideImages);
}
function generateRandomNumber(min, max) {
return Math.floor(Math.random() * (max-min + 1));
}
Check out codepen
I can't make the script to create random amount of divs. In this specific example between 5 and 20. The problem is in the for loop maybe? The function that generates random numbers is working correctly below in the random color function, I guess it is not recognized for some reasons. Also I am not getting any errors in firebug.
Example:
function generateDiv(){
var dfrag = document.createDocumentFragment();
var count = generateRandom(5, 20);
var i=0;
for (var i = 0; i < count; i++){
var div = document.createElement("div");
dfrag.appendChild(div);
}
}
var divs = document.getElementsByTagName("div");
for (i = 0; i < divs.length; i++) {
div = divs[i];
alterDivStyle(div);
}
function rndColor() {
var r = ('0' + generateRandom(0,255).toString(16)).substr(-2), // red
g = ('0' + generateRandom(0,255).toString(16)).substr(-2), // green
b = ('0' + generateRandom(0,255).toString(16)).substr(-2); // blue
return '#' + r + g + b;
}
function generateRandom(min, max) {
var number = Math.floor(Math.random() * (max - min )) + min;
return number;
}
function alterDivStyle(div){
div.style.width = generateRandom(20, 100) +"px";
div.style.height = generateRandom(20, 100) +"px";
div.style.backgroundColor = rndColor();
div.style.color = rndColor();
div.style.position = "absolute";
div.style.border = "solid";
div.style.borderColor = rndColor();
div.style.borderWidth = rndColor();
div.style.borderRadius = generateRandom(0, 10)+"px";
div.innerHTML = "<strong>div</strong>";
};
You never added the document fragment to the DOM
"DocumentFragments are DOM Nodes. They are never part of the main DOM tree. The usual use case is to create the document fragment, append elements to the document fragment and then append the document fragment to the DOM tree. In the DOM tree, the document fragment is replaced by all its children."
https://developer.mozilla.org/en-US/docs/Web/API/document.createDocumentFragment
1) You closed the "generateDiv function" in the wrong place, move the closing bracket from before the "var divs" to after the "var divs" loop.
2) You are altering all the existing divs in the DOM:
var divs = document.getElementsByTagName("div");
Don't do that, use dfrag.
3) Like Matthew said, you have to add dfrag to the DOM.
function generateDiv(){
var dfrag = document.createDocumentFragment();
var count = generateRandom(5, 20);
var i=0;
for (var i = 0; i < count; i++){
var div = document.createElement("div");
dfrag.appendChild(div);
}
for (i = 0; i < dfrag.childNodes.length; i++) {
div = dfrag.childNodes[i];
alterDivStyle(div);
}
document.body.appendChild(dfrag);
}
function rndColor() {
var r = ('0' + generateRandom(0,255).toString(16)).substr(-2), // red
g = ('0' + generateRandom(0,255).toString(16)).substr(-2), // green
b = ('0' + generateRandom(0,255).toString(16)).substr(-2); // blue
return '#' + r + g + b;
}
function generateRandom(min, max) {
var number = Math.floor(Math.random() * (max - min )) + min;
return number;
}
function alterDivStyle(div){
div.style.width = generateRandom(20, 100) +"px";
div.style.height = generateRandom(20, 100) +"px";
div.style.backgroundColor = rndColor();
div.style.color = rndColor();
div.style.position = "absolute";
div.style.border = "solid";
div.style.borderColor = rndColor();
div.style.borderWidth = rndColor();
div.style.borderRadius = generateRandom(0, 10)+"px";
div.innerHTML = "<strong>div</strong>";
};
generateDiv();
Somewhere in my code, I seem to be doing something wrong and I cannot tell which part is going awry. I've printed to console the values I'm getting from the various arrays and it seems to match up. Then when I run the equalization function (a la Wikipedia-Histogram Equalization) my output image is close to total black. I was trying to interpret this guy's php into javascript just to test some stuff out and figured I did a decent job. But I'm not an expert.
The pertinent parts:
function imageLoaded(ev) {
element = document.getElementById("canvas1");
c = element.getContext("2d");
im = ev.target; // the image
// read the width and height of the canvas
width = element.width;
height = element.height;
// stamp the image on the left of the canvas:
c.drawImage(im, 0, 0);
// get all canvas pixel data
imageData = c.getImageData(0, 0, width, height);
w2 = width / 2;
var reds = new Array();
var greens = new Array();
var blues = new Array();
var freqR = new Array();
var freqG = new Array();
var freqB = new Array();
if (imageData){
buildHistograms(reds, greens,blues);
buildFrequencies(reds, greens, blues, freqR, freqG, freqB);
}
var alpha = 255/(w2*height);
// run through the image
for (y = 0; y < height; y++) {
inpos = y * width * 4; // *4 for 4 ints per pixel
outpos = inpos + w2 * 4;
for (x = 0; x < w2; x++) {
//reads pixel data(of img c)to each channel of rgb
r = imageData.data[inpos++];
g = imageData.data[inpos++];
b = imageData.data[inpos++];
a = imageData.data[inpos++];
//using histogram eqalization formula:
adjR = freqR[r]*alpha;
adjG = freqG[g]*alpha;
adjB = freqB[b]*alpha;
//assigns pixel data of output image
imageData.data[outpos++] = adjR;
imageData.data[outpos++] = adjG;
imageData.data[outpos++] = adjB;
imageData.data[outpos++] = a;
}
}
// put pixel data on canvas
c.putImageData(imageData, 0,0);
}
im = new Image();
im.onload = imageLoaded;
im.src = "Lenna.png";
function buildHistograms(reds,greens,blues){
//run through image building histogram
for (y=0; y < height; y++){
inpos = y * width *4;
for (x=0; x < w2; x++){
rd = imageData.data[inpos++];
g = imageData.data[inpos++];
b = imageData.data[inpos++];
a = imageData.data[inpos++];
// Add counts to our histogram arrays for each color.
reds.push(rd);
greens.push(g);
blues.push(b);
}
}
// Sort them by keys into order
reds.sort(function(a,b){return a-b});
greens.sort(function(a,b){return a-b});
blues.sort(function(a,b){return a-b});
}
function buildFrequencies(reds, greens, blues, freqR, freqG, freqB){
// Build frequency charts for all colors: takes REDS GREENS BLUES from buildHistograms and places them on top of each other accordingly
for(i=0; i<=255; i++){
sumR=0;
sumG=0;
sumB=0;
for(j=0; j<= i; j++){
if (reds[j]){sumR+=reds[j];}
if (greens[j]){sumG+=greens[j];}
if (blues[j]){sumB+=blues[j];}
}
freqR[i] = sumR;
freqG[i] = sumG;
freqB[i] = sumB;
}
}
Any help is appreciated, Thanks.
Looks like my build frequencies section was all wrong. I modified it in this way:
var len = reds.length;
for (j=0; j < len; j++) {
var rCurrVal = reds[j];
var gCurrVal = greens[j];
var bCurrVal = blues[j];
if (freqR.hasOwnProperty(rCurrVal)) {
freqR[rCurrVal] += 1;
} else {
freqR[rCurrVal] = 1;
}
if (freqG.hasOwnProperty(gCurrVal)) {
freqG[gCurrVal] += 1;
} else {
freqG[gCurrVal] = 1;
}
if (freqB.hasOwnProperty(bCurrVal)) {
freqB[bCurrVal] += 1;
} else {
freqB[bCurrVal] = 1;
}
}
for (i=0; i<255; i++){
if ($.inArray(i,reds)===-1){freqR[i]=0;}
if ($.inArray(i,greens)=== -1){freqG[i]=0;}
if ($.inArray(i,blues)=== -1){freqB[i]=0;}
if (i>0){
freqR[i]+=freqR[i-1];
freqG[i]+=freqG[i-1];
freqB[i]+=freqB[i-1];
}
}
I need to draw a bezier curve defined by N control points which are stored in an array. I have a canvas which is 500px x 500px.
Here's the JSFiddle link : jsfiddle.net/HswXy
Entire JS code:
<script>
window.onload=function(){
var old_n=0,n=0;
var nrSelect = document.getElementById("mySelect");
var submit = document.getElementById("submit");
nrSelect.addEventListener("change",function(){
old_n=n;
n = nrSelect.selectedIndex;
var inputx,inputy,br;
if(document.getElementById("pointsdiv"))
{
for(i=1;i<=n;i++){
inputx = document.createElement('input');
inputy = document.createElement('input');
br = document.createElement('br');
inputx.type = "text";
inputy.type = "text";
inputx.size = 3;
inputy.size = 3;
inputx.id = "x_" + i;
inputy.id = "y_" + i;
inputx.value = "x_" + i;
inputy.value = "y_" + i;
inputx.addEventListener("focus",function(){if(this.value==this.id) this.value="";});
inputy.addEventListener("focus",function(){if(this.value==this.id) this.value="";});
document.getElementById("pointsdiv").appendChild(inputx);
document.getElementById("pointsdiv").appendChild(inputy);
document.getElementById("pointsdiv").appendChild(br);
}
document.getElementById("pointsdiv").id="pointsdiv_after";
}
else
{
if( old_n < n )
{
for(i=old_n+1;i<=n;i++){
inputx = document.createElement('input');
inputy = document.createElement('input');
br = document.createElement('br');
inputx.type = "text";
inputy.type = "text";
inputx.size = 3;
inputy.size = 3;
inputx.id = "x_" + i;
inputy.id = "y_" + i;
inputx.value = "x_" + i;
inputy.value = "y_" + i;
inputx.addEventListener("focus",function(){if(this.value==this.id) this.value="";});
inputy.addEventListener("focus",function(){if(this.value==this.id) this.value="";});
document.getElementById("pointsdiv_after").appendChild(inputx);
document.getElementById("pointsdiv_after").appendChild(inputy);
document.getElementById("pointsdiv_after").appendChild(br);
}
}
else
{
var parent;
for(i=n+1;i<=old_n;i++){
parent = document.getElementById("pointsdiv_after");
parent.removeChild(parent.lastChild);
parent.removeChild(parent.lastChild);
parent.removeChild(parent.lastChild);
}
}
}
});
//BEZIER CURVE
function factorial(n){
var result=1;
for(i=2;i<=n;i++){
result = result*i;
}
return result;
}
function Point(x,y){
this.x=x;
this.y=y;
}
var points = new Array();
function getPoint(t){
var i;
var x=points[0].x;
var y=points[0].y;
var factn = factorial(n);
for(i=0;i<n;i++){
var b = factn / (factorial(i)*factorial(n-i));
var k = Math.pow(1-t,n-i)*Math.pow(t,i);
// console.debug( i+": ",points[i] );
x += b*k*points[i].x;
y += b*k*points[i].y;
}
return new Point(x, y);
}
//--BEZIER CURVE
submit.addEventListener("click",function(){
if(n){
for(i=1;i<=n;i++){
var px = document.getElementById("x_"+i);
var py = document.getElementById("y_"+i);
points.push(new Point(parseInt(px.value,10),parseInt(py.value,10)));
// console.debug( points[i-1] );
}
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.beginPath();
console.debug( points[0].x, points[0].y );
context.moveTo(points[0].x, points[0].y);
var t=0.01;
while (t<=1)
{
//get coordinates at position
var p=getPoint(t);
// console.debug( p.x, p.y );
//draw line to coordinates
context.lineTo(p.x, p.y);
//increment position
t += 0.01;
}
context.stroke();
}
});
}
</script>
The problem is that it doesn't seem to work correctly. I'm testing it for 2 points now and it always starts in the upper left corner o the canvas (even if my first point is at let's say (250,250) and the length of the line is not the number of pixels it should be.. it's longer.
I'm no expert on canvas or geometry, but here is what I think: you shouldn't moveTo points[0] before drawing your faux line, since your getPoint function seems to lead you there. What I could see while debugging your code is that you first moved to (20,20), then drew a straight line to (roughly) (40,40), then started drawing gradually back to (20,20), generating that closed shape that wasn't what you were looking for.
A small (quick and dirty) change to your code made it start drawing a curve:
// DO NOT MOVE TO HERE
//context.moveTo(points[0].x, points[0].y);
var t = 0.01;
// MOVE TO THE FIRST POINT RETURNED BY getPoint
var p0 = getPoint(t);
context.moveTo(p0.x, p0.y);
t+=0.01;
// now loop from 0.02 to 1...
I'm sure you can refactor that into something better, as I said my changes were quick and dirty.
http://jsfiddle.net/HswXy/3/