Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   Таймер для игры (https://javascript.ru/forum/project/37871-tajjmer-dlya-igry.html)

Daiver 12.05.2013 03:56

Таймер для игры
 
Делаю игру судоку на javascript. Нужно исправить/переделать таймер, чтобы он смог:
а) Ставиться/сниматься с паузы без глюков. В нынешнем состоянии если несколько раз часто пощелкать на кнопку паузы запускается парралельно несколько setTimeout()-ов параллельно и таймер скачет не соответствуя реальности.
б) Останавливаться окончательно и безповоротно из отдельной функции. Возможно сама дойду до этого пункта при полном решении всех проблем из остальных пунктов.
в) Имея не законченную игру и запущенный таймер при запуске новой игры чтобы не было глюка из пункта (а).

На данный момент таймер реализован через рекурсивную функцию с использованием setTimeout(). О наличии метода setInterval() знаю, но как-то не совсем мне удалось понять как с ним работать. Ссылка на подробное описание, с примерами, работы с ним приветствуются.
Готового решения :stop: не ищу и даже отвергаю.
Нужны подсказки в каком направлении мыслить + минимальные опорные точки для направления. Хочу все написать сама.:write:
Заранее всем благодарна.
P.S. Сильно не бейте за кривой код. Я самоучка. Все писала сама. Сейчас перерабатываю тонну HTML в циклы с объектно ориентированной генерацией через DOM.

edison 12.05.2013 07:04

var timerID=null; // global
timerID=setTimeout(.....);
clearTimeout(timerID);
timerID=null;
Цитата:

не совсем мне удалось понять как с ним работать
ммм так-же как и с сеттаймаут , один в один)) только будет вызов не 1 раз а много раз пока не сделать clearInterval(intervalID) где intervalID это переменная куда положен сет интервал )
В общем таймер(-ы) в переменную(-ые) и все 3 пункта решатся ) б) - clearTimeout clearInterval ( правда с вызовом функции из самой себя, можно проскочить момент с clearTimeout , так-что лучше переделывать под clearInterval )

Aetae 12.05.2013 07:05

Таймер так и делается, там всё просто:
var timeout;
function timer(){
    //действия
    timeout = setTimeout(timer, 1000);
}

//запуск
timer();

//остановка
clearTimeout(timeout);


С clearTimeout'ом ничего проскочить нельзя, т.к. если clearTimeout произведён то никаких вызовов точно не будет. Главное правило чтоб не накосячить - одновременно на одну задачу должен существовать только один таймер, следующий не должен вызываться пока предыдущий не закончится.
А вот как раз таки setInterval использовать не рекомендуется(только в особых случаях), т.к. он имеет свойство в случае лагов накапливаться, и может случиться так, что он уже очищен, а функция продолжает вызываться.)

Daiver 12.05.2013 14:27

Цитата:

Сообщение от edison (Сообщение 249964)
В общем таймер(-ы) в переменную(-ые) и все 3 пункта решатся

Замечание понято. Буду исправляться.

Из всего сказанного возникает вопрос - а можно ли как-то исправить следующее: когда ставится пауза, то обнуляется таймер, а когда игра снимается с паузы, то таймер опять ждет 1000 мс чтобы переключить на табло еще одну секунду. Получается накапливание времени зазоров. Хотелось бы, к примеру - если табло было переключено пол секунды назад, то чтобы после паузы таймер отсчитывал уже пол секунды, а не целую. Так вот как можно выцепить сколько времени прошло с запуска таймера до обрывания, чтобы потом таймер можно было поставить не на 1000 мс, а на (1000-(столько, сколько прошло перед обрывом отсчета))мс.?

Aetae 12.05.2013 15:16

Date.now() вам в помощь.
Однако не вижу особого смысла именно в секундной задержке. Обычно с этим не заморачиваются и выводят время с интервалом в 100мс. Никаких задержек тогда не заметно.
Ну и плюс обратите внимание на мой пример: в нём сначала выполняется код, а потом уже запускается таймер следующего вызова. Т.е. при нажатии на кнопку обновление происходит сразу.

edison 12.05.2013 20:36

Aetae
Про проскочить, имелось в виду не существование 2х таймеров, а когда идет вызов таймера на функцию из самой себя, то может наступить тот момент, когда мы во время выполнения этой функции жмем стоп, но функция вешает опять таймер, т.к. выполняется все асинхронно.

Понятно, что в вашем примере вероятность попадания clearTimeout(timeout);
в момент выполнения функции timer стремится к нулю, но чем больше функция, тем выше шанс. Вообще можно вводить дополнительную переменную для проверки в обоих случаях.

9xakep 12.05.2013 20:59

1) Ну я хз зачем вам интервал в судоку

function Game() {
  var interval, self = this;
    this.count = 0;
    this.start = function () {
        interval = setInterval(function () {
            self.count++;
        }, 1000)
    }
    this.pause = function () {
        clearInterval(interval);
    }
}

var snake = new Game();
     snake.start();
     setTimeout(function () { alert(snake.count); snake.pause(); }, 3000) // Берем результаты через 3 секунды

     
     setTimeout(function () { alert(snake.count+' Результат тот же, значит пауза сработала'); snake.start()}, 5000) // Проверяем, что пауза сработала
 
    
    setTimeout(function () { alert(snake.count+' Результат изменился, значит работа продолжилась');snake.pause(); }, 7000) // Проверяем, что мы продолжили работу

Daiver 12.05.2013 21:11

В коде по выше приведенной ссылке вероятно сложно найти нужную часть кода. Привожу пример отдельно взятого табло с таймером.
После вставления таймера в переменную как предложил edison проблема не решилась. Попробуйте часто пощелкать по кнопке пауза при запущеном таймере и вы увидите удивительный глюк. За одну секунду реального времени перескакивает сразу несколько секунд на табло. Что не так?

9xakep 12.05.2013 21:18

<div id='timer'></div><br />
<script>
function Game() {
  var interval, self = this, isStart = false;
    this.count = 0;
    this.start = function () {
	
		if (!isStart) { 
           isStart = true;
			interval = setInterval(function () {
			
				/* Тут вы пишете код, который будет выполнятся */
				
				self.count++;
				self.log();
				
			}, 1000)
		}
    }
    this.pause = function () {
		 
		 isStart = false;
		/* Тут просто останавливаете выполнение кода */
		
        clearInterval(interval);
    }
	this.stop = function () {
		
		/* А тут останавливаете, плюс восстанавливаете изначальные значения (count = 0) */
	
		self.pause();
		self.count = 0;
		self.log()
	}
	this.log = function () {
	
		// Этот метод просто обновляет div
		timer.innerHTML = self.count;
	}
}

var snake = new Game();
   

    
</script>
<input type='button' value='start' onclick='snake.start()' /><br />
<input type='button' value='pause' onclick='snake.pause()' /><br />
<input type='button' value='stop' onclick='snake.stop()'  />

Daiver 12.05.2013 22:01

Спасибо, 9xakep, принцип поняла, сейчас попробую переделать. Но у меня все на много проще - мне надо просто реализовать обновление табло через каждую секунду. Просто чтобы пользователь видел сколько времени прошло с момента начала игры, с возможностью поставить на паузу.


Часовой пояс GMT +3, время: 02:01.