| 
	| 
	
	| 
		
	| 
			
			 
			
				12.08.2018, 09:28
			
			
			
		 |  
	| 
		
			
			| Интересующийся       |  | 
					Регистрация: 12.08.2018 
						Сообщений: 18
					 
		
 |  |  
	| 
				Игра на JS эффект ночи
			 Всем привет. Решил я вообщем сделать свою небольшую игрушку, ничего особенного простенькая бродилка по карте из двухмерного массива с индексами координат спрайтов для отрисовки текстур ландшафта. 
И вот стало мне интересно, как можно реализовать в игре эффект смены времени суток? Что бы вся карта очень сильно затемнялась, но в некоторых точках которые я определю на оси X и Y (например у фонаря или в точке нахождения персонажа), был небольшой радиус подсвечивающий ближайшую местность.
 
Хочу добиться вот такого эффекта как на этих скриншотах!
https://www.google.ru/imgres?imgurl=...&iact=c&ictx=1
https://www.google.ru/imgres?imgurl=...&iact=c&ictx=1
https://www.google.ru/imgres?imgurl=...&iact=c&ictx=1 
Буду благодарен за помощь! |  |  
	| 
		
	| 
			
			 
			
				12.08.2018, 10:26
			
			
			
		 |  
	| 
		
			|  | Профессор       |  | 
					Регистрация: 01.12.2016 
						Сообщений: 3,650
					 
		
 |  |  
	| я так полагаю делаете используя обычные html элементы? |  |  
	| 
		
	| 
			
			 
			
				12.08.2018, 10:45
			
			
			
		 |  
	| 
		
			
			| Интересующийся       |  | 
					Регистрация: 12.08.2018 
						Сообщений: 18
					 
		
 |  |  
	| 
	
 
	| Сообщение от j0hnik   |  
	| я так полагаю делаете используя обычные html элементы? |  
	
 Нет, вся отрисовка на хостле canvas. 
В принципе я немного продвинулся по этому направлению, написал для персонажа функцию нахождения дистанции объекта относительно персонажа и установил переменную с радиусом света, если дистанция больше, тогда поверх фона отрисовываю новый слой rgba(0,0,0,0.8) если же радиус меньше то добавляю легкое затемнение, вроде работает
 
var map = location.getMap("bg");
for (var i = 0 ; i < map.length; i++) {
    for (var j = 0; j < map[i].length; j++) {
        var x = (j * cellSize) + offset_map.x, y = (i * cellSize) + offset_map.y;
        
        if(character.getDistanseTo({x: x + (cellSize / 2), y: y + (cellSize / 2)}) 
                         >= character.getRadiusLight()) {
            ctx.fillStyle = "rgba(0,0,0,0.8)";
	    ctx.fillRect(x, y, cellSize, cellSize);
	}
	else {
	    ctx.fillStyle = "rgba(0,0,0,0.3)";
	    ctx.fillRect(x, y, cellSize, cellSize);
        }
    }
}
Но есть некоторые недочеты и тут так как вся система карты у меня построена на сетке 32х32 так и отрисовка немного "квадратная" получается... 
Вот думаю как исправить.  
Если кто подскажет красивую формулу вычета разницы между этими отступами и закрашивания соседних квадратов ровно по линии радиуса персонажа, буду безмерно благодарен! |  |  
	| 
		
	| 
			
			 
			
				12.08.2018, 18:26
			
			
			
		 |  
	| 
		
			|  | Профессор       |  | 
					Регистрация: 27.05.2010 
						Сообщений: 33,150
					 
		
 |  |  
	| 
				canvas круг света
			 Arhitector, 
мысли вслух ...
 
<!DOCTYPE HTML>
<html>
<head>
  <title>Untitled</title>
</head>
<body>
<canvas id="canvas" width="600" height="400" style="border:1px solid #d3d3d3;"></canvas>
<script>
var img = new Image;
img.src = "https://mdn.mozillademos.org/files/5397/rhino.jpg";
img.onload = function() {
  draw(this);
};
function draw(img) {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");
  ctx.fillStyle = "black";
  ctx.fillRect(0, 0, 600, 400);
  function move(event) {
    ctx.drawImage(img, 0, 0, 600, 400);
    var x = event.layerX;
    var y = event.layerY;
    var grd = ctx.createRadialGradient(x, y, 5, x, y, 100);
    grd.addColorStop(0, "transparent");
    grd.addColorStop(1, "black");
    ctx.fillStyle = grd;
    ctx.fillRect(0, 0, 600, 400);
  }
  canvas.addEventListener("mousemove", move);
};
</script>
</body>
</html>
 |  |  
	| 
		
	| 
			
			 
			
				12.08.2018, 20:20
			
			
			
		 |  
	| 
		
			
			| Интересующийся       |  | 
					Регистрация: 12.08.2018 
						Сообщений: 18
					 
		
 |  |  
	| 
	
 
	| Сообщение от рони   |  
	| Arhitector, мысли вслух ...
 
 
<!DOCTYPE HTML>
<html>
<head>
  <title>Untitled</title>
</head>
<body>
<canvas id="canvas" width="600" height="400" style="border:1px solid #d3d3d3;"></canvas>
<script>
var img = new Image;
img.src = "https://mdn.mozillademos.org/files/5397/rhino.jpg";
img.onload = function() {
  draw(this);
};
function draw(img) {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");
  ctx.fillStyle = "black";
  ctx.fillRect(0, 0, 600, 400);
  function move(event) {
    ctx.drawImage(img, 0, 0, 600, 400);
    var x = event.layerX;
    var y = event.layerY;
    var grd = ctx.createRadialGradient(x, y, 5, x, y, 100);
    grd.addColorStop(0, "transparent");
    grd.addColorStop(1, "black");
    ctx.fillStyle = grd;
    ctx.fillRect(0, 0, 600, 400);
  }
  canvas.addEventListener("mousemove", move);
};
</script>
</body>
</html>
 |  
	
 Вот это действительно очень круто, спасибо. Сколько не гуглил но на createRadialGradient  ни разу так и не наткнулся.
 
Тут возникает немного другая проблема, когда вешаю данный код на функцию при наведением мыши  которая запускается при попадании курсора на холст, всё работает замечательно.
 
А вот когда пытаюсь привязать данное действие к координатам персонажа в функции которая запускается сразу  и начинает зацикленно отрисовывать мою карту, вот тут сразу же игру ломает вот такая ошибка
Uncaught TypeError: Failed to execute 'createRadialGradient' on 'CanvasRenderingContext2D': The provided double value is non-finite. at Object.drawMapBackground (draw.js:212)
 at render (game.js:178)
 at Image.water_bg.onload (game.js:211)
 
function render () {
	// отрисовка ландшафта, объектов персонажа и тд тд тд
	draw.drawMapBackground(); // <<<<----- сюда
	requestAnimationFrame(render); // зацикливание отрисовки
}
var draw = {
	// код код код
	// 
	drawMapBackground: function () {
		var real_pos = character.getRealCoordinates();
			var grd = ctx.createRadialGradient(real_pos.x, real_pos.y, 10, real_pos.x, real_pos.y, r);
		    grd.addColorStop(0, "transparent");
		    grd.addColorStop(1, "rgba(0,0,0,0.85)");
		    ctx.fillStyle = grd;
		    ctx.fillRect(0, 0, example.width, example.height);
	}
}
С чем это может быть связано? Сам я что то не смог разобраться, гугловский перевод аля 
"Предоставляемое двойное значение не ограничено " как то совсем не помог увы  			 Последний раз редактировалось Arhitector, 12.08.2018 в 20:28.
 |  |  
	| 
		
	| 
			
			 
			
				12.08.2018, 20:30
			
			
			
		 |  
	| 
		
			|  | Профессор       |  | 
					Регистрация: 27.05.2010 
						Сообщений: 33,150
					 
		
 |  |  
	| Arhitector,по обрывкам кода сложно что-то сказать, и выше была только идея, реализовать её можно по разному.
 |  |  
	| 
		
	| 
			
			 
			
				12.08.2018, 20:34
			
			
			
		 |  
	| 
		
			|  | Профессор       |  | 
					Регистрация: 20.12.2009 
						Сообщений: 1,714
					 
		
 |  |  
	| Проверьте real_pos.x , real_pos.y  и r . 
Они должны быть числами(но не NaN или Infinite) и не строками.
 
Возможно перед вызовом createRadialGradient можно проверить?
 
if(!Number.isFinite(real_pos.x)) console.log("invalid real_pos.x");
if(!Number.isFinite(real_pos.y)) console.log("invalid real_pos.y");
if(!Number.isFinite(r)) console.log("invalid r");
			 Последний раз редактировалось Malleys, 12.08.2018 в 20:41.
 |  |  
	| 
		
	| 
			
			 
			
				12.08.2018, 21:04
			
			
			
		 |  
	| 
		
			
			| Интересующийся       |  | 
					Регистрация: 12.08.2018 
						Сообщений: 18
					 
		
 |  |  
	| 
	
 
	| Сообщение от Malleys   |  
	| Проверьте real_pos.x, real_pos.y и r. Они должны быть числами(но не NaN или Infinite) и не строками.
 
 Возможно перед вызовом createRadialGradient можно проверить?
 
 
if(!Number.isFinite(real_pos.x)) console.log("invalid real_pos.x");
if(!Number.isFinite(real_pos.y)) console.log("invalid real_pos.y");
if(!Number.isFinite(r)) console.log("invalid r");
 |  
	
 Жаль на этом форуме нет кнопки "сто тысяч благодарностей"... вы ёё заслужили... 
И правда, совсем уже видимо замотался с этим делом, голова у меня не варит, переменные то проверить забыл, всё сразу встало на места.
 
Я уже даже такую штуку написать успел... брр
 
var r = character.getRadiusLight(),
  pos = character.getCoordinates(),
  normalDrawBG = function(object) {
    var r = object.r, x = object.x, y = object.y,
    bend = Math.round(object.r / Math.PI);
    ctx.fillStyle = "rgba(0,0,0,0.85)";
    ctx.moveTo(x - r, y); 
    ctx.bezierCurveTo(x - r, (y - r) - bend, x + r, (y - r) - bend, x + r, y);
    ctx.bezierCurveTo(x + r, y + r + bend, x - r, y + r + bend, x - r, y);
};
ctx.beginPath();
normalDrawBG({x: pos.x, y: pos.y, r: r});
ctx.moveTo(0, 0); 
ctx.lineTo(0, canvas.height); 
ctx.lineTo(canvas.width, canvas.height); 
ctx.lineTo(canvas.width, 0); 
ctx.closePath();
ctx.fill();
			
			
	
			
			
			
			
			
				  |  |  
	| 
		
	| 
			
			 
			
				12.08.2018, 21:05
			
			
			
		 |  
	| 
		
			
			| Интересующийся       |  | 
					Регистрация: 12.08.2018 
						Сообщений: 18
					 
		
 |  |  
	| 
	
 
	| Сообщение от рони   |  
	| Arhitector, по обрывкам кода сложно что-то сказать, и выше была только идея, реализовать её можно по разному.
 |  
	
 Это была чисто моя ошибка, ваш код супер, еще раз спасибо   |  |  
	| 
		
	| 
			
			 
			
				12.08.2018, 21:25
			
			
			
		 |  
	| 
		
			
			| Интересующийся       |  | 
					Регистрация: 12.08.2018 
						Сообщений: 18
					 
		
 |  |  
	| Еще сразу тогда спрошу тут же, что бы темы не плодить. Можно ли добавить одновременно 2-3 и более таких эффектов на карту? |  |  |  |