使用Android Drawable作为AndEngine HUD

时间:2012-11-30 06:48:57

标签: android andengine xml-drawable

我正在尝试创建一个AndEngine HUD,它将位于TMXTiledMap的顶部(跟我一起,我对AndEngine很新)。为了简单起见,我有一个通过Android drawables创建的简单矩形。这个想法是,它将位于屏幕的底部中心,并且永远不会移动,即使其下方的地图向各个方向移动也是如此。现在,我想做的就是让那个矩形出现。稍后我会在矩形中添加其他功能。

我的drawable是这样创建的:

    ?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle" >
        <corners
            android:radius="7dp" />
        <gradient
            android:startColor="#343434"
            android:endColor="#17171717"
            android:angle="270"
            android:useLevel="false"
            android:type="linear" />
        <padding
            android:left="10dp"
            android:top="10dp"
            android:right="10dp"
            android:bottom="10dp" />
    </shape>

我把它拉成这样的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="300dip"
    android:layout_height="100dip"
    android:orientation="horizontal" 
    android:layout_marginLeft="20dp"
    android:background="@drawable/menu_bkgrnd" >
</LinearLayout>

然后最后,我试图将其作为HUD拉入其中:

rect = new HUD();
ITouchArea container = (ITouchArea) findViewById(R.id.container);
this.rect.registerTouchArea(container);
rect.attachChild((IEntity) container);

正如你所看到的,我正在进行大量的演员来满足AndEngine,但是当我运行它时,地图完全搞砸了。我正确地谈到这个吗?我的演员是不正确的? (或者两者兼而有之!)。

感谢您的帮助。

编辑: 根据Jong和正宗白布鞋在下面提出的代码,我调整了我的Java代码如下:

this.atlas = new BitmapTextureAtlas(null, 256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.atlas.load();
ITextureRegion drawable = BitmapTextureAtlasTextureRegionFactory.createFromResource(atlas, getApplicationContext(), R.drawable.myDrawable, 0, 0);
rect.attachChild(new Sprite(0, 0, drawable, this.getVertexBufferObjectManager()));

此时,我仍然只是想让它出现在屏幕上。我稍后会调整大小和位置。

所有内容都可以无错误地编译和运行,但是我的屏幕只是一团糟。

正如您所看到的,我必须对构造函数参数进行一些小的调整,以使AndEngine接受我的实例化。不确定我是否正确这样做。

我在此代码中看到的另一个问题是,在我看来,此代码只是在屏幕上放置一个非活动形状。我知道在我原来的帖子中,我说我的直接目标是让这个矩形显示出来,但我认为它必须显示为一个注册的触摸区域,因为它最终会有一些需要响应的控件用户命令。对不起,如果我过度地减少了我想要做的事情。

我还没有得到这个。有人有什么建议吗?再次感谢!

2 个答案:

答案 0 :(得分:2)

您无法将LinearLayout转换为ITouchAreaITouchArea是仅由AndEngine类实现的接口。

与正宗白布鞋建议一样,你应该使用createFromResource的{​​{1}}方法。

您可以使用此代码:

BitmapTextureAtlasTextureRegionFactory

修改

如果您希望精灵响应触摸事件,可以将其注册为BitmapTextureAtlas atlas = new BitmapTextureAtlas(sizeX, sizeY, TextureOptions.BILINEAR_PREMULTIPLYALPHA); TextureRegion drawable = BitmapTextureAtlasTextureRegionFactory.createFromResource(atlas, getApplicationContext(), R.drawable.drawableId, 0, 0); rect.attachChild(new Sprite(x, y, drawable)); HUD中的触摸区域。

rect

答案 1 :(得分:0)

几天前我遇到了同样的问题,我找不到合适的答案。所以现在我收集了不同来源的信息,这就是我处理这个问题的方法。

AFAIK,来自createFromResource(atlas, getApplicationContext(), R.drawable.drawableId, 0, 0)的{​​{1}}方法似乎无法处理XML drawable(例如BitmapTextureAtlasTextureRegionFactory)。 实际上,当我只显示一个彩色矩形时,一切都很好 - 而且我认为也有一个PNG文件 - 但是当我尝试从我的XML drawable中创建一个<shape>...</shape>时,我当绘图发生时,总是得到Sprite

我采取的步骤:

  • 将可绘制资源转换为NullBitmapException
  • Drawable转换为DrawableSource here
  • Bitmap转换为Bitmap(这是我使用的地方this
  • TextureRegion创建Sprite(或选择/取消选择两个,如here
  • TextureRegion附加到游戏的Sprite

所以,代码:

转换可绘制资源HUD

TextureRegion

实用程序中介类

/**
 * Takes a drawable, and converts it to a TextureRegion.
 * @param context
 * @param resId the drawable ID
 * @param textureSizeX width for our TextureRegion
 * @param textureSizeY height for our TextureRegion
 * @return a TextureRegion from the drawable
 */
public static TextureRegion textureRegionFromDrawable(BaseGameActivity context, int resId, int textureSizeX, int textureSizeY) {
    Drawable drawable = context.getResources().getDrawable(resId);
    Bitmap bitmap = drawableToBitmap(drawable);
    BitmapTextureAtlasTextureSource source = new BitmapTextureAtlasTextureSource(bitmap);
    BitmapTextureAtlas textureAtlas = new BitmapTextureAtlas(context.getTextureManager(), textureSizeX, textureSizeY);
    textureAtlas.addTextureAtlasSource(source, 0, 0);
    textureAtlas.load();
    TextureRegion textureRegion = (TextureRegion) TextureRegionFactory.createFromSource(textureAtlas, source, 0, 0);
    return textureRegion;
}
// Drawable to Bitmap
public static Bitmap drawableToBitmap(Drawable drawable) {
    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable) drawable).getBitmap();
    }
    Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);
    return bitmap;
}

public class BitmapTextureAtlasTextureSource extends BaseTextureAtlasSource implements IBitmapTextureAtlasSource { private final int[] mColors; public BitmapTextureAtlasTextureSource(Bitmap pBitmap) { super(0, 0, pBitmap.getWidth(), pBitmap.getHeight()); mColors = new int[mTextureWidth * mTextureHeight]; for (int y = 0; y < mTextureHeight; ++y) { for (int x = 0; x < mTextureWidth; ++x) { mColors[x + y * mTextureWidth] = pBitmap.getPixel(x, y); } } } @Override public Bitmap onLoadBitmap(Config pBitmapConfig) { return Bitmap.createBitmap(mColors, mTextureWidth, mTextureHeight, Bitmap.Config.ARGB_8888); } @Override public IBitmapTextureAtlasSource deepCopy() { return new BitmapTextureAtlasTextureSource(Bitmap.createBitmap(mColors, mTextureWidth, mTextureHeight, Bitmap.Config.ARGB_8888)); } @Override public Bitmap onLoadBitmap(Config pBitmapConfig, boolean pMutable) { // TODO Auto-generated method stub return null; } } 创建两个Sprite(我的按钮需要2个状态:已选中/未选中),并将它们附加到TextureRegion < / p>

HUD

我们也可以使用int textureSizeX = 512, textureSizeY = 512; TextureRegion textureDefault = AndEngineUtils.textureRegionFromDrawable(activity, R.drawable.custom_menu_button, textureSizeX, textureSizeY); TextureRegion textureSelected = AndEngineUtils.textureRegionFromDrawable(activity, R.drawable.custom_menu_button_selected, textureSizeX, textureSizeY); mGameHUD = new HUD(); // 2 sprites for selected and unselected final Sprite buttonUnselected, buttonSelected ; buttonSelected = new Sprite(0, 0, textureSelected, activity.getVertexBufferObjectManager()); buttonSelected.setVisible(false); buttonUnselected = new Sprite(0, 0, textureDefault, activity.getVertexBufferObjectManager()) { @Override public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) { switch (pSceneTouchEvent.getAction()) { case TouchEvent.ACTION_DOWN: // Change button buttonSelected.setVisible(true); this.setVisible(false); break; case TouchEvent.ACTION_UP: // reset button this.setVisible(true); buttonSelected.setVisible(false); break; default: break; } return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX, pTouchAreaLocalY); } }; mGameHUD.attachChild(buttonSelected); mGameHUD.attachChild(buttonUnselected); mGameHUD.registerTouchArea(buttonUnselected); camera.setHUD(mGameHUD); 来制作一个“不需要的”滑动手势 - 直到按钮外部 - 采取措施重置按钮颜色(参见this thread)。

我刚开始使用scene.setOnAreaTouchListener(touchListener)并且我还不熟悉最佳做法,所以请随时纠正我。