Миникарта. Проверка по битмапе.
Написал вот такую нехитрую утилитку, мож кому пригодится.
Реализовывает такую вот схему:
- Есть битмапдата
- В битмапдате разные объекты имеют свой цвет. Каждый цвет это один бит из доступных 0xffffff
- рисуем объект в эту битмапдату доступными в классе методами
- после чего имеем возможность быстренько проверить есть ли такой цвет в этой точке или нету.
- Проверка имеется двух видов: "жесткая" и "обычная".
-- Обычная просто смотрит есть ли такой цвет в этой точке. Т.е. при обычной проверке вернется тру даже если в той точке имеется наслоение из кучи цветов, хоть и все доступные биты.
-- При жесткой идет проверка ==. Т.е. запрошенный цвет должен равняться тому который в битмапе. Т.е. в этой точке должен быть только один запрошенный слой.
У меня это используется так:
Есть миникарта города.
У зданий есть требования: нельзя строить на краю карты, на камнях, некоторые здания должны строиться только на берегу или на воде. Так же дороги имеют ряд требований для красивого рендера поворотов и изгибов разного рода.
Отрисовываю эти все объекты в эту битмапу, далее провожу разного рода проверки. Например в одной точке может быть бит цвета здания+ бит цвета края карты + бит цвета берега. Собственно хоть все доступные.
Но в той или иной ситуации меня может интересовать только один из этих битов.
Как-то так. Вроде всё понятно.
От спрайта наследовал только потому что он клики понимает, можно было отказаться и оставить только битмапу.
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 | |
А почему вы пишете бит, это все-таки байт.
|
20.10.2011 12:13 | |
BiteMap <= Секретная техника убийства одним укусом
|
20.10.2011 17:03 | |
20.10.2011 22:49 | |
Dukobpa3, и всё таки байт. Даже 4.
А, я понял. Внутри числа 0xFFFFFF прячутся 32 бита и их и используем. Было бы здорово, если этот момент был бы расписан. Он не очень очевиден. |
|
Обновил(-а) Psycho Tiger 20.10.2011 в 22:52
|
20.10.2011 22:54 | |
@Psycho Tiger
Именно, 32 бита, их и используем, в итоге у нас получается 32-х слойная миникарта. А как это использовать - это уже личное дело каждого. |
21.10.2011 08:19 | |
0xFFFFFF это 24 бита
Использовать 32 бита (0xFFFFFFFF) не получится из-за алгоритма оптимизации битмапа. |
21.10.2011 10:19 | |
Может, на byte array перейти?
|
21.10.2011 15:19 | |
Зачем двухмерный? Зная размерность, можно всегда вычислить индекс и наоборот.
|
21.10.2011 18:49 | |
Цитата:
Зная размерность, можно всегда вычислить индекс и наоборот.
|
Последние записи от Dukobpa3
- Strategy (Стратегия) (27.12.2013)
- State (Состояние) (27.12.2013)
- State-machine (конечный автомат, машина состояний) (25.12.2013)
- Медиатор, Прокси (14.11.2013)
- Инкапсуляция объекта vs инкапсуляция поведения (14.11.2013)