How to trigger a function repeatedly - javascript

I am working on a randomising function for a game in javascript and jquery. I have written this to randomise the position of a square in a 8x8x64px grid, and give the player a point when their character moves over it. The function works once, but wont repeat.
The relevant script
Every time the player moves it searches for
if (xNum==ptX && yNum==ptY) {
getPoint();
pointRand();
}
yNum and xNum is the player's coordinates and ptY and ptX is the point's. Movement occurs on keyUp for the arrow keys, and the if is also executed then.
Corresponding functions
//Score
var ptAllow = true;
var pt = 0;
var ptX = 7;
var ptY = 7;
var yPt = ptX*64+"px";
var xPt = ptY*64+"px";
function getPoint() {
if (ptAllow == true) {
pt++;
document.getElementById("scoreCounter").innerHTML = "score: "+pt;
document.getElementById("scoreFin").innerHTML = "score: "+pt;
}
}
function pointRand() {
ptX = Math.floor(Math.random() * 8) + 1;
ptY = Math.floor(Math.random() * 8) + 1;
ptX--;
ptY--;
yPt = ptX*64+"px";
xPt = ptY*64+"px";
$("#point").animate({"left": xPt, "top": yPt}, 100);
}
Like I said, It works perfectly the first time you move over a point, but after that nothing happens. . ptAllow is set to false once the player hits an obstacle, and the game is over.
Edit: There are no errors in the browser console, and the reason for adding and subtracting in pointRand() is that math.floor does not seem to work with a lowest value of zero.

Related

Three.js performance very slow using onMouseMove with RayCaster

I'm building an application in three.js, however I'm having real problems with performance. This part of the application is based upon the Voxel Painter example. In my version, the user clicks on a cell to begin placement, drags the cursor to where they wish to end placement, and clicks to end.
function onDocumentMouseMove(event) {
//set up mouse and raycaster
event.preventDefault();
mouse.set((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1);
raycaster.setFromCamera(mouse, camera);
switch (buildMode) {
case buildModes.CORRIDOR:
scene.add(rollOverFloor);
var intersects = raycaster.intersectObjects(gridObject);
if (intersects.length > 0) {
var intersect = intersects[0];
if (beginPlace == true) {
//store the intersection position
var endPlace = new THREE.Vector3(0, 0, 0);
endPlace.copy(intersect.point).add(intersect.face.normal);
endPlace.divideScalar(step).floor().multiplyScalar(step).addScalar(step / step);
endPlace.set(endPlace.x, 0, endPlace.z);
corridorDrag(endPlace);
}
//if user hasn't begun to place the wall
else {
//show temporary wall on grid
rollOverFloor.position.copy(intersect.point).add(intersect.face.normal);
rollOverFloor.position.divideScalar(step).floor().multiplyScalar(step).addScalar(step / step);
rollOverFloor.position.set(rollOverFloor.position.x, 0, rollOverFloor.position.z);
}
}
break;
}
render();
}
The code above is called when the user moves the mouse (there are many buildmodes in the main application, but I have not included them here). This function simply gets a start and end point, the corridorDrag() function fills in the cells between the start and end points:
function corridorDrag(endPlace) {
deleteFromScene(stateType.CORRIDOR_DRAG);
var startPoint = startPlace;
var endPoint = endPlace;
var zIntersect = new THREE.Vector3(startPoint.x, 0, endPoint.z);
var xIntersect = new THREE.Vector3(endPoint.x, 0, startPoint.z);
var differenceZ = Math.abs(startPlace.z - zIntersect.z);
var differenceX = Math.abs(startPlace.x - xIntersect.x);
var mergedGeometry = new THREE.Geometry();
for (var i = 0; i <= (differenceZ / step); i++) {
for (var j = 0; j <= (differenceX / step); j++) {
var x = startPlace.x;
var y = startPlace.y;
var z = startPlace.z;
if (endPoint.x <= (startPlace.x )) {
if (endPoint.z <= (startPlace.z)) {
x = x - (step * j);
z = z - (step * i);
}
else if (endPoint.z >= (startPlace.z)) {
x = x - (step * j);
z = z + (step * i);
}
} else if (endPoint.x >= (startPlace.x)) {
if (endPoint.z <= (startPlace.z)) {
x = x + (step * j);
z = z - (step * i);
}
else if (endPoint.z >= (startPlace.z)) {
x = x + (step * j);
z = z + (step * i);
}
}
floorGeometry.translate(x, y, z);
mergedGeometry.merge(floorGeometry);
floorGeometry.translate(-x, -y, -z);
}
}
var voxel = new THREE.Mesh(mergedGeometry, tempMaterial);
voxel.state = stateType.CORRIDOR_DRAG;
scene.add(voxel);
tempObjects.push(voxel);
}
Firstly, the deleteFromScene() function removes all current highlighted cells from the scene (see below). The code then (I believe), should create a number of meshes, depending on the start and end points, and add them to the scene.
function deleteFromScene(state) {
tempObjects = [];
var i = scene.children.length;
while (i--) {
if (scene.children[i].state != undefined)
if (scene.children[i].state == state)
scene.children.splice(i, 1);
}
}
As I said, it is very, very slow. It also appears to be adding an obscene amount of vertices to the renderer, as seen in the WebGLRenderer stats window. I have no idea why it's adding so many vertices, but I'm assuming that's why it's rendering so slowly.
The application can be viewed here - the problem can be seen by clicking on one cell, dragging the cursor to the other end of the grid, and observing the time taken to fill in the cells.
Thank you in advance, this really is a last resort.
A few years ago Twitter put out an update. In this update they had just introduced infinite scrolling and on the day of its release the update was crashing users browsers. Twitter engineers did some investigating and found that the crashes were the result of the scroll event firing hundreds of times a second.
Mouse events can fire many MANY times a second and can cause your code to execute too often, which slows down the browser and (in many cases) crashes it. The solution for Twitter (and hopefully you) was simple: Poll your event.
Inside your mousemove event handler check that it has been some number of milliseconds since the last move event.
var lastMove = Date.now();
function onDocumentMouseMove(event) {
if (Date.now() - lastMove < 31) { // 32 frames a second
return;
} else {
lastMove = Date.now();
}
// your code here
}
I hope that helps!

How do I determine the efficiency of mouse movement from Point A to Point B in Javascript?

I am trying to create an analytical program which keeps track of user mouse movement on a website and stores the data in a DB. Here is where I am stuck:
Assuming the mouse is always starting at the middle of the screen, and the user is instructed to move it to a particular element, how do I determine the efficiency and accuracy of that movement. I need to keep in mind the duration from start of hovering till the click, but I want to also include the hovering path of the mouse.
A perfect score would be a perfect line from Point A to Point B in x seconds, how do I determine the score of a curved path in 2x seconds, or an instance where the path goes in the wrong direction before proceeding to Point B? Are there any algorithms in existence?
Thanks for your help!
Here is a JSFiddle that I created. Click on the START box and then click on the FINISH box. Hopefully this will help you get started.
var start = false;
var start_time,end_time;
var points = [];
$("#start").click(function() {
start = true;
points = [];
start_time = Date.now();
});
$("#finish").click(function() {
start = false;
distance = travelledDistance();
time = (Date.now() - start_time)/1000;
var center_x_start = $("#start").offset().left + $("#start").width() / 2;
var center_y_start = $("#start").offset().top + $("#start").height() / 2;
var center_x_finish = $("#finish").offset().left + $("#finish").width() / 2;
var center_y_finish = $("#finish").offset().top + $("#finish").height() / 2;
var straight_distance = Math.round(Math.sqrt(Math.pow(center_x_finish - center_x_start, 2) + Math.pow(center_y_finish - center_y_start, 2)));
$("#time").text(+time+"s");
$("#distance").text(distance+"px");
$("#straight_distance").text(straight_distance+"px");
});
$(document).mousemove(function( event ) {
if(!start)
return;
points.push(event.pageX + "," + event.pageY);
});
function travelledDistance(){
var distance = 0;
for (i = 0; i < points.length - 1; i++) {
start_point = points[i].split(",");
end_point = points[i+1].split(",");
distance += Math.round(Math.sqrt(Math.pow(end_point[0] - start_point[0], 2) + Math.pow(end_point[1] - start_point[1], 2)));
}
return distance;
}
UPDATE
I made a new version here. Now you can drag the targets to check the different results.

move div smoothly with javascript/jquery and an array of pos

I'm looking for a way to move a div from an array of position with javascript/jquery.
I have trying to do it with jquery.animate but he moved the div with a pause at each iteration of my array.
That could be something like move the div from 0,0 to 120px,230px passing by the 23px,35px;45px,50px etc...
That is for moving an game character on a Tile map
So as requested, some bit of code
First you have a global timer that call a function at short interval to see if it have any action to execute.
In this loop a routine look if some mobile tiles are waiting of any mouvement.
Mobiles are declared as Object class and have a sub function that do the deplacement like that
setPos:function(coord){
var pos = jQuery("#"+this.id).position();
var x = (coord[0] - 32 + this.screenOffX + this.xOffset) - pos.left;
var y =(coord[1] + this.yOffset) - pos.top;
//this.stopAnimation();
//this.startAnimation(this.walkingAnimation);
jQuery("#"+this.id).animate({
left: '+='+ x,
top: '+='+ y
}, 33, function() {
// Animation complete.
});
},
That is a bit messy cause i trying a lot of thing to do the smooth movement that i'm looking for.
so setPos is calling in another place like that
stepMobile:function(mobile){
var wp;/*TEST*/
mobile.changeState("idle");
var ind = mobile.getWayPointIndex();
while(ind < (mobile.getWayPoints()).length - 1){
if (ind < (mobile.getWayPoints()).length - 1) {
wp = (mobile.getWayPoints())[ind + 1];
if (getTime() > wp.time) {
mobile.setWayPointIndex(ind + 1);
ind = ind +1;
}
}
wp = (mobile.getWayPoints())[ind];
var x;
var y = 0;
var z;
x = this.tileWidth * (wp.getTile()).getCol();
z = this.tileHeight * (wp.getTile()).getRow();
var elapsed = getTime() - wp.getTime();
console.log(elapsed);
if (ind == (mobile.getWayPoints()).length - 1) {
console.log('checkForOnStopEvent()');
} else {
//x += 1 * mobile.getWalkSpeed() * mobile.getCosAngle();
//z += 1 * mobile.getWalkSpeed() * mobile.getSinAngle();
}
var coord = this.mapToScreen(x, y, -z);
mobile.setPos(coord);
ind = mobile.getWayPointIndex();
}
},
Again lot of junk code here cause i literally burned my brain but i didn't get any good result.
And you have that global function that run this function over all mobiles waiting for deplacement.

Garbage collection pauses; Javascript

I've been working on creating a basic 2D tiled game and have been unable to pinpoint the source of noticeable pauses lasting ~100-200ms every second or two, but it seems like GC pauses as when I profiled my app, each game loop is taking around 4ms with a target of 60fps, which means it is running well within the required limit (16ms).
As far as I am aware, I have moved my object variables outside the functions that use them so they never go out of scope and therefore should not be collected, but I am still getting pauses.
Each game loop, the tiles are simply moved 1px to the left (to show smoothness of game frames), and apart from that, all that is called is this draw map function: (NOTE, these functions are defined as part of my engine object at startup so is this true that these functions are not created then collected each time they are called?).
engine.map.draw = function () {
engine.mapDrawMapX = 0;
engine.mapDrawMapY = 0;
// Just draw tiles within screen (and 1 extra on both x and y boundaries)
for (engine.mapDrawJ = -1; engine.mapDrawJ <= engine.screen.tilesY; engine.mapDrawJ++) {
for (engine.mapDrawI = -1; engine.mapDrawI <= engine.screen.tilesX; engine.mapDrawI++) {
//calculate map location (viewport)
engine.mapDrawMapX = engine.mapDrawI + engine.viewport.x;
engine.mapDrawMapY = engine.mapDrawJ + engine.viewport.y;
engine.mapDrawTile = (engine.currentMap[engine.mapDrawMapY] && engine.currentMap[engine.mapDrawMapY][engine.mapDrawMapX]) ? engine.currentMap[engine.mapDrawMapY][engine.mapDrawMapX] : '';
engine.tile.draw(engine.mapDrawI, engine.mapDrawJ, engine.mapDrawTile);
}
}
};
And the method called to draw each tile is:
engine.tile.drawTile = new Image(0,0);
engine.tile.draw = function (x, y, tile) {
if ('' != tile) {
engine.tile.drawTile = engine.tile.retrieve(tile); //this returns an Image() object
engine.context.drawImage(engine.tile.drawTile,
x * TILE_WIDTH + engine.viewport.offsetX,
y * TILE_HEIGHT + engine.viewport.offsetY,
TILE_WIDTH, TILE_HEIGHT);
} else {
engine.context.clearRect(x * TILE_WIDTH, y * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
}
};
As per request, here are the store and retrieve functions:
engine.tile.store = function (id, img) {
var newID = engine.tile.images.length;
var tile = [id, new Image()];
tile[1] = img;
engine.tile.images[newID] = tile; // store
};
engine.tile.retrieveI;
engine.tile.retrieve = function (id) {
//var len = engine.tile.images.length;
for (engine.tile.retrieveI = 0; engine.tile.retrieveI < engine.tile.images.length; engine.tile.retrieveI++) {
if (engine.tile.images[engine.tile.retrieveI][0] == id) {
return engine.tile.images[engine.tile.retrieveI][1]; // return image
}
}
//return null;
};

How to hide/show multiple square at different time

I'm still struggling with my simple javascript game. Here is my previous question: Simple javascript game, hide / show random square
Some square show and hide randomely for a few seconds and you have to click on them. I use RaphaelJS to draw the square and a few of JQuery ($.each() function)
I can't make the hide/show with the setInterval working for each square. The function made by Mishelle looks good but I get a "This is not a function" error.. I've test different stuff but it's not as obvious as I thought :/
window.onload = function() {
var paper = new Raphael(document.getElementById('canvas_container'), 500, 500);
// random function to for the x and y axis of the square
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var rectanglemain = paper.rect(0, 0, 500, 500).attr({fill: "white",});
var win_click = 0; // set the var to count the click on the square
var recs = [];
for(var i = 0; i < 50; i++) {
var x = random(1,450);
var y = random(1,450);
var rec = paper.rect(x, y, 50, 50).attr({fill: 'blue'});
recs.push(rec); // add the square in an array
recs[i].click(function () {
//counting the clicks
win_click = win_click + 1;
})
function hideSquare() {recs[i].hide();}
hideSquare();
}
rectanglemain.click(function () {
alert('you click on ' + win_click + ' squares');
});
/* here is a function made by Mishelle on my previous question, unfortunately I can't make it work (this is not a function error).
function showBriefly (timeFromNow, duration) {
window.setTimeout(this.rec.show, timeFromNow);
window.setTimeout(this.rec.hide, timeFromNow + duration);
}
recs[2].showBriefly(1000, 3000); to test the function
*/
}
Thanks for the help :)
try
window.setTimeout(function(){this.rec.show();}, timeFromNow )
Just came across your problem, just in case you read this and you want to know what was the problem. this is undefined within the callback, thus you need to store which rectangle you were referring to in a variable (I've called it square), see my code:
showBriefly: function(timeFromNow, duration) {
square = this.box;
setTimeout(function(){square.show();}, timeFromNow )
setTimeout(function(){square.hide();}, timeFromNow + duration )
}
Cheers

Categories

Resources