You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从安卓图库选图并导入LibGDX纹理?游戏头像设置需求

在LibGDX安卓游戏中实现从图库选图作为头像的步骤

1. 安卓端(AndroidLauncher)配置与实现

1.1 添加权限

在AndroidManifest.xml中添加图片读取权限,兼容不同安卓版本:

<!-- Android 13+ 适配 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<!-- Android 12及以下 兼容 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />

1.2 实现图库选择逻辑

在AndroidLauncher中使用ActivityResultContracts实现现代版图库选择,并处理权限申请:

import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import java.io.IOException;
import java.io.InputStream;

public class AndroidLauncher extends AndroidApplication {
    private ActivityResultLauncher<Intent> pickImageLauncher;
    private MyGdxGame gameInstance;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
        
        gameInstance = new MyGdxGame();
        initialize(gameInstance, config);

        // 初始化图片选择启动器
        pickImageLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == RESULT_OK && result.getData() != null) {
                    Uri imageUri = result.getData().getData();
                    try {
                        InputStream inputStream = getContentResolver().openInputStream(imageUri);
                        gameInstance.handleSelectedImage(inputStream);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        );
    }

    // 供Core调用的图库启动方法
    public void launchImagePicker() {
        // 检查权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.READ_MEDIA_IMAGES}, 100);
                return;
            }
        } else {
            if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, 100);
                return;
            }
        }

        // 启动图库
        Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        intent.setType("image/*");
        pickImageLauncher.launch(intent);
    }

    // 处理权限申请结果
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 100) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                launchImagePicker();
            } else {
                Toast.makeText(this, "需要读取图片权限才能设置头像", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

2. Core模块处理图片加载与显示

在Core的游戏主类中,接收安卓端传递的输入流,加载为纹理并处理渲染:

import com.badlogic.gdx.Application;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import java.io.IOException;
import java.io.InputStream;

public class MyGdxGame extends Game {
    private SpriteBatch batch;
    private Texture avatarTexture;

    @Override
    public void create() {
        batch = new SpriteBatch();
        // 其他初始化逻辑
    }

    // 接收安卓端传递的图片输入流,在GL线程加载纹理
    public void handleSelectedImage(final InputStream inputStream) {
        Gdx.app.postRunnable(() -> {
            try {
                // 释放旧纹理,避免内存泄漏
                if (avatarTexture != null) {
                    avatarTexture.dispose();
                }
                // 加载新纹理
                avatarTexture = new Texture(inputStream);
                // 设置纹理过滤,优化显示效果
                avatarTexture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        batch.begin();
        // 绘制头像(示例:左上角200x200大小)
        if (avatarTexture != null) {
            batch.draw(avatarTexture, 50, Gdx.graphics.getHeight() - 250, 200, 200);
        }
        batch.end();
    }

    @Override
    public void dispose() {
        batch.dispose();
        if (avatarTexture != null) {
            avatarTexture.dispose();
        }
    }
}

3. 游戏内触发图库选择

在游戏的UI界面(比如设置页)中,添加按钮点击事件调用图库选择:

import com.badlogic.gdx.scenes.scene2d.ui.Button;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.Application;

// 示例:设置界面的按钮点击逻辑
Button pickAvatarBtn = new Button(skin);
pickAvatarBtn.addListener(new ClickListener() {
    @Override
    public void clicked(com.badlogic.gdx.scenes.scene2d.InputEvent event, float x, float y) {
        if (Gdx.app.getType() == Application.ApplicationType.Android) {
            AndroidLauncher androidLauncher = (AndroidLauncher) Gdx.app.getApplicationListener();
            androidLauncher.launchImagePicker();
        }
    }
});

关键注意事项

  • 内存管理:每次加载新头像时必须释放旧纹理,避免内存泄漏。
  • 线程安全:LibGDX纹理必须在GL线程加载,使用Gdx.app.postRunnable()确保操作在正确线程执行。
  • 图片压缩:若用户选择大尺寸图片,可在安卓端先压缩后再传递给Core,避免内存溢出。

内容的提问来源于stack exchange,提问作者Владислав Шестернин

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 16:10:33