Все что описано в этом сообщении, касается движка AndEngine версии GLES2, под версию GLES1 не проверялось.
Мне встречалась попытка реализации такого класса на stackoverflow.com, но приведенный там код у меня не заработал и сейчас, к сожалению, я не могу дать на него прямую ссылку.
Итак, к делу.
В AndEngine есть великолепный класс - AutoParallaxBackground который позволяет сделать непрерывно движущуюся картинку бэкграунда. Конечно, картинка должна быть согласована, т.е. начало картинки должно совпадать с концом (чисто визуально), иначе, все получится, но будет виден разрыв. Благодаря такому поведению спрайта, создается впечатление глубины сцены, а если его сделать многослойным - получается очень красиво и профессионально.Ну про AutoParalaxBackground мы можем подробно узнать из AndEngine examples.
А, что делать, если нам нужно такое же "поведение" спрайта, но не на бэкграунде, а поверх сцены? Например, сделать непрерывно движущиеся облака поверх солнца или там луны, и при этом к объекту, который перекрывается облаками нам нужен доступ как к обычному спрайту (это максимально развязывает руки дизайнеру и разработчику), К сожалению, AndEngine не предоставляет такого класса... Хотя почему к сожалению? Есть повод пораскинуть мозгами! (а у меня есть тема для блога) Короче, начнем раскидывать:-)
Мне встречалась попытка реализации такого класса на stackoverflow.com, но приведенный там код у меня не заработал и сейчас, к сожалению, я не могу дать на него прямую ссылку.
Итак, к делу.
В AndEngine есть великолепный класс - AutoParallaxBackground который позволяет сделать непрерывно движущуюся картинку бэкграунда. Конечно, картинка должна быть согласована, т.е. начало картинки должно совпадать с концом (чисто визуально), иначе, все получится, но будет виден разрыв. Благодаря такому поведению спрайта, создается впечатление глубины сцены, а если его сделать многослойным - получается очень красиво и профессионально.Ну про AutoParalaxBackground мы можем подробно узнать из AndEngine examples.
А, что делать, если нам нужно такое же "поведение" спрайта, но не на бэкграунде, а поверх сцены? Например, сделать непрерывно движущиеся облака поверх солнца или там луны, и при этом к объекту, который перекрывается облаками нам нужен доступ как к обычному спрайту (это максимально развязывает руки дизайнеру и разработчику), К сожалению, AndEngine не предоставляет такого класса... Хотя почему к сожалению? Есть повод пораскинуть мозгами! (а у меня есть тема для блога) Короче, начнем раскидывать:-)
public class ParallaxSprite extends Sprite { private float mParallaxSpeed; private float mOffsetX = 0; public ParallaxSprite(float pX, float pY, float mParallaxSpeed, ITextureRegion pTextureRegion, VertexBufferObjectManager pVertexBufferObjectManager) { super(pX, pY, pTextureRegion, pVertexBufferObjectManager); this.mParallaxSpeed = mParallaxSpeed; this.mOffsetX = pX - (pX * mParallaxSpeed); } @Override public void onManagedUpdate(float pSecondsElapsed){ super.onManagedUpdate(pSecondsElapsed); this.mOffsetX += this.mParallaxSpeed * pSecondsElapsed; } @Override protected void onManagedDraw(GLState pGLState, Camera pCamera) { pGLState.pushModelViewGLMatrix(); { final float shapeWidthScaled = this.getWidthScaled(); final float cameraWidth = pCamera.getWidth(); float baseOffsetX = (this.mOffsetX * this.mParallaxSpeed)% shapeWidthScaled; while(baseOffsetX > 0) { baseOffsetX -= shapeWidthScaled; } pGLState.translateModelViewGLMatrixf(baseOffsetX, 0, 0); float currentMaxX = baseOffsetX; do { this.preDraw(pGLState, pCamera); this.draw(pGLState, pCamera); this.postDraw(pGLState, pCamera); pGLState.translateModelViewGLMatrixf(shapeWidthScaled, 0, 0); currentMaxX += shapeWidthScaled; } while(currentMaxX < cameraWidth); } pGLState.popModelViewGLMatrix(); } public void setSpeed(float pSpeed){ this.mParallaxSpeed = pSpeed; } public float getSpeed(float pSpeed){ return this.mParallaxSpeed; } }Использование:
ParallaxSprite spriteClouds1 = new ParallaxSprite(0, 0, 5.0f, mRegionClouds, this.getVertexBufferObjectManager())
0,0 - это координаты левого верхнего угла спрайта относительно сцены.
mRegionClouds - это регион текстуры нашего спрайта.
this.getVertexBufferManager() - это так надо ;-)
Вот и все.
Что мы натворили: перекрыли метод отрисовки стандартного спрайта немного измененным кодом AutoParallaxBackground. Если интересуют какие именно отличия - велком в исходный код AutoParallaxBackground.
Еще тройка интересных, на мой взгляд, замечаний:
1.Здесь реализовано горизонтальное движение, а если хотим вертикальное? Посмотрите на этот незамысловатый код внимательней и увидите, что его ничего не стоит переделать и двигать по оси Y, причем делать это в зависимости от ситуации. Зачем двигать спрайт вертикально? Чтобы сделать джампер круче Doodle например ;-)
2.Наши облака представляют собой два спрайта имеющих одну и ту же текстуру. Они занимают всю сцену и имеют разные скорости, таким образом, создается впечатление, что облака постоянно меняются, хотя на самом деле две одинаковых картинки движутся относительно друг друга с разной скоростью.
3. Вы можете изменить направление движения поставив третий параметр < 0.
Кроме того, эта штука реализована у нас в обоях. Добро пожаловать и прокомментировать!
Да, много чудовищных терминов конечно, ну а так нормально....Вперёд к покорению интернета.
ОтветитьУдалитьПривет. У тебя глюк с нумерацией строк. Он проявляется в Хроме с недавнего времени. Проверь. Вчера я нашел костыль на эту тему. Если надо - обращайся...
ОтветитьУдалитьSapfil, привет! А как с тобой связаться?
ОтветитьУдалитьЕсли по поводу глюков с подсветкой, то я написал небольшой пост на эту тему.
Удалитьhttp://sapfil-proger.blogspot.com/2012/09/syntaxhighlighter.html
Надеюсь, что это сэкономит время таким как я :).
Если просто связаться по какому-либо другому поводу - можно в скайпе "Sapfil2"
Но учиться у меня нечему. Я вот пытаюсь сейчас разобраться с второй версией AndEngine. И совершенно не понимаю, что такое "VertexBufferObjectManager". :(
ага. именно глюки с подсветкой, а по поводу буфермэнеджера - видимо обслуживать вершины объекта может не только менеджер активити, но и какой-то другой. по сути он представляет собой класс с двумя arraylist в одном из которых загруженные объекты, а в другом которые будут выгружены. Вообще,имхо, его вызов остался там, потому, что его забыли или поленились убрать. ;)
УдалитьАга. Додумался прочесть твой пост.
ОтветитьУдалить"this.getVertexBufferManager() - это так надо ;-)"
Если я правильно понял, движок сам создает этот шайтан-буфер, и к нему просто нужно обращаться через "this"?
Не все понял в твоем ответе про буферменеджер - слаб я еще в яве. :( Но хочу сказать одно - в первой версии движка AndEngine этой фигни не было. И она намеренно добавлена во вторую. Значит оно именно кому-то очень надо. Но это надо изучать OpenGL, видимо...
Мы пишем игры еще с первой версии, и в курсе этих изменений. Тем не менее, со 2-й версией работать комфортней =) This - это ссылка объекта на самого себя. Если нужно создать спрайт в другом классе, то нужно обратиться к твоей главной активити. Я это делаю создавая специальную ссылку Instance которую можно использовать в любом месте проекта, и вызывать любые (не приват) методы активити и поля.
ОтветитьУдалитьДада. Про this я знаю из С++. Там опыта побольше у меня :)
УдалитьОк. Думаю твой совет про Instance мне потребуется в ближайшее время.
П.с. А чего не правишь разметку кода? :)
пока некогда) как раз рисуем новую игрушку. как будет повод для статьи так и исправлю уже везде)
Удалить