Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 20.10.2017, 23:31
Новичок на форуме
Отправить личное сообщение для igdev Посмотреть профиль Найти все сообщения от igdev
 
Регистрация: 20.10.2017
Сообщений: 7

Обработка событий
Пишу небольшую игрушку. Суть ее заключается в том, что муха "летает" по экрану пользователя (движение задается кривыми Безье),
а пользователь должен ее "прибить" мышкой при этом не давая мухе "сесть", т.е. остановить свое движение.
Если муха села, игра завершается.

Собственно, ближе к делу. Трудность возникает в том, как обработать такое событие.
Текущее координаты мухи на экране вычисляются в цыкле:
for(var i = 0; i <= shift && flag; i += step)
{
	secondFlag = true;
	var coord = formula.getPointOnCurve(i, points);
		
	context.clearRect(0, 0, 1000, 1000);		
	context.drawImage(picture, coord[0], coord[1]);
			
	canvas.addEventListener('mousemove', function(evt) 
	{
		var mousePos = getMousePos(evt);
					
						
		if (Math.abs(mousePos.x - coord[0]) <= 7 && Math.abs(mousePos.y - coord[1]) <= 7)
		{
			cancelAnimationFrame(myReq);
			context.clearRect(0, 0, 1000, 1000);
			context.drawImage(badPicture, coord[0], coord[1]);
			pushScore(score++);
			flag = false;
		}
					
	});
}


Т.е. здесь вычисляются текущее координаты мухи и координаты мышки, если они совпадают, то муху "убиваем".
Однако такой подход очень плохой, т.к. при нескольких вызовов функции полета мухи, игра начинает лагать.

Прошу помощи, совета, как можно оптимизировать данное решение, чтобы оно соответсвовало начальным требования, которые я описал выше.

Вот полностью код:
window.onload = function() {
	
	window.requestAnimationFrame = window.requestAnimationFrame
                               || window.mozRequestAnimationFrame
                               || window.webkitRequestAnimationFrame
                               || window.msRequestAnimationFrame
                               || function(f){return setTimeout(f, 1000/60)}

	window.cancelAnimationFrame = window.cancelAnimationFrame
                              || window.mozCancelAnimationFrame
                              || function(requestID){clearTimeout(requestID)} //fall back
	
	var canvas = document.getElementById('bezier');
	var context = canvas.getContext('2d');
	
	
	var formula = {};


		
	formula.getPointOnLine = function(shift,points){
		return [
			(points[1][0] - points[0][0]) * (shift / 100) + points[0][0],
			(points[1][1] - points[0][1]) * (shift / 100) + points[0][1]
		];
	};

	formula.getPointOnCurve = function(shift,points){
		if(points.length == 2){
			return this.getPointOnLine(shift,points);
		}
		var pointsPP = [];
		for(var i = 1;i < points.length;i++){
			pointsPP.push(this.getPointOnLine(shift,[
				points[i - 1],
				points[i]
			]));
		}
		return this.getPointOnCurve(shift,pointsPP);
	};

		

	function getCoordinates()
	{
		var max = 650;
		var min = -150;
			
		return Math.floor(Math.random() * (max - min + 1) + min);
	}
	
	
	var score = 0;
	var life = 3;
	var myReq;
	var flag = true;
	var secondFlag = false;
	
	var started = false;
	var running = false;
	
	
	
	function pushScore(scores)
	{
		var value = document.getElementById("sixthTd");
        value.innerHTML = "Score: " + scores;
	}
	
	function pushLife(lifes)
	{
		var value = document.getElementById("fourthTd");
		value.innerHTML = "Life: " + lifes;
	}

	
	
	
	var picture = new Image();
	picture.src = "../images/Mosca_ON.gif";
		
	var badPicture = new Image();
	badPicture.src = "../images/Mosca_OFF.gif";
	
	
	
	var points = [];
		
		function generateCoords()
		{
			var valueXPoint = Math.floor(Math.random() * (700 - 100 + 1) + 100);
			var valueYPoint = Math.floor(Math.random() * (700 - 100 + 1) + 100);
			points = [
				[valueXPoint, valueYPoint],
				[getCoordinates(), getCoordinates()],
				[getCoordinates(), getCoordinates()],
				[getCoordinates(), getCoordinates()],
				[getCoordinates(), getCoordinates()],
				[getCoordinates(), getCoordinates()],
				[getCoordinates(), getCoordinates()],
				[getCoordinates(), getCoordinates()],
				[getCoordinates(), getCoordinates()],
				[getCoordinates(), getCoordinates()],
				[getCoordinates(), getCoordinates()],
				[getCoordinates(), getCoordinates()],
				[getCoordinates(), getCoordinates()],
				[getCoordinates(), getCoordinates()],
				[valueXPoint, valueYPoint]
		];
		}
		
		var shift = 0;
		var step = 1;
		
	function getMousePos(evt)
	{
		//set and store..
		priorEvt = evt = evt || priorEvt;
		//get the bounding rectangle
		var rect = canvas.getBoundingClientRect();
		//lastly, return the x and y coordinates
		if (evt)
			return {
				x: evt.clientX - rect.left,
				y: evt.clientY - rect.top
			};
		return {
			x: 0,
			y: 0
		};
	}
	
	function stop()
	{
		running = false;
		started = false;
		cancelAnimationFrame(myReq);
	}
	
	function mainLoop(timestamp) {
		if (timestamp >= 2500.0)
		{
			
			stop();
			return;
		}
		
		myReq = requestAnimationFrame(mainLoop);
	}
	
	function start()
	{
		if(!started)
		{
			started = true;
			generateCoords();
			myReq = requestAnimationFrame(function (timestamp){
				draw(1);
				running = true;
				myReq = requestAnimationFrame(mainLoop);
			});
		}
	}
	
	function newGame()
	{
		stop();
		secondFlag = false;
		flag = true;
		start();
	}
	
	function draw(timestamp)
	{
		
		context.beginPath();
			
		
		
		if(shift > 100){
			shift = 100;
		}
			
				

		for(var i = 0; i <= shift && flag; i += step)
		{
			secondFlag = true;
			var coord = formula.getPointOnCurve(i, points);
		
			context.clearRect(0, 0, 1000, 1000);		
			context.drawImage(picture, coord[0], coord[1]);
			
			canvas.addEventListener('mousemove', function(evt) 
			{
				var mousePos = getMousePos(evt);
					
						
				if (Math.abs(mousePos.x - coord[0]) <= 7 && Math.abs(mousePos.y - coord[1]) <= 7)
				{
					cancelAnimationFrame(myReq);
					context.clearRect(0, 0, 1000, 1000);
					context.drawImage(badPicture, coord[0], coord[1]);
					pushScore(score++);
					flag = false;
				}
					
				});
		}
		
		
		if (flag == false)
			newGame();
		
			
		context.stroke();	
		context.closePath();

		if(shift <= 100){
			shift += step;
		}
		
		requestAnimationFrame(draw);
		console.log(timestamp);
	
	}
	
	start();
	pushScore(score);
	pushLife(life);
}


<canvas id = "bezier" width = "700" height = "1000"></canvas>
Ответить с цитированием
  #2 (permalink)  
Старый 21.10.2017, 21:17
Новичок на форуме
Отправить личное сообщение для igdev Посмотреть профиль Найти все сообщения от igdev
 
Регистрация: 20.10.2017
Сообщений: 7

Rise,
Цитата:
надо на классах делать
Что именно надо делать? Полностью весь код переписать?

Нельзя просто внести минимальные изменения в мой код так, чтобы просто работало то, что я хочу, т.е. муха отлавливалась, убивалась, появлялась новая, опять убивалась пользователем и так до тех пор, пока она не сядет и пользователю выведет сообщение, что игра закончилась? При этом, чтобы не было подглагиваний.
Ответить с цитированием
  #3 (permalink)  
Старый 21.10.2017, 21:21
Новичок на форуме
Отправить личное сообщение для igdev Посмотреть профиль Найти все сообщения от igdev
 
Регистрация: 20.10.2017
Сообщений: 7

Я просто подозреваю, что в своем цикле я порождаю много ивентов и оно начинает лагать. Закрыть ивент не получается. Я уже просто не знаю, куда копать.

Может есть возможность как-то вынести этот ивент вне цикла при этом сохраняя возможность отлавливать расположение этой мухи?
Ответить с цитированием
  #4 (permalink)  
Старый 21.10.2017, 21:24
Новичок на форуме
Отправить личное сообщение для igdev Посмотреть профиль Найти все сообщения от igdev
 
Регистрация: 20.10.2017
Сообщений: 7

И еще. Хочу оточнить: когда картинка мухи движется по канвасу, а я пытаюсь отловить событием движения мыши ее, то канвас в этом случаи считается все мое пространство 1000х1000 или только картинки мухи?
Ответить с цитированием
  #5 (permalink)  
Старый 22.10.2017, 01:26
Новичок на форуме
Отправить личное сообщение для igdev Посмотреть профиль Найти все сообщения от igdev
 
Регистрация: 20.10.2017
Сообщений: 7

Rise,
Ну, допустим, проще переписать. Как тогда мне отлавливать муху на экране?
Ответить с цитированием
  #6 (permalink)  
Старый 22.10.2017, 01:29
Новичок на форуме
Отправить личное сообщение для igdev Посмотреть профиль Найти все сообщения от igdev
 
Регистрация: 20.10.2017
Сообщений: 7

И с чего лучше начать при переписывании? Можете привести начальный пример для моей реализации? А то js для меня не особо знаком. На С++ с классами все намного проще, чем здесь.
Ответить с цитированием
  #7 (permalink)  
Старый 22.10.2017, 12:10
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,012

igdev,
Прежде всего надо разобраться - какого хрена в каждом вызове draw в каждой итерации цикла вешается новый обработчик mousemove??? Этот обработчик должен быть отдельной функцией, которая вешается при старте и снимается при финише.
Ответить с цитированием
  #8 (permalink)  
Старый 22.10.2017, 12:42
Новичок на форуме
Отправить личное сообщение для igdev Посмотреть профиль Найти все сообщения от igdev
 
Регистрация: 20.10.2017
Сообщений: 7

Alexandroppolus,
Ок. Но как тогда мне отлавливать положение мухи, если я вынесу этот обработчик в отдельную функцию? Я этого не могу понять.
Ответить с цитированием
  #9 (permalink)  
Старый 22.10.2017, 13:27
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,109

igdev,
Подборка уроков для начинающего разработчика игр на JavaScript
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Canvas обработка событий ДанилаDeep Events/DOM/Window 6 28.08.2014 16:55
ie и другие браузеры - обработка событий torsar Javascript под браузер 1 24.05.2014 20:29
Обработка событий в нужной очередности. lamer Общие вопросы Javascript 15 29.04.2013 18:40
JQuery отложенная обработка событий hover DemonWather jQuery 2 09.03.2011 09:01
svg. обработка событий amigo* Элементы интерфейса 0 23.06.2010 22:31