Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Змейка: совпадение координат (https://javascript.ru/forum/misc/37532-zmejjka-sovpadenie-koordinat.html)

Hekumok 23.04.2013 16:15

Змейка: совпадение координат
 
Делаю игру "змейка" на канвасе. Имеется такой код
function randomNumber(max) {
	return Math.floor(Math.random() * max) ;
} // генерит случайное число от 0 до (но не включая) max
function Position(x, y, side) {
	this.x = x ;
	this.y = y ;
	if(side !== undefined)
		this.movementToSide = side ;
} // конструктор позиций, x и y - координаты, movementToSide - сторона, в которую двигаемся
function Food() {
	this.position = new Position(randomNumber(canvas.width), randomNumber(canvas.height)) ;
} // конструктор еды, которую ест змейка; position - позиция, где эта еда находится, она может появиться в любом месте на поле
function Snake() {
	this.positionsOfTurns = [] ;
	this.head = new Position(canvas.center.x + canvas.cellSize, canvas.center.y, "right") ;
	this.tail = new Position(canvas.center.x - canvas.cellSize, canvas.center.y, "right") ;
}
/* positionOfTurns - массив позиций, где и в какую сторону поворачивает змейка
пример этого массива:
[{
	x: 250,
	y: 250,
	movementToSide: "top"
},
{
	x: 250,
	y: 200,
	movementToSide: "left"
}], т.е. первый поворот змейка делает вверх в позиции x:250, y:250; далее передвигается на 50пикселей вверх и следующий поворот она делает влево в позиции x:250, y:200
head - позиция головы змейки
tail - позиция хвоста змейки
*/
// прочий код

Так вот, когда создается позиция для еды, нужно проверить, не попала ли она на змейку (нельзя же, чтоб еда появилась на змейке). Следовательно, вопрос: как максимально эффективно (т.е. наиболее быстро) и можно ли вообще проверить, совпала позиция еды с какой-либо координатой, где ползет сейчас змейка, не имея при этом массива всех этих координат змейки (у меня же только хранятся позиции головы, хвоста и поворотов змейки). Я не вижу никакого варианта, кроме как с использованием массива всех координат

Aetae 23.04.2013 16:45

Ну не всех координат, можно взять imageData конкретного участка. Также возможно поможет isPointInPath().

Dim@ 23.04.2013 17:44

Hekumok,
хвост следует за головой по пути пройденному головой => по идее, должен быть массив поворотов которые должен сделать хвост на данный момент, он есть (если есть можно его скинуть)?

JsLoveR 23.04.2013 18:41

Может быть стоит проверять если координаты еды попадают в прямоугольник, где залито цветом змейки, а не цветом фона и возвращать true. Как Aetae предложил.

Hekumok 23.04.2013 21:53

Aetae, JsLoveR, спасибо, но получается, что мне нужно в цикле пробегать по всем координатам змейки и смотреть, совпадают ли они с позицией еды или нет, но я этого не хочу, почему и не использую массив всех координат змейки. А вообще у меня тут идейка появилась, завтра попробую.
Dim@, ээмм... Ну так snake.positionsOfTurns - это и есть массив поворотов змейки, т.е. поворотов, которые должен пройти хвост

Dim@ 23.04.2013 22:07

Hekumok,
просто по логике змейка состоит из линий можно по поворотам узнать линии и соответственно координаты змеи полностью, но как я понял для тебя это не катит

Можно попробовать такую вещь - нужна длина змеи и придётся создавать массив точек недоступных для помещения в них еды. Точка недоступна если кол-во шагов пройденных головой из этой точки меньше длины змейки

nerv_ 23.04.2013 22:26

Цитата:

Сообщение от Dim@
массив поворотов

:cray:

Цитата:

Сообщение от Hekumok
Я не вижу никакого варианта, кроме как с использованием массива всех координат

делай с массивом и не страдай ерундой )

Dim@ 23.04.2013 22:29

nerv_,
Цитата:

Сообщение от nerv_
Цитата:

Сообщение от Dim@
массив поворотов

:cray:

:cray: да я знаю

Aetae 23.04.2013 22:37

Я говорю о том, что раз змейка отрисовывается на canvas надо использовать методы canvas и тупо смотреть закрашена ли область.

Dim@ 23.04.2013 22:51

Aetae,
это логично, а если там змейка не в виде простых линий?

Aetae 23.04.2013 23:02

Цитата:

Сообщение от Dim@ (Сообщение 247815)
Aetae,
это логично, а если там змейка не в виде простых линий?

Пофигу. Главное чтоб фон отдельно рисовался.(что рекомендуют все уроки по canvas).
А дальше: в получившейся зоне есть непрозрачный пиксель? Значит false.)

JsLoveR 23.04.2013 23:13

Цитата:

Сообщение от Aetae
Я говорю о том, что раз змейка отрисовывается на canvas надо использовать методы canvas и тупо смотреть закрашена ли область.

и я о том, что-то вроде такого:
<script type="text/javascript">

var canvas = null;
var ctx = null;

function createRect(x, y, width, height, color) {
	ctx.fillStyle = color;
	ctx.fillRect(x, y, width, height);
}

function randomFood() {
	var randX = Math.floor(Math.random() * canvas.width / 30);
	var randY = Math.floor(Math.random() * canvas.height / 30);
	var block = ctx.getImageData(randX * 30, randY * 30, 1, 1);
	createRect(randX * 30, randY * 30, 30, 30, "#FF9900");
	if(block.data[0] == 153 && block.data[1] == 204 && block.data[2] == 0 && block.data[3] == 255) {
		alert("Попали на змейку!");
	}
}

window.onload = function(e){
	canvas = document.getElementById('map');
	ctx = canvas.getContext("2d");
	createRect(30, 30, 30, 30, "#99CC00");
	createRect(60, 30, 30, 30, "#99CC00");
	createRect(30, 60, 30, 30, "#99CC00");
	createRect(90, 30, 30, 30, "#99CC00");
	createRect(120, 30, 30, 30, "#99CC00");
	createRect(150, 30, 30, 30, "#99CC00");
	createRect(150, 60, 30, 30, "#99CC00");
	createRect(150, 90, 30, 30, "#99CC00");
	createRect(150, 120, 30, 30, "#99CC00");
}

</script>
<canvas id="map" width="200" height="200" style="border:1px solid #999999; float:left"></canvas>
<button onclick="randomFood()" style="float:left">Генерировать еду</button>

Но лучше использовать, наверное, стандартный подход ) Пробегать по массиву координат змейки, ведь там 1 цикл.

Dim@ 24.04.2013 09:16

Aetae,
ну да верно и сразу решает проблему установки еды на еду и другие объекты:)

Hekumok 24.04.2013 09:27

Цитата:

Сообщение от nerv_
делай с массивом и не страдай ерундой )

Цитата:

Сообщение от JsLoveR
Пробегать по массиву координат змейки, ведь там 1 цикл.

Ну а если длина змейки будет большой, массив всех её координат будет тоже большой. Пока пробежим по всему массиву, змейка будет стоять на месте, либо ползти, но на карте не будет еды (смотря как сделать), некрасиво получится(
Цитата:

Сообщение от Aetae
Я говорю о том, что раз змейка отрисовывается на canvas надо использовать методы canvas и тупо смотреть закрашена ли область.

То есть нужно брать методом getImageData массив пикселей (при чем это будет ведь квадратная область, и полученный массив будет больше обычного массива всех координат змейки), также пробегать по нему и смотреть попал/не попал на змейку. Но при большой длине змейки, массив будет немаленьким, и пробегать по нему будет довольно долго.
Цитата:

Сообщение от Dim@
Hekumok,
просто по логике змейка состоит из линий можно по поворотам узнать линии и соответственно координаты змеи полностью, но как я понял для тебя это не катит

:yes:
Цитата:

Сообщение от Dim@
массив точек недоступных для помещения в них еды.

Так это ж и получится массив всех координат змейки :blink:

Hekumok 24.04.2013 09:37

Цитата:

Сообщение от Aetae
Также возможно поможет isPointInPath()

Тьфу ты, блин, точно) благодарю))

Aetae 24.04.2013 13:51

Цитата:

Сообщение от Hekumok (Сообщение 247842)
То есть нужно брать методом getImageData массив пикселей (при чем это будет ведь квадратная область, и полученный массив будет больше обычного массива всех координат змейки), также пробегать по нему и смотреть попал/не попал на змейку. Но при большой длине змейки, массив будет немаленьким, и пробегать по нему будет довольно долго.

То есть можно брать методом getImageData массив пикселей предполагаемой области появления еды, а не всей змейки. И зависит он, соответственно, только от размеров еды. Но если isPointInPath подходит, то, естесно, лучше юзать его.

Hekumok 24.04.2013 19:38

Aetae, да-да, чё-т я конкретно тупанул :)


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