Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > Dukobpa3

Оценить эту запись

Миникарта. Проверка по битмапе.

Запись от Dukobpa3 размещена 19.10.2011 в 18:56
Обновил(-а) Dukobpa3 20.10.2011 в 17:03

Написал вот такую нехитрую утилитку, мож кому пригодится.

Реализовывает такую вот схему:
- Есть битмапдата
- В битмапдате разные объекты имеют свой цвет. Каждый цвет это один бит из доступных 0xffffff
- рисуем объект в эту битмапдату доступными в классе методами
- после чего имеем возможность быстренько проверить есть ли такой цвет в этой точке или нету.
- Проверка имеется двух видов: "жесткая" и "обычная".
-- Обычная просто смотрит есть ли такой цвет в этой точке. Т.е. при обычной проверке вернется тру даже если в той точке имеется наслоение из кучи цветов, хоть и все доступные биты.
-- При жесткой идет проверка ==. Т.е. запрошенный цвет должен равняться тому который в битмапе. Т.е. в этой точке должен быть только один запрошенный слой.

У меня это используется так:

Есть миникарта города.
У зданий есть требования: нельзя строить на краю карты, на камнях, некоторые здания должны строиться только на берегу или на воде. Так же дороги имеют ряд требований для красивого рендера поворотов и изгибов разного рода.

Отрисовываю эти все объекты в эту битмапу, далее провожу разного рода проверки. Например в одной точке может быть бит цвета здания+ бит цвета края карты + бит цвета берега. Собственно хоть все доступные.
Но в той или иной ситуации меня может интересовать только один из этих битов.

Как-то так. Вроде всё понятно.

От спрайта наследовал только потому что он клики понимает, можно было отказаться и оставить только битмапу.
Код AS3:
package com.addictedcompany.hittest 
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.geom.Rectangle;
 
	/**
	 * ...
	 * @author Dukobpa3
	 */
	public class HittestMap extends Sprite 
	{
		/** Собственно битмапа для отображения, по сути ненужная весчь но без нее не сможем добавить на экран */
		private var _bitmap:Bitmap;
		/** битмапдата для проверок */
		private var _bitmapData:BitmapData;
 
		/** список цветов */
		private var _colors:Object;
 
		/** Техническая переменная, нужняа только для того чтобы видеть максимальный номер цвета при добавлении следующего */
		private var _lastColor:uint = 1;
 
		/**
		 * Конструктор, принимает размеры требуемой битмапы
		 * @param	w
		 * @param	h
		 */
		public function HittestMap(w:int, h:int, clone:HittestMap = null) 
		{
			if (clone)
			{
				cloneFrom(clone)
			}
			else
			{
				_bitmapData = new BitmapData(w, h, false, 0x000000);
				_bitmap = new Bitmap(_bitmapData);
				_colors = { };
 
				addChild(_bitmap);
			}
		}
 
		/**
		 * Отрисовывает в битмапу в этот прямоугольник этот цвет
		 * @param	rect прямоугольник
		 * @param	color имя цвета
		 */
		public function drawRect(rect:Rectangle, color:String):void
		{
			registerColor(color);
 
			for (var x:int = rect.x ; x < rect.x + rect.width ; x ++ )
			{
				for (var y:int = rect.y ; y < rect.y + rect.height ; y ++ )
				{
					drawPoint(new Point(x, y), color);
				}
			}
		}
 
		/**
		 * Отрисовывает  в битмапу в эту точку этот цвет
		 * @param	point точка
		 * @param	color имя цвета
		 */
		public function drawPoint(point:Point, color:String):void
		{
			registerColor(color);
 
			var colorFin:uint = _bitmapData.getPixel(point.x, point.y) | _colors[color];
			_bitmapData.setPixel(point.x, point.y, colorFin);
 
			trace(color, point)
		}
 
		/**
		 * Очищает этот цвет в этом прямоугольнике
		 * @param	rect прямоугольник
		 * @param	color имя цвета
		 */
		public function clearRect(rect:Rectangle, color:String):void
		{
			for (var x:int = rect.x ; x < rect.x + rect.width ; x ++ )
			{
				for (var y:int = rect.y ; y < rect.y + rect.height ; y ++ )
				{
					clearPoint(new Point(x, y), color);
				}
			}
		}
 
		/**
		 * Очищает этот цвет в этой точке
		 * @param	point точка
		 * @param	color имя цвета
		 */
		public function clearPoint(point:Point, color:String):void
		{
			if(checkColor(point, color))
			{
				var checkColor:uint = _bitmapData.getPixel(point.x, point.y);
				var resultColor:uint = checkColor - _colors[color];
 
				_bitmapData.setPixel(point.x, point.y, resultColor);
			}
		}
 
		/**
		 * Проверяет наличие/отсутствие этого цвета в этой точке
		 * @param	point точка
		 * @param	color имя цвета
		 * @param	strict если тру - то провека будет не по наличию цвета в массе других, а жесткая: цвет в точке == запрошенному / цвет в точке != запрошенному
		 * @return тру если цвет есть, фалс если нету
		 */
		public function checkColor(point:Point, color:String, strict:Boolean = false):Boolean
		{
			var checkColor:uint = _bitmapData.getPixel(point.x, point.y);
 
			return strict ?
				(checkColor == _colors[color]) ? 
					true : 
					false:
				((checkColor & _colors[color]) == _colors[color]) ?	
					true : 
					false;
		}
 
		/**
		 * Очищает все цвета, заливает всё черным
		 */
		public function clearAll():void
		{
			_bitmapData.fillRect(new Rectangle(0, 0, _bitmapData.width, _bitmapData.height), 0);
		}
 
		/**
		 * Клонирует данные из другого HittestMap
		 * @param	clone
		 */
		public function cloneFrom(clone:HittestMap):void
		{
			_bitmapData.dispose();
			_bitmapData = null;
			_bitmapData = new BitmapData(clone.bitmapData.width, clone.bitmapData.height);
			_bitmapData.draw(clone.bitmapData);
 
			removeChild(_bitmap);
 
			_bitmap = new Bitmap(_bitmapData);
			addChild(_bitmap);
 
			_colors = clone.colors;
		}
 
		/**
		 * Добавляет новый цвет в битмапу. Сам цвет выбирается автоматически по степени двойки.
		 * @param	name имя по которому этот цвет можно будет брать
		 */
		private function registerColor(name:String):void
		{
			if (!_colors.hasOwnProperty(name))
			{
				_colors[name] = _lastColor;
				_lastColor *= 2;
			}
 
		}
 
		/**
		 * Геттеры, нужны для клонирования
		 */
		protected function get bitmapData():BitmapData { return _bitmapData; }
		protected function get colors():Object { return _colors; }
	}
 
}
Всего комментариев 10

Комментарии

Старый 20.10.2011 11:30 Genzo вне форума
Genzo
 
Аватар для Genzo
А почему вы пишете бит, это все-таки байт.
Старый 20.10.2011 12:13 BuKT вне форума
BuKT
 
Аватар для BuKT
BiteMap <= Секретная техника убийства одним укусом
Старый 20.10.2011 17:03 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
@Genzo - Видимо потому что таки бит)))

Код AS3:
_lastColor *= 4;
втыкнул поправить, то для проверки стояло чтобы цвета визуально больше отличались чем если бы по одному биту занимали. Но в любом случае 4 бита это не байт отнюдь

@BuKT - а это что? как-то туго гуглится.
Старый 20.10.2011 22:49 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Dukobpa3, и всё таки байт. Даже 4.

А, я понял. Внутри числа 0xFFFFFF прячутся 32 бита и их и используем.
Было бы здорово, если этот момент был бы расписан. Он не очень очевиден.
Обновил(-а) Psycho Tiger 20.10.2011 в 22:52
Старый 20.10.2011 22:54 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
@Psycho Tiger

Именно, 32 бита, их и используем, в итоге у нас получается 32-х слойная миникарта. А как это использовать - это уже личное дело каждого.
Старый 21.10.2011 08:19 iNils вне форума
iNils
 
Аватар для iNils
0xFFFFFF это 24 бита
Использовать 32 бита (0xFFFFFFFF) не получится из-за алгоритма оптимизации битмапа.
Старый 21.10.2011 10:19 dimarik вне форума
dimarik
 
Аватар для dimarik
Может, на byte array перейти?
Старый 21.10.2011 12:38 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
@iNils да, ты прав, таки 24. 3 ключевых цвета х8 бит каждый. В моем случае не суть важно в виду того что больше восьми слоев ни разу не приходилось использовать.

Именно поэтому, наверное dimarik тоже прав только я не знаю как это красиво сделать. Хранить в БайтАррей массив точек двумерный? И имеет ли это смысл вообще, имхо битмапдата дает всё что нужно, навигацию по координатам и этих самых 24 слоя без всяких бубнов.
Старый 21.10.2011 15:19 iNils вне форума
iNils
 
Аватар для iNils
Зачем двухмерный? Зная размерность, можно всегда вычислить индекс и наоборот.
Старый 21.10.2011 18:49 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
Цитата:
Зная размерность, можно всегда вычислить индекс и наоборот.
Ну так примитивная реализация двумерного массива все-равно получится с такой схемой.
 

 


Часовой пояс GMT +4, время: 14:13.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.