![]() |
|
||||||||||
|
|||||||
|
|
« Предыдущая тема | Следующая тема » |
| Опции темы | Опции просмотра |
|
![]() |
|
|||||
|
блогер
Регистрация: Feb 2008
Адрес: Россия, Новосибирск, Академгородок
Сообщений: 2,113
Записей в блоге: 1
|
Всем привет!
У меня тут случилась вроде бы простая задача, но всё никак не получается решить. Буду благодарен за любую помощь. В общем, есть некий игровой уровень. Он строится из квадратных "блоков" фиксированного размера (30 пикселей), каждый из которых занимает свою "ячейку", координаты которой кратны размеру. Если проще — подобно тому, как закрашиваем клетки в тетрадном листе. На этом уровне есть персонаж. Его размер кратен размеру блоков, и он, по-сути, является "склеенными" двумя блоками. В ширину персонах 30 пикселей, в высоту 60. В общем, два "блока". Персонаж может менять свои координаты, при этом его положение не ограничивается кратностью размера. Он может иметь любые координаты. Теперь, собственно, к проблеме. Я не использую каких-либо физических движков (их и не предлагать, кстати). Мне необходимо найти алгоритм ограничения персонажа таким образом, чтобы его габаритная фигура (прямоугольник из двух "блоков") не пересекал клетки и, в ситуациях, когда под персонажем нет клеток (падение), он просто смещался бы вниз (без ускорения достаточно). Перемещение персонажа считать внешним процессом, никак не зависящим от алгоритма. То есть по факту, при каждой новой итерации алгоритма (энтерфрэйм или таймер, не важно) я должен смотреть, зашел ли персонаж на стенку или "вдавился" ли в пол и, соответственно, разруливать эту ситуацию. Первое, что приходит на ум — проверка соседних клеток. Если координаты персонажа "входят" в клетку под ним, то сдвинуть его вверх. Если слева от него — сдвинуть вправо и так далее. Но при таком подходе есть неочевидный недостаток, — если персонаж упал на пол, углубился хотя бы чуть-чуть, то его клетками слева и справа станут клетки пола, хотя, по-идее, такого быть не должно. Иными словами, если я падаю с движением вправо на совершенно ровный пол из клеток (блоков), то в какой-то момент меня сдвинет в сторону, как от стены. Если менять последовательность подобных операций (сравнение сначала по вертикали, потом по горизонтали) — толку особого не будет, лишь поменяется вид ошибки. Я прикрепил очень простенькую заготовку, если у кого возникнет желание помочь / поразбираться. И, конечно же, код: package { import flash.display.Graphics; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.KeyboardEvent; import flash.ui.Keyboard; /** * ... * @author Hauts */ public class Main extends Sprite { private var _cells:Array; private var _cellsX:Array; private var _cellSize:int = 30; private var _player:Sprite; private var _container:Sprite; private var _levelWidth:int; private var _levelHeight:int; private var _up:Boolean = false; private var _down:Boolean = false; private var _left:Boolean = false; private var _right:Boolean = false; public function Main():void { if (stage) { init(); } else { addEventListener(Event.ADDED_TO_STAGE, init); } } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); // entry point stage.scaleMode = StageScaleMode.NO_SCALE; stage.showDefaultContextMenu = false; stage.align = StageAlign.TOP_LEFT; _container = new Sprite(); addChild(_container) var map:Array = []; map.push([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); map.push([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); map.push([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); map.push([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); map.push([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); map.push([1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1]); map.push([1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1]); map.push([1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]); map.push([1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1]); map.push([1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1]); map.push([1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1]); map.push([1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]); map.push([1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]); map.push([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); _levelWidth = map[0].length * _cellSize; _levelHeight = map.length * _cellSize; // generate map _cells = []; _cellsX = []; for (var k:int = 0; k < map.length; k++) { var mapColumn:Array = map[k] for (var j:int = 0; j < mapColumn.length; j++) { if (mapColumn[j] != 0) { var cell:Sprite = createBlock(_cellSize, _cellSize); cell.x = _cellSize * j; cell.y = _cellSize * k; _cells.push(cell) if (_cellsX[j] == null) { _cellsX[j] = []; } _cellsX[j][k] = cell; } } } // create 'player' element _player = createBlock(_cellSize, _cellSize * 2, 0x00FF00); _player.x = _cellSize * 1.25 _player.y = _cellSize * 2.75 stage.addEventListener(KeyboardEvent.KEY_DOWN, keyHandler); stage.addEventListener(KeyboardEvent.KEY_UP, keyHandler); addEventListener(Event.ENTER_FRAME, enterFrameHandler); enterFrameHandler(null) } private function keyHandler(e:KeyboardEvent):void { var value:Boolean = e.type == KeyboardEvent.KEY_DOWN; var keyCode:uint = e.keyCode; if (keyCode == Keyboard.UP) { _up = value; } if (keyCode == Keyboard.DOWN) { _down = value; } if (keyCode == Keyboard.LEFT) { _left = value; } if (keyCode == Keyboard.RIGHT) { _right = value; } } private function enterFrameHandler(e:Event):void { if (_left) { _player.x -= 5.125 } if (_right) { _player.x += 5.125 } if (_up) { _player.y -= 7.125 } if (_down) { _player.y += 7.125 } alignToPlayer() } private function alignToPlayer():void { var sw:int = stage.width; var sh:int = stage.height; _container.x = sw / 2 - _player.x; _container.y = sh / 2 - _player.y; if (_container.y > 0) { _container.y = 0; } if (_container.x > 0) { _container.x = 0; } } private function createBlock(width:int, height:int, color:uint = 0xFF0000):Sprite { var blockSprite:Sprite = new Sprite(); var gr:Graphics = blockSprite.graphics; gr.beginFill(color, 0.35); gr.lineStyle(1, 0); gr.drawRect(0, 0, width, height); gr.endFill(); gr.lineStyle(2, 0); gr.moveTo(-1, 0) gr.lineTo(1, 0) gr.moveTo(0, -1) gr.lineTo(0, 1) blockSprite.cacheAsBitmap = true; _container.addChild(blockSprite) return blockSprite; } } }
__________________
hauts.ru |
![]() |
Часовой пояс GMT +4, время: 18:09. |
|
|
« Предыдущая тема | Следующая тема » |
|
|