Hey I am using a Spawn function I found for a javascript game I am creating to randomy generate enemies to click on. But it is very slow and I would like it to be able to generate faster and faster.. is it possible to modify this code in that way? the spawn function is at the end of the code.
function Gem(Class, Value, MaxTTL) {
this.Class = Class;
this.Value = Value;
this.MaxTTL = MaxTTL;
};
var gems = new Array();
gems[0] = new Gem('green', 10, 0.5);
gems[1] = new Gem('blue', 20, 0.4);
gems[2] = new Gem('red', 50, 0.6);
function Click(event)
{
if(event.preventDefault) event.preventDefault();
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;
var target = event.target || event.srcElement;
if(target.className.indexOf('gem') > -1){
var value = parseInt(target.getAttribute('data-value'));
var current = parseInt( score.innerHTML );
var audio = new Audio('music/blaster.mp3');
audio.play();
score.innerHTML = current + value;
target.parentNode.removeChild(target);
if (target.className.indexOf('red') > 0){
var audio = new Audio('music/scream.mp3');
audio.play();
endGame("You lose");
}
}
return false;
}
function Remove(id) {
var gem = game.querySelector("#" + id);
if(typeof(gem) != 'undefined')
gem.parentNode.removeChild(gem);
}
function Spawn() {
var index = Math.floor( ( Math.random() * 3 ) );
var gem = gems[index];
var id = Math.floor( ( Math.random() * 1000 ) + 1 );
var ttl = Math.floor( ( Math.random() * parseInt(gem.MaxTTL) * 1000 ) + 1000 ); //between 1s and MaxTTL
var x = Math.floor( ( Math.random() * ( game.offsetWidth - 40 ) ) );
var y = Math.floor( ( Math.random() * ( game.offsetHeight - 44 ) ) );
var fragment = document.createElement('span');
fragment.id = "gem-" + id;
fragment.setAttribute('class', "gem " + gem.Class);
fragment.setAttribute('data-value', gem.Value);
game.appendChild(fragment);
fragment.style.left = x + "px";
fragment.style.top = y + "px";
setTimeout( function(){
Remove(fragment.id);
}, ttl)
}
function Stop(interval) {
clearInterval(interval);
}
function endGame( msg ) {
count = 0;
Stop(interval);
Stop(counter);
var left = document.querySelectorAll("section#game .gem");
for (var i = 0; i < left.length; i++) {
if(left[i] && left[i].parentNode) {
left[i].parentNode.removeChild(left[i]);
}
}
time.innerHTML = msg || "Game Over!";
start.style.display = "block";
UpdateScore();
}
this.Start = function() {
score.innerHTML = "0";
start.style.display = "none";
interval = setInterval(Spawn, 750);
count = 4000;
counter = null;
function timer()
{
count = count-1;
if (count <= 0)
{
endGame();
return;
} else {
time.innerHTML = count + "s left";
}
}
counter = setInterval(timer, 1000);
setTimeout( function(){
Stop(interval);
}, count * 1000)
};
addEvent(game, 'click', Click);
addEvent(start, 'click', this.Start);
HighScores();
}
JS/HTML Performance tips:
1) var gems = new Array(); change to new Array(3);
2) cache all new Audio('...');
3) use getElementById it faster then querySelector('#')
4) prepare var fragment = document.createElement('span'); and cache it, use cloneNode to insert it.
5) fragment.style.left & top change to CSS3 transform: translate(). CSS3 transform use your video card GPU, style.left use CPU...
6) Use only single setInterval and run on all list of fragments.
7) You can make a pool of "fragments" and just show\hide, it will increase performance dramatically.
Basically it works slow due to many page redraws, every time you add new elements to page browser must to redraw whole screen, do not add elements, just show\hide them.
Related
Is it possible to transform this code to generate when the page loads instead of when the button is clicked. I tried to change the events to load but it does not function. I do not know what I exactly I am doing wrong.
<p><button id="generate">Generate</button></p>
<p><code id="output"></code></p>
(function() {
function IDGenerator() {
this.length = 8;
this.timestamp = +new Date;
var _getRandomInt = function( min, max ) {
return Math.floor( Math.random() * ( max - min + 1 ) ) + min;
}
this.generate = function() {
var ts = this.timestamp.toString();
var parts = ts.split( "" ).reverse();
var id = "";
for( var i = 0; i < this.length; ++i ) {
var index = _getRandomInt( 0, parts.length - 1 );
id += parts[index];
}
return id;
}
}
document.addEventListener( "DOMContentLoaded", function() {
var btn = document.querySelector( "#generate" ),
output = document.querySelector( "#output" );
btn.addEventListener( "click", function() {
var generator = new IDGenerator();
output.innerHTML = generator.generate();
}, false);
});
})();
There is small bug.
Just change the document object to window like below
window.addEventListener('DOMContentLoaded', function() {
});
The goal I am trying to achieve is to get my timer to stop when all the questions of my quiz has been answered. I have 10 total questions. I have been able to get the timer to start. But getting ot to stop on the click of submit on the 10th question is something I can't figure out.
Let me know if you know what I am doing
StackOverflow said my code was too long... I added my code to codepen. I also included my JS on here.
// variables
var score = 0; //set score to 0
var total = 10; //total nmumber of questions
var point = 1; //points per correct answer
var highest = total * point;
//init
console.log('script js loaded')
function init() {
//set correct answers
sessionStorage.setItem('a1', "b");
sessionStorage.setItem('a2', "a");
sessionStorage.setItem('a3', "c");
sessionStorage.setItem('a4', "d");
sessionStorage.setItem('a5', "b");
sessionStorage.setItem('a6', "d");
sessionStorage.setItem('a7', "b");
sessionStorage.setItem('a8', "b");
sessionStorage.setItem('a9', "d");
sessionStorage.setItem('a10', "d");
}
// timer
// var i = 1;
// $("#startButton").click(function (e) {
// setInterval(function () {
// $("#stopWatch").html(i);
// i++;
// }, 1000);
// });
// $("#resetButton").click(function (e) {
// i = 0;
// });
//hide all questions to start
$(document).ready(function() {
$('.questionForm').hide();
//show question 1
$('#question1').show();
$('.questionForm #submit').click(function() {
//get data attribute
current = $(this).parents('form:first').data('question');
next = $(this).parents('form:first').data('question') + 1;
//hide all questions
$('.questionForm').hide();
//show next question in a cool way
$('#question' + next + '').fadeIn(400);
process('' + current + '');
return false;
});
});
//process answer function
function process(n) {
// get input value
var submitted = $('input[name=question' + n + ']:checked').val();
if (submitted == sessionStorage.getItem('a' + n + '')) {
score++;
}
if (n == total) {
$('#results').html('<h3>Your score is: ' + score + ' out of ' + highest + '!</h3> <button onclick="myScore()">Add Your Name To Scoreboard!</a>')
}
return false;
}
window.yourPoints = function() {
return n;
}
function myScore() {
var person = prompt("Please enter your name", "My First Name");
if (person != null) {
document.getElementById("myScore").innerHTML =
person + " " + score
}
}
// function showTime() {
// var d = new Date();
// document.getElementById("clock").innerHTML = d.toLocaleTimeString();
// }
// setInterval(showTime, 1000);
var x;
var startstop = 0;
window.onload = function startStop() { /* Toggle StartStop */
startstop = startstop + 1;
if (startstop === 1) {
start();
document.getElementById("start").innerHTML = "Stop";
} else if (startstop === 2) {
document.getElementById("start").innerHTML = "Start";
startstop = 0;
stop();
}
}
function start() {
x = setInterval(timer, 10);
} /* Start */
function stop() {
clearInterval(x);
} /* Stop */
var milisec = 0;
var sec = 0; /* holds incrementing value */
var min = 0;
var hour = 0;
/* Contains and outputs returned value of function checkTime */
var miliSecOut = 0;
var secOut = 0;
var minOut = 0;
var hourOut = 0;
/* Output variable End */
function timer() {
/* Main Timer */
miliSecOut = checkTime(milisec);
secOut = checkTime(sec);
minOut = checkTime(min);
hourOut = checkTime(hour);
milisec = ++milisec;
if (milisec === 100) {
milisec = 0;
sec = ++sec;
}
if (sec == 60) {
min = ++min;
sec = 0;
}
if (min == 60) {
min = 0;
hour = ++hour;
}
document.getElementById("milisec").innerHTML = miliSecOut;
document.getElementById("sec").innerHTML = secOut;
document.getElementById("min").innerHTML = minOut;
document.getElementById("hour").innerHTML = hourOut;
}
/* Adds 0 when value is <10 */
function checkTime(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
function reset() {
/*Reset*/
milisec = 0;
sec = 0;
min = 0
hour = 0;
document.getElementById("milisec").innerHTML = "00";
document.getElementById("sec").innerHTML = "00";
document.getElementById("min").innerHTML = "00";
document.getElementById("hour").innerHTML = "00";
}
//adding an event listener
window.addEventListener('load', init, false);
https://codepen.io/rob-connolly/pen/xyJgwx
Any help would be appreciated.
its a pretty simple solution just call the stop function in the if condition of n == total
if (n == total) {
$('#results').html('<h3>Your score is: ' + score + ' out of ' + highest + '!</h3>
<button onclick="myScore()">Add Your Name To Scoreboard!</a>')
stop()
}
https://codepen.io/nony14/pen/VwYREgr
Try using clearInterval() to stop the timer.
https://codepen.io/thingevery/pen/dyPrgwz
I am making an artificial intelligent agent to play google chromes t-rex game and need help creating a loop for the game to continuously play at the moment to begin the game I have to actually press space.
document.getElementById("botStatus").addEventListener("change", function() {
if (this.checked === true) {
// Activate bot
var INTERVAL = 2;
window.tRexBot = setInterval(function() {
var tRex = Runner.instance_.tRex;
var obstacles = Runner.instance_.horizon.obstacles;
var lengthsize = 0;
var a = 0.1;
var b = 5;
var c = 35;
var d = 160;
var posWidth = 20;
// if (!tRex.jumping && (obstacles.length > 0) && (obstacles[0].xPos + obstacles[0].width) <= ((parseInt(Runner.instance_.currentSpeed - 0.1) - 5) * 34 + 160) && (obstacles[0].xPos + obstacles[0].width) > 20) {
if (!tRex.jumping && (obstacles.length > lengthsize) && (obstacles[0].xPos + obstacles[0].width) <= ((parseInt(Runner.instance_.currentSpeed - a) - b) * c + d) && (obstacles[0].xPos + obstacles[0].width) > posWidth) {
// console.log(obstacles[0].xPos + obstacles[0].width + " | " + ((parseInt(Runner.instance_.currentSpeed - 0.1) - 5) * 34 + 160));
tRex.startJump();
}
}, INTERVAL);
} else {
// Disable bot
clearInterval(tRexBot);
}
});
what I require is for once the Interval ends, I would like it to take the games current speed and distance of obstacles then either increase or decrease the variables I have set into a new interval, so that it will hopefully learn how to get further and further into the game as it picks up speed...
If this sort of makes sense?
A number of changes you could make to improve the code.
1) Extract the code for starting/stopping the bot to their own functions
var INTERVAL = 2;
function startBot(){
var bot = {}; //empty bot info
bot.tRex = Runner.instance_.tRex;
....
bot.posWidth = 20;
bot.interval = setInterval(function() {
if (!bot.tRex.jumping && (bot.obstacles.length > bot.lengthsize) /*...*/) {
tRex.startJump();
}
},INTERVAL);
return bot;
}
function stopBot(bot) {
clearInterval(bot.interval);
}
document.getElementById("botStatus").addEventListener("change", function() {
if (this.checked === true) {
window.bot = startBot();
}
else {
stopBot(window.bot);
}
}
2) pass the config parameters into the "startBot" function so you can more easily change it on the outside.
var config = { posWidth:20,a: 01,...};
startBot(config);
function startBot(config) {
var bot = config;
//....
}
I created a prototype for a horizontal scroller which will select a winner in an animated fashion. I am looking to improve this by programmatically highlighting the selected image under the indicator. I have figured out how to get it to scroll where I want, but I cannot figure out how to programmatically select the image after it's won.
Currently using:
HTML
CSS
jQuery
GSAP TimeLineMax
Working Example: http://codepen.io/ByteKnight13/pen/950a1a0d277fc0204d1827120bdcc090/
Current Code:
if (!String.prototype.format) {
String.prototype.format = function () {
var args = arguments;
return this.replace(/{(\d+)}/g, function (match, number) {
return typeof args[number] != 'undefined'
? args[number]
: match;
});
};
}
$(window).load(function () {
console.log('Window loaded!');
var $roulette = $('#roulette-images-list');
$roulette.html(generateRouletteImages(200));
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getPositionOfWinner(winner) {
var widthOfImg = $('#roulette-img0').width();
var minDistanceToEdgeAllowed = 4;
var desiredImg = $('#roulette-img' + winner.toString());
var minPos = desiredImg.position().left + minDistanceToEdgeAllowed;
var maxPos = desiredImg.position().left + widthOfImg - minDistanceToEdgeAllowed;
console.log('Position.Left: {0} | Offset().left: {1}'.format(desiredImg.position().left, desiredImg.offset().left));
return getRandomInt(minPos, maxPos);
}
function printLeftOfRouletteSpinner() {
var pos = $('#roulette-images-list').position().left;
if (pos % 100 == 0) console.log(pos);
}
function rouletteSpin(destImg) {
if (!destImg) destImg = 40;
var tl = new TimelineMax({onUpdate: printLeftOfRouletteSpinner}),
rouletteImages = $('#roulette-images-list'),
startLeft = rouletteImages.position().left;
tl//.to(rouletteImages, 0, {x: 5000})
.to(rouletteImages, 10, {x: getPositionOfWinner(destImg) * -1, ease:Power4.easeOut})
.to(rouletteImages, 0, {x: 0}, 11);
}
$('#spin').click(function () {
var winner = $('#winner-text').val();
//if (isNaN(winner) || winner > 49) alert('Enter 0 through 49');
rouletteSpin(winner);
});
function getRandomColor() {
return ((1 << 24) * Math.random() | 0).toString(16)
}
function generateRouletteImages(howMany) {
var imgTemplate = '<img src="{0}" class="{1}" id="roulette-img{2}">';
var imgClass = 'roulette-img';
var imgSrcTemplate = 'http://placehold.it/{0}/{1}?text={2}';
var completedRouletteImages = [];
for (var i = 0; i < howMany; i++) {
var color = getRandomColor();
var imgSrc = imgSrcTemplate.format('80', color, i);
var completedTemplate = imgTemplate.format(imgSrc, imgClass, i);
completedRouletteImages.push('<li>' + completedTemplate + '</li>');
}
return completedRouletteImages;
}
});
There is an onComplete parameter on TimelineMax. Combining that with the onCompleteParams parameter, you can pass the winner image reference to the onComplete callback.
new TimelineMax({
onComplete: timelineFinished,
onCompleteParams: [ destImg ]
})
function timelineFinished(destImg){
// this is where you highlight your winner
$('#roulette-img' + destImg).css({
border: '3px solid red'
});
}
Also, the roulette was resetting after to completed the spin, so I removed the last: .to(rouletteImages, 0, {x: 0}, 11)
Its a pretty rough selection, but you can clean it up with some CSS or whatever you are trying to achieve.
Working Example:
http://codepen.io/kingkode/pen/EyKwJW
I cant figuret how set cookie for my countdownt timeer, that if i refresh page it vill not disapear but vill counting.
i be glad if eny can help. i use jquery 2.1.4 and this java countdown script, but when i refresh page all my coundown timers are lost!
/**
* Created by op on 18.07.2015.
*/
function leadZero (n)
{
n = parseInt(n);
return (n < 10 ? '0' : '') + n;
}
function startTimer(timer_id) {
var timer = $(timer_id);
var time = timer.html();
var arr = time.split(":");
var h = arr[0];
h = h.split(" / ");
h = h[1];
var m = arr[1];
var s = arr[2];
if (s == 0)
{
if (m == 0)
{
if (h == 0)
{
timer.html('')
return;
}
h--;
m = 60;
}
m--;
s = 59;
}
else
{
s--;
}
timer.html(' / '+leadZero(h)+":"+leadZero(m)+":"+leadZero(s));
setTimeout(function(){startTimer(timer_id)}, 1000);
}
function timer (name, time)
{
var timer_name = name;
var timer = $(timer_name);
var time_left = time;
timer.html(' / '+ time);
startTimer(timer_name);
}
$(document).ready(function(){
$('.fid').click(function (e)
{
var timer_name = '.timer_'+$(this).data('fid');
var timer = $(timer_name);
if (timer.html() == '')
{
var time_left = timer.data('timer');
var hours = leadZero(Math.floor(time_left / 60));
var minutes = leadZero(time_left % 60);
var seconds = '00';
timer.html(' / '+hours+':'+minutes+':'+seconds);
startTimer(timer_name);
}
});
$.each($('.tab'), function () {
$(this).click(function () {
$.each($('.tab'), function() {
$(this).removeClass('active');
});
$(this).addClass('active');
$('.list').hide();
$('#content-'+$(this).attr('id')).show();
});
});
if (window.location.hash != '')
{
var tab = window.location.hash.split('-');
tab = tab[0];
$(tab).click();
}
console.log(window.location.hash)
});
It would help if you actually set a cookie.
Setting the cookie would go like:
document.cookie="timer=" + time;
And then call it at the beginning of your code
var time = getCookie("timer");
The getCookie() function is outlined in that link, as well as a base knowledge about them.