如何在LibGdx中实现Camera功能及调用设备相机拍照?
Hey there! Let's break down your two LibGDX camera-related questions clearly—first, the virtual rendering camera you use to frame your game, and second, accessing the device's physical camera to snap photos. Let's dive in!
LibGDX uses cameras to control how your game world is viewed on screen. The most common one for 2D games is OrthographicCamera, which keeps things flat and free of perspective distortion. Here's how to set it up:
Step 1: Initialize the Camera
In your game's create() method (or wherever you initialize core components), create and configure the camera:
import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.Gdx; private OrthographicCamera gameCamera; @Override public void create() { // Option 1: Fixed viewport (e.g., 800x480, great for consistent scaling) gameCamera = new OrthographicCamera(); gameCamera.setToOrtho(false, 800, 480); // The 'false' flips the y-axis so (0,0) is the bottom-left corner (LibGDX default) // Option 2: Match the screen resolution // gameCamera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); }
Step 2: Update and Use the Camera
Every frame before drawing, you need to update the camera's matrix and tell your SpriteBatch to use it:
import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.g2d.SpriteBatch; private SpriteBatch spriteBatch; @Override public void create() { spriteBatch = new SpriteBatch(); // ... camera initialization from above } @Override public void render(float delta) { // Clear the screen first Gdx.gl.glClearColor(0f, 0f, 0f, 1f); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // Update the camera (critical if you move/zoom it) gameCamera.update(); // Tell the SpriteBatch to use the camera's projection matrix spriteBatch.setProjectionMatrix(gameCamera.combined); // Start drawing spriteBatch.begin(); // Draw your game objects here, e.g.: // mySprite.draw(spriteBatch); spriteBatch.end(); }
Bonus: Move/Zoom the Camera
To pan or zoom the camera, adjust its properties and call update():
// Move the camera right by 100 units per second gameCamera.position.x += 100 * delta; // Zoom in (values <1 zoom out, >1 zoom in) gameCamera.zoom += 0.1f; // Always call update() after changing properties! gameCamera.update();
This is platform-specific (since camera hardware varies by device), so we'll use an interface to keep your core LibGDX code clean, then implement it for Android (the most common mobile target).
Step 1: Create a Cross-Platform Interface
In your core LibGDX project, define an interface to abstract camera functionality:
public interface DeviceCameraService { void takePhoto(); void onPhotoCaptured(String photoFilePath); // Callback for when photo is ready }
Step 2: Implement the Android-Specific Camera Logic
In your Android project, create a class that handles the native camera intent and file management:
import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Environment; import androidx.core.content.FileProvider; import com.badlogic.gdx.backends.android.AndroidApplication; import java.io.File; import java.io.IOException; public class AndroidDeviceCamera implements DeviceCameraService { private final AndroidApplication app; private static final int CAMERA_REQUEST_CODE = 101; private String tempPhotoPath; public AndroidDeviceCamera(AndroidApplication app) { this.app = app; } @Override public void takePhoto() { // Create a temporary file to store the photo try { File storageDir = app.getExternalFilesDir(Environment.DIRECTORY_PICTURES); File photoFile = File.createTempFile("LibGDX_Photo_", ".jpg", storageDir); tempPhotoPath = photoFile.getAbsolutePath(); // Use FileProvider to avoid permission issues on newer Android versions Uri photoUri = FileProvider.getUriForFile( app, app.getPackageName() + ".fileprovider", photoFile ); // Launch the native camera app Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoUri); app.startActivityForResult(cameraIntent, CAMERA_REQUEST_CODE); } catch (IOException e) { e.printStackTrace(); } } // Handle the camera's result (call this from your AndroidLauncher) public void handleActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CAMERA_REQUEST_CODE && resultCode == Activity.RESULT_OK) { onPhotoCaptured(tempPhotoPath); } } @Override public void onPhotoCaptured(String photoFilePath) { // Run LibGDX-related code on the main thread com.badlogic.gdx.Gdx.app.postRunnable(() -> { // Load the photo into a Texture, for example com.badlogic.gdx.graphics.Texture photoTexture = new com.badlogic.gdx.graphics.Texture(photoFilePath); // Do something with the texture (draw it, store it, etc.) }); } }
Step 3: Set Up Permissions and FileProvider in Android
Add these permissions to your AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" android:minSdkVersion="33" /> <application> <!-- Add FileProvider to handle file URIs safely --> <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> </application>
Create a res/xml/file_paths.xml file to define where photos are stored:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="camera_photos" path="Pictures" /> </paths>
Step 4: Integrate with Your LibGDX Core
In your Android launcher, wire up the camera service and pass it to your game:
import android.content.Intent; import android.os.Bundle; import com.badlogic.gdx.backends.android.AndroidApplication; import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; public class AndroidLauncher extends AndroidApplication implements DeviceCameraService { private AndroidDeviceCamera cameraService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); cameraService = new AndroidDeviceCamera(this); // Pass the service to your game instance initialize(new MyGame(cameraService), config); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); cameraService.handleActivityResult(requestCode, resultCode, data); } @Override public void takePhoto() { cameraService.takePhoto(); } @Override public void onPhotoCaptured(String photoFilePath) { cameraService.onPhotoCaptured(photoFilePath); } }
Then in your core game class, use the service when you need to take a photo:
public class MyGame extends com.badlogic.gdx.Game { private final DeviceCameraService cameraService; public MyGame(DeviceCameraService cameraService) { this.cameraService = cameraService; } @Override public void create() { // Example: Call this when a button is pressed // cameraService.takePhoto(); } }
内容的提问来源于stack exchange,提问作者user111682

