@ArtC

Полёт пули в игре html5+js?

Друзья всем привет! Мне нужна ваша помощь. У меня игра на HTML5 + JS на полотне canvas. На этом полотне есть объект, который стреляет пулями. Сама карта игры (canvas) достаточно большая, и пуля летит в направлении через всю карту. Как сделать, чтобы она пролетала, скажем, 100-200 пикселей и после этого исчезала?

Я точно не уверен, но думаю, что реализовать это можно здесь:

if( this.weapon.fireRateTick < this.weapon.fireRate ){
			this.weapon.fireRateTick += $.dt;
		} else {
			if( $.autofire || ( !$.autofire && $.mouse.down ) ){
				$.audio.play( 'shoot' );
				if( $.powerupTimers[ 2 ] > 0 || $.powerupTimers[ 3 ] > 0 || $.powerupTimers[ 4 ] > 0) {
					$.audio.play( 'shootAlt' );
				}

				this.weapon.fireRateTick = this.weapon.fireRateTick - this.weapon.fireRate;
				this.weapon.fireFlag = 6;

				if( this.weapon.count > 1 ) {
					var spreadStart = -this.weapon.spread / 2;
					var spreadStep = this.weapon.spread / ( this.weapon.count - 1 );
				} else {
					var spreadStart = 0;
					var spreadStep = 0;
				}

				var gunX = this.x + Math.cos( this.direction ) * ( this.radius + this.weapon.bullet.size );
				var gunY = this.y + Math.sin( this.direction ) * ( this.radius + this.weapon.bullet.size );

				for( var i = 0; i < this.weapon.count; i++ ) {
					$.bulletsFired++;
					var color = this.weapon.bullet.strokeStyle;
					if( $.powerupTimers[ 2 ] > 0 || $.powerupTimers[ 3 ] > 0 || $.powerupTimers[ 4 ] > 0) {
						var colors = [];
						if( $.powerupTimers[ 2 ] > 0 ) { colors.push( 'hsl(' + $.definitions.powerups[ 2 ].hue + ', ' + $.definitions.powerups[ 2 ].saturation + '%, ' + $.definitions.powerups[ 2 ].lightness + '%)' ); }
						if( $.powerupTimers[ 3 ] > 0 ) { colors.push( 'hsl(' + $.definitions.powerups[ 3 ].hue + ', ' + $.definitions.powerups[ 3 ].saturation + '%, ' + $.definitions.powerups[ 3 ].lightness + '%)' ); }
						if( $.powerupTimers[ 4 ] > 0 ) { colors.push( 'hsl(' + $.definitions.powerups[ 4 ].hue + ', ' + $.definitions.powerups[ 4 ].saturation + '%, ' + $.definitions.powerups[ 4 ].lightness + '%)' ); }
						color = colors[ Math.floor( $.util.rand( 0, colors.length ) ) ];
					}
					$.bullets.push( new $.Bullet( {					
[B]						x: gunX,
						y: gunY,
						speed: this.weapon.bullet.speed,
						direction: this.direction + spreadStart + i * spreadStep,
						damage: this.weapon.bullet.damage,
						size: this.weapon.bullet.size,
						lineWidth: this.weapon.bullet.lineWidth,
						strokeStyle: color,
						piercing: this.weapon.bullet.piercing[/B]					
					} ) );
				}
			}
		}


В участке кода, что я выделил жирным - можно устанавливать значения размера пули, скорости, её урона. Вероятно в этом участке указывать длину пути? Но каким образом? Прошу вашей помощи.
  • Вопрос задан
  • 503 просмотра
Решения вопроса 1
lastuniverse
@lastuniverse
Всегда вокруг да около IT тем
ArtC, выкладываю демонстрацию. Покликайте левой кнопкой мышки по листу с сеткой.

код реализации цикла расчета и отображения пуль
(function(exports) {
	console.log("Billets");
	"use strict";

	/**
	 * в данном модуле для векторных расчетов используется модуль Vector
	 * его код доступен по ссылке https://game.lastuniverse.ru/gun.2d.01/js/vector.js
	 * в этом модуле его функционал доступен через глобальную переменную window.libs.Vector
	 */
	// создаем сокращенную ссылку на функционал модуля vector.js
	const Vector = window.libs.Vector;


	/**
	 * в данном модуле для отрисовки на canvas-е сетки, а также для масштабирования
	 * используется специальная прослойка. В вашем случае вы будете просто сами рисовать через
	 * 2d контекст canvas-а полученный с помощью ctx = canvas.getContext("2d");
	 * здесь же я использую специальные врапперы, таким образом чтобы код 
	 * представленный далее можно было использовать на обычном контексте canvas-а
	 */
	// создаем врапер на контекст канваса canvas.getContext("2d")
	let ctx = window.libs.ctx;
	// в вашем случае будет както так
	// ctx = canvas.getContext("2d");


	/**
	 * Функция перерисовки сетки. В вашем случае это будет функция рисующая 
	 * через ctx какой то фон на канвасе
	 */
	function redraw() {
		window.libs.sheet.planedReDraw();
		window.libs.sheet.reDraw();	
		// в вашем случае будет както так:
		// ctx.fillStyle="#1b1b1b"; // устанавливаем цвет фона
		// ctx.fillRect(0,0,canvas.width,canvas.height); // зарисовываем канвас этим цветом

	}


	/**
	 * для того чтобы интерфейс мог иметь доступ к параметрам пули и менять их
	 * экспортируем объект с настройками и функциями данного модуля. 
	 * В других модулях будет доступен как window.libs.bullets
	 * в вашем случае в этом нет необходимости
	 */
	exports.bullets = {};

	
	/**
	 * Настройки симуляции
	 * settings.speed 		- скорость новых пуль
	 * settings.size 		- размер новых пуль
	 * settings.distance	- радиус жизни пуль
	 */
	const settings = {
		speed: 10,
		size: 10,
		distance: 200
	};
	// экспортируем для интерфейса объект с настройками пуль. 
	// В вашем случае в этом нет необходимости
	exports.bullets.settings = settings;
	





	/**
	 * Приготовления завершены, начинаем создавать пули !!!!
	 */





	
	/**
	 * массив с пулями. каждая пуля описывается объектом, содержащим ключи:
	 * @key {object} loc 		объект {x: ..., y: ...} содержащий текущие координаты пули
	 * @key {object} emitter 	объект {x: ..., y: ...} содержащий координаты из которых стартовала пуля
	 * @key {object} direction 	нормализованный вектор/объект {x: ..., y: ...} содержащий направление полета пули (нормализованный - значит его длинна равна 1)
	 * @key {number} distance	радиус жизни пули
	 * @key {number} speed 		скорость пули
	 * @key {number} size 		размер пули
	 */
	let bullets = [];

	
	/**
	 * Обработчик собития click по рабочему пространству листа (canvas-а)
	 * @param  {object} event 	имитация стандартного эвента события click (в вашем случае при использовании этого кода будет не имитация)
	 */
	function mouseclick(event){
		add_bullet(
			{ x: 0, y: 0 }, // летит из центра
			{ x: event.clientX, y: event.clientY }, // по направлению к курсору мышки
			settings.distance, // c радиусом жизни пули указанным в настройках
			settings.speed, // со скоростью указанной в настройках
			settings.size // с размером указанным в настройках
		);
	}
	// экспортируем обработчик события click по листу. Будет вызван при клике на листе
	exports.bullets.mouseclick = mouseclick;
	// в вашем случае вместо этого вы сделаете так:
	// canvas.addEventListener("click", mouseclick);


	/**
	 * функция добавления новой пули
	 * @param {object} emitter 		объект {x: ..., y: ...} содержащий координаты из которых стартует пуля
	 * @param {object} direction 	        не нормализованный вектор/объект {x: ..., y: ...} содержащий направление полета пули
	 * @param {number} distance		радиус жизни пули
	 * @param {number} speed     	скорость пули
	 * @param {number} size 		размер пули
	 */
	function add_bullet(emitter, direction, distance, speed, size) {
		
		// заносим в массив с пулями новую пулю
		bullets.push({
			emitter: emitter,
			loc: emitter,
			direction: new Vector(direction.x, direction.y).normalize(),
			distance: distance,
			speed: speed,
			size: size
		});
	}

	/**
	 * функция расчета следующей позиции пули
	 * @param  {object} bullet 	объект, содержащий параметры пули: loc, emitter, direction, speed, size
	 */
	function calc_bullet(bullet) {
		
		// преобразуем координаты в объект класса Vector
		const loc = new Vector(bullet.loc.x, bullet.loc.y);
		
		// рассчитываем вектор приращения в направлении движения пули для ее скорости
		const vector = bullet.direction.multiply(bullet.speed);

		// добавляем к координатам пули значение вектора с приращениями
		bullet.loc = loc.add(vector).toLocate();
	}

	/**
	 * функция расчета следующей позиции всех пуль.
	 * также функция следит за удалением пуль при их
	 * отлете на расстояние превышающее радиус жизни пули
	 */
	function calc_all_bullets() {
		
		// прокручиваем в цикле все пули
		bullets.forEach(bullet=>{
			
			// расчитываем новые координаты очередной пули
			calc_bullet(bullet);

			// рассчитываем расстояние пули от точки старта
			const distance = Math.sqrt( Math.pow(bullet.emitter.x-bullet.loc.x, 2) + Math.pow(bullet.emitter.y-bullet.loc.y, 2) );

			// если дистанция болше чем дистанция жизни этой пули, запоминаем что ее надо удалить
			if( distance > bullet.distance ){
				bullet.toDelete = true;
			}
		});

		// удаляем помеченые для удаления пули
		bullets = bullets.filter(bullet=> !bullet.toDelete);
	}

	/**
	 * функция отрисовки пули
	 */
	function draw_bullet(bullet) {
		ctx.beginPath();
		ctx.strokeStyle = "#fff";
		ctx.fillStyle = "#f00";
		ctx.arc( bullet.loc.x, bullet.loc.y, bullet.size, 0, Math.PI*2, false );
		ctx.closePath();
		ctx.fill();
		ctx.stroke();		
	}

	/**
	 * функция отрисовки всех имеющихся пуль
	 */
	function draw_all_bullets() {
		
		// прокручиваем в цикле все пули
		bullets.forEach(bullet=>{
			
			// отрисовываем очередную пулю
			draw_bullet(bullet)

		});
	}


	/**
	 * функция содержащая действия цикла игровой симуляции
	 */
	function play(){

		// следующую строку в вашем случае нужно удалить
		if(!ctx) ctx = window.libs.ctx;

		// расчитываем новые координаты всех пуль
		calc_all_bullets();

		// перерисовыаем фон на листе (на канвасе)
		redraw();

		// перерисовыаем все пули
		draw_all_bullets();

		// панируем запуск следующей итерации игрового цикла через 20 милисекунд
		setTimeout(play,20);
	}


	/**
	 * запускаем функцию игрового цикла.
	 */
	play();

})(this.libs=this.libs||{});



PS: Так же Вы можете дополнительно посмотреть как реализованы векторные вычисления на плоскости canvas-a (вычисление расстояний, скоростей, направлений а также масштабирования) в этом ответе
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы