Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Чтобы элемент передвигался рандомно (https://javascript.ru/forum/misc/68767-chtoby-ehlement-peredvigalsya-randomno.html)

yaparoff 07.05.2017 13:33

Чтобы элемент передвигался рандомно
 
По полю передвигается квадратик (вверх-вниз, влево-вправо)
http://plnkr.co/edit/wx0ygfaGTWHj9dSz07G0?p=preview

1) Как сделать так чтобы он передвигался рандомно?
Т.е. либо влево на 20рх, либо вправо на 20рх, либо вверх, либо вниз.
Естественно нужно чтобы он это это делал в пределах контейнера,
и передвигался постоянно
(знаю что может помочь Math.random(), но как именно его прописать?)

2) На поле есть неподвижные квадратики - это камни. На них элемент не может заходить - он должен их обходить

3) Как создать второй такой же элемент, чтобы он рождался в рандомном месте(кроме камня и другого элемента), также ходил, но при встрече двух элементов, они не могли вставать друг на друга, а обходили друг друга

рони 07.05.2017 14:46

yaparoff,
массив надо делать, чтобы знать где можно ходить, а где какой-то обьект.много кода ... коллизии обьектов вычислять.

yaparoff 07.05.2017 15:39

Цитата:

Сообщение от рони (Сообщение 451848)
yaparoff,
массив надо делать

В сети нашел что-то и свое подставил.
Т.е. есть массив массивов list где есть 8 вариантов, куда сделать шаг,
потом это перебирается Math.random() и выбирается одно направление.

и как результат этого вставить в мой код?
var randomDirection = {
		list: [
			[0, -20],
			[20, -20],
			[20, 0],
			[20, 20],
			[0, 20],
			[-20, 20],
			[-20, 0],
			[-20, -20]
		],
		already: [],
		random: function () {
			return this.directions[Math.floor(Math.random() * this.list.length)];
		},
		get: function () {
			var direction = this.random();

			if (this.already.length >= this.list.length) {
				this.already = [];
				return direction;
			}
			if (this.already.indexOf(direction) !== -1) {
				return this.get();
			} else {
				this.already.push(direction);
				return direction;
			}
		}
	};
	
	alert(randomDirection.get());

yaparoff 07.05.2017 16:51

Цитата:

Сообщение от рони (Сообщение 451848)
чтобы знать где можно ходить, а где какой-то обьект

Вот. Так вычисляем координаты камней:
var stones = document.querySelectorAll('.stone');
	var stonesCoords = [];
	for (var i = 0; i < stones.length; i++) {
		stonesCoords.push(getCoords(stones[i]));
	}
	function getCoords(element) {
		var box = element.getBoundingClientRect();

		return {
			top: box.top + pageYOffset,
			left: box.left + pageXOffset,
			right: box.right + pageXOffset,
			bottom: box.bottom + pageYOffset
		};
	}

В код добавил http://plnkr.co/edit/wx0ygfaGTWHj9dSz07G0?p=preview

Хотелось бы добавить, что элемент должен видеть только в пределах одного хода - дальше он не видит.

yaparoff 07.05.2017 17:04

Как теперь это все воедино соединить?

рони 07.05.2017 17:33

yaparoff,
может ну его нафиг?

yaparoff 07.05.2017 17:40

Цитата:

Сообщение от рони (Сообщение 451857)
может ну его нафиг?

Не получиться. Нужно сделать обязательно. Эта задача - не моя прихоть

yaparoff 07.05.2017 17:57

Rise,
Да. Из книги выразительный JavaScript
Автор рассказывает как делать, НО нужна своя реализация, нельзя копировать код.
Автор так объясняет, что мне не остается просто брать и копировать оттуда код. Но так нельзя. Мне код автора во многих местах не понятен.
Поэтому реализовываю по своему, чтобы каждая строчка кода мне понятна была.

В итоге примерно вот что должно получиться http://eloquentjavascript.net/code/#7.2

но объектов может быть меньше чем там

Diphenyl Oxalate 07.05.2017 18:44

yaparoff, может чем поможет
Броуновское движение на js

yaparoff 07.05.2017 20:37

Цитата:

Сообщение от Rise (Сообщение 451868)
но там достаточно доходчиво и интересно написано

Как сделать собственную реализацию этого куска кода:
(о нем здесь написано)
Копировать нельзя
function Vector(x, y) {
  this.x = x;
  this.y = y;
}
Vector.prototype.plus = function(other) {
  return new Vector(this.x + other.x, this.y + other.y);
};

var grid = ["top left",    "top middle",    "top right",
            "bottom left", "bottom middle", "bottom right"];

function Grid(width, height) {
  this.space = new Array(width * height);
  this.width = width;
  this.height = height;
}
Grid.prototype.isInside = function(vector) {
  return vector.x >= 0 && vector.x < this.width &&
         vector.y >= 0 && vector.y < this.height;
};
Grid.prototype.get = function(vector) {
  return this.space[vector.x + this.width * vector.y];
};
Grid.prototype.set = function(vector, value) {
  this.space[vector.x + this.width * vector.y] = value;
};

var grid = new Grid(5, 5);
grid.set(new Vector(1, 1), "X");
console.log(grid.get(new Vector(1, 1)));

yaparoff 07.05.2017 20:41

И вот это как самому реализовать, не копируя?
var directions = {
  "n":  new Vector( 0, -1),
  "ne": new Vector( 1, -1),
  "e":  new Vector( 1,  0),
  "se": new Vector( 1,  1),
  "s":  new Vector( 0,  1),
  "sw": new Vector(-1,  1),
  "w":  new Vector(-1,  0),
  "nw": new Vector(-1, -1)
};

/* Вот простое тупое существо, которое просто идёт, пока не врезается в препятствие, а затем отскакивает в случайном направлении. */

function randomElement(array) {
  return array[Math.floor(Math.random() * array.length)];
}
function BouncingCritter() {
  this.direction = randomElement(Object.keys(directions));
};
BouncingCritter.prototype.act = function(view) {
  if (view.look(this.direction) != " ")
    this.direction = view.find(" ") || "s";
  return {type: "move", direction: this.direction};
};

yaparoff 08.05.2017 06:00

Цитата:

Сообщение от Rise (Сообщение 451876)
Лицензия MIT не запрещает копирование.

Уже бы давно скопировал.
У меня задача - сделать собственную реализацию. Копировать запрещено

В поисках этого решения и пришел сюда.

Просто забить и сказать "да ну его нафиг" - не получиться. Мне обязательно нужно это сделать

yaparoff 08.05.2017 07:15

(удалено)

Dilettante_Pro 08.05.2017 16:14

черновой набросок
<style>
.container {
   position:absolute;
   top:30px;
   left:20px;
   width:400px;
   height:400px;
   border:1px solid gray;
}
.animal {
   width:20px;
   height:20px;
   transition: 0.3s;
   border-radius: 10px;
   background-color: red;
}
.stone {
   width:20px;
   height:20px;
   border-radius: 10px;
   background-color: black;
}
</style>
Количество животных: <input type='number' id ='aCount' value='2'>
  Количество камней: <input type='number' id ='sCount' value='10'>
<input type='button' id='mainBut' value='Пуск'>
<div class='container'></div>
<script>
var field = document.querySelector('.container'),
     fieldTop = +field.style.top,
     fieldLeft = +field.style.left,
     unit,
     units = [],
     animals = [],
     stoneCount = 10,
     animalCount = 2,
     stopFlag = false;

function createUnit(unitType) {
    var unitTop, unitLeft, noFree = true, unitPos = {};
    do {
        unitTop = (Math.round(Math.random() * 19 ) * 20 - fieldTop) + 'px';
        unitLeft = (Math.round(Math.random() * 19 ) * 20 - fieldLeft) + 'px';
        noFree = false;
        for(var i = 0; i < units.length; i++){
           if(units[i].top == unitTop && units[i].left == unitLeft) noFree = true;
        } 
    } while (noFree);
    unit = document.createElement('div');
    unit.classList.add(unitType);
    unit.style.position = 'absolute';
    unit.style.top = unitTop;
    unit.style.left = unitLeft; 
    field.appendChild(unit); 
    unitPos.top = unitTop;
    unitPos.left = unitLeft;
    units.push(unitPos);
    if(unitType == 'animal') {
       animals.push(unitPos);
       unit.id = "a" + i;
       unit.innerText = i;
    }
}
function moveAnimals() {
   var stepTop, stepLeft, unitTop, unitLeft, noFree, unitPos = {};
   for(var i = 0; i<animals.length;i++) {
      noFree = true;
      do {
         stepTop = Math.round(Math.random() * 2 - 1) * 20;
         stepLeft = Math.round(Math.random() * 2 - 1) * 20;

         unitTop = +animals[i].top.replace(/\D/g,"") + stepTop;
         unitLeft = +animals[i].left.replace(/\D/g,"") + stepLeft;
         if(unitTop < 0 || unitLeft < 0 || unitTop >  380 || unitLeft > 380) { noFree = true; }
         else {
            unitTop = unitTop + "px";
            unitLeft = unitLeft + "px";  
            noFree = false;
            for(var j = 0; j< units.length; j++){
               if(units[j].top == unitTop && units[j].left == unitLeft) noFree = true;
           } 
        }
     } while (noFree);      
     units[i].top = unitTop;
     units[i].left = unitLeft;
     animals[i].top = unitTop;
     animals[i].left = unitLeft;
     var elem = document.querySelector('#a' + i);
     elem.style.top = unitTop;
     elem.style.left = unitLeft;
   }
}

function start() {
    if(stopFlag) return;
    moveAnimals();
    setTimeout(start, 500); 
};

function startLife() {
   for(var i = 0; i < animalCount;i++){
       createUnit('animal');
   }
   for(var i = 0; i < stoneCount;i++){
       createUnit('stone');
   }

    start();
}
document.querySelector('#mainBut').onclick = function() {
    if(this.value == 'Пуск') {
        stopFlag = false;
        animalCount = +document.querySelector('#aCount').value;
        stoneCount = +document.querySelector('#sCount').value;
        this.value = 'Стоп';
        startLife();
    }
    else {
        stopFlag = true;
        this.value = 'Пуск';
        field.innerHTML = "";
        units = [];
        animals = [];
    }
}
</script>

yaparoff 09.05.2017 09:14

Dilettante_Pro, огромное спасибо!
В целом код понятен, правда хотелось бы некоторые моменты уточнить:

1) Для чего стоит "+" у +field.style.top. Он преобразует в число, но ведь там и так будет число. Или нет?
А понял, туда поступает допустим 20рх и он обрезает "рх" и оставляет только "20" - я правильно понял?

2) Что означает noFree = true ? То что ячейка занята?
3) На 36 строке для чего мы Math.random() умножаем именно на 19 ? Затем всё это умножаем на 20 и после вычитаем fieldTop?
Почему именно так?

4) Что означает эта запись (строка 40):
if(units[i].top == unitTop && units[i].left == unitLeft) noFree = true;

5) Для чего в 60-ой строке стоит noFree = true; ?
6) Для чего нужен второй цикл на 71 строке ?
7) Строки 77 и 79: для чего мы задаем одно и то же значение для units[i].left и animals[i].left ?
8) Как существо понимает, что на камень нельзя заходить?

Diphenyl Oxalate 09.05.2017 09:38

76     units[i],top = unitTop;


78     animals[i],top = unitTop;


Вот, а в strict mode бы не пустило.

yaparoff 09.05.2017 09:50

Цитата:

Сообщение от Diphenyl Oxalate (Сообщение 451952)
Вот, а в strict mode бы не пустило.

Ничего страшного, это я заметил и исправил у себя

Dilettante_Pro 09.05.2017 10:16

yaparoff,
Цитата:

Сообщение от yaparoff
2) Что означает noFree = true ? То что ячейка занята?

Ну ведь понятно же - именно это.
Цитата:

Сообщение от yaparoff
3) На 36 строке для чего мы Math.random() умножаем именно на 19 ? Затем всё это умножаем на 20 и после вычитаем fieldTop?
Почему именно так?

сначала получаем случайное число от 0 до 19 - т.к у нас 20 ячеек по вертикали и по горизонтали, а потом умножаем на 20 - размер ячейки, корректируем полученные координаты относительно положения контейнера
Цитата:

Сообщение от yaparoff
4) Что означает эта запись (строка 40):
if(units[i].top == unitTop && units[i].left == unitLeft) noFree = true;

если две новых координаты unitTop и unitLeft есть у каких-то units - ячейка занята
Цитата:

Сообщение от yaparoff
5) Для чего в 60-ой строке стоит noFree = true; ?

Убрать значение предыдущей итерации. Чтобы цикл do-while заработал.
Цитата:

Сообщение от yaparoff
6) Для чего нужен второй цикл на 71 строке ?

Первый цикл - новые координаты для животных, второй - проверка занятости ячеек
Цитата:

Сообщение от yaparoff
7) Строки 77 и 79: для чего мы задаем одно и то же значение для units[i].left и animals[i].left ?

Запоминаем новые позиции животных.
units - все элементы - камни и животные, для проверки занятости ячеек
animals - животные, для управления
Цитата:

Сообщение от yaparoff
8) Как существо понимает, что на камень нельзя заходить?

Смотри ответ на вопрос 4
Цитата:

Сообщение от Diphenyl Oxalate
76     units[i],top = unitTop;


78     animals[i],top = unitTop;


Вот, а в strict mode бы не пустило.

Спасибо. Просто я писал наскоро, на смартфоне (Очень неудобно!). Специально написал, что черновик. Поправил. Убрались некоторые глюки

PS: имейте в виду, что строки скрипта немного сдвинулись в связи с расширением функциональности в последней редакции

yaparoff 09.05.2017 10:44

Цитата:

Сообщение от Dilettante_Pro (Сообщение 451954)
Спасибо.

Тебе спасибо! )))

рони 09.05.2017 12:42

игра кролики и клубника (передвижение обьекта в массиве рандомно)
 
yaparoff,
запусти кроликов в огород (клик по полю)
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  *{
    padding: 0;
    margin: 0;
  }

  .cell {
    text-align: center;
     float: left;
     height: 23px;
     width: 23px;
     border: #0000CD 1px solid;
     background-color: #FFEBCD;
     font-size: 12px;
     -webkit-transition: all .5s ease-in-out;
     -moz-transition: all .5s ease-in-out;
     -o-transition: all .5s ease-in-out;
     transition: all .5s ease-in-out;
  }
  #matrix{
    display: inline-block;
    margin: 50px auto;
  }
  .red{
    border-radius: 4px;
    background-image: url(http://www.smayly.ru/gallery/big/vkBunny/12.png);
    background-repeat: no-repeat;
    background-size: cover;
  }
 .yellow{
     background: #FFFF00;
   }
  .green{
    background-image: url(http://moyhutor.net/images/klubnika2.png);
    background-repeat: no-repeat;
    background-size: cover;
  }
  .blue{
    background: #0000FF
  }
  </style>

  <script>
window.addEventListener("DOMContentLoaded", function() {
    var matrix = document.getElementById("matrix"),
        l = (Math.random() * 15 | 0) + 10;
    t = (Math.random() * 10 | 0) + 10, n = l * t;

    function createMatrix() {
        var w;
        for (var i = 0; i < n; i++) {
            var div = document.createElement("div");
            div.className = "cell";
            Math.random() < .07 && div.classList.add("green");
            div.dataset.index = i;
            matrix.appendChild(div);
            if (i == l - 1) w = matrix.offsetWidth + 1
        }
        matrix.style.width = w + "px";
        matrix.style.display = "block"
    }

    function chec(indx, size) {
        var s = [],
            x = indx % l,
            y = indx / l |
            0;
        size = size || 1;
        for (var i = y - size; i <= y + size; i++)
            for (var k = x - size; k <= x + size; k++) {
                var num = k + i * l,
                    max = Math.max(Math.abs(i - y), Math.abs(k - x));
                i > -1 && i < t && k > -1 && k < l && num < i * l + l && num != indx? s.push(num): s.push(null)
            }
        return {
            s: s
        }
    }
    createMatrix();
    var divs = [].slice.call(document.querySelectorAll(".cell"), 0);
    matrix.addEventListener("click", function(event) {
        var el = event.target,
            cls = el.classList;
        if (cls && cls.contains("cell") && !cls.contains("green") && !cls.contains("red")) {
            var index = el.dataset.index;
            move(index, Math.random() * 8 | 0)
        }
    });

    function move(index, num) {
        var arr = chec(index, 1);
            m = [];
        var k = arr.s.filter(function(indx,i) {
            return indx !== null && !divs[indx].classList.contains("green") && !divs[indx].classList.contains("red") && indx != index && m.push(i)
        });

        if (k.length) {
            divs[index].classList.remove("red");
            if (m.indexOf(num) == -1|| Math.random() < .17) num = m[Math.floor(Math.random() * m.length)];
            k = arr.s[num];
            divs[k].classList.add("red");
            window.setTimeout(function() {
                move(k, num)
            }, 500)
        }
       else window.setTimeout(function() {
                move(index, num)
            }, 2000)
    }
});
  </script>
</head>

<body> <p></p>
<div id="matrix" ></div>

</body>
</html>

Dilettante_Pro 09.05.2017 13:39

рони,
Похоже, я телепат: я чувствовал, что что-то подобное появится

рони 09.05.2017 13:49

Dilettante_Pro,
:)

рони 10.05.2017 14:10

:write: изменил алгоритм движения кроликов пост №23

yaparoff 10.05.2017 17:11

Прикрутил к коду Dilettante_Pro кое-что еще:
добавил некоторые элементы ООП;
добавил новый юнит - траву.

Теперь думаю над следующим:
1) Нужно реализовать эффект зарастания травы по всему полю. Т.е если на клетке трава, то через некоторое время(допустим через 4 сек) на соседней клетке (выбирается рандомно) тоже должна появиться трава.
(смотреть строку № 100) http://plnkr.co/edit/yFvDmjtbARSTLjoKK0rW?p=preview

2) Животное (красный квадратик) должно кушать эту траву и получать энергию (баллы). Если оно не ест (количество баллов = 0) - через какое-то время оно умирает.

Сейчас же животное не может даже зайти на траву, т.к. никакой юнит не может заходить на другого юнита

Dilettante_Pro 10.05.2017 17:48

yaparoff,
У вас при движении животных получается двойной forEach - при вызове функции moveAnimal() и внутри этой функции. Из-за этого животные прыгают как сумасшедшие

yaparoff 10.05.2017 18:34

Цитата:

Сообщение от Dilettante_Pro (Сообщение 452065)
получается двойной forEach

Предлагаете убрать forEach у SetInterval (строка 129) ?

Написал вот так:
setInterval(function() {
	moveAnimal();
}, 1000);

Но интерпретатор не может понять что это за moveAnimal();
К нему надо подобраться по другому. Как?

Dilettante_Pro 11.05.2017 15:27

Цитата:

Сообщение от yaparoff
К нему надо подобраться по другому. Как?

Например, так
Animal.prototype.moveAnimal = function(i) {
	var stepTop, stepLeft, unitTop, unitLeft, noFree, unitPos = {};
//	for (var i = 0; i < animals.length; i++) {
		noFree = true;
		do {
			stepTop = Math.round(Math.random() * 2 - 1) * 20;
			stepLeft = Math.round(Math.random() * 2 - 1) * 20;
			unitTop = +animals[i].top.replace(/\D/g,"") + stepTop;
			unitLeft = +animals[i].left.replace(/\D/g,"") + stepLeft;
			if (unitTop < 0 || unitLeft < 0 || unitTop >  380 || unitLeft > 380) {
				noFree = true; 
			} else {
				unitTop = unitTop + 'px';
				unitLeft = unitLeft + 'px';
				noFree = false;
				
				for(var j = 0; j< units.length; j++) {
					if(units[j].top == unitTop && units[j].left == unitLeft) {
						noFree = true;
					}
				}
			}

		} while (noFree);
		units[i].top = unitTop;
		units[i].left = unitLeft;
		animals[i].top = unitTop;
		animals[i].left = unitLeft;
		var elem = document.querySelector('#a' + i);
		elem.style.top = unitTop;
		elem.style.left = unitLeft;
//	}
}


setInterval(function() {
		newAnimals.forEach(function(animal, index) {
			console.log(animal);
			animal.moveAnimal(index);
		});
	}, 1000);


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